From 6d69b96409abeef171c7bb29157e7f3877632ee2 Mon Sep 17 00:00:00 2001 From: lml Date: Sun, 15 Mar 2026 22:16:25 +0800 Subject: [PATCH] feat: enhance Whisper model selection with detailed information including disk/memory usage and transcription quality. --- lib/core/constants.dart | 63 +++++++++++++++++++++--- lib/l10n/app_en.arb | 9 ++++ lib/l10n/app_localizations.dart | 54 ++++++++++++++++++++ lib/l10n/app_localizations_en.dart | 27 ++++++++++ lib/l10n/app_localizations_zh.dart | 27 ++++++++++ lib/l10n/app_zh.arb | 9 ++++ lib/ui/widgets/transcription_panel.dart | 65 +++++++++++++++++++++++-- 7 files changed, 242 insertions(+), 12 deletions(-) diff --git a/lib/core/constants.dart b/lib/core/constants.dart index 48b3e89..59fa0b1 100644 --- a/lib/core/constants.dart +++ b/lib/core/constants.dart @@ -1,17 +1,64 @@ +import 'package:caption_trans/l10n/app_localizations.dart'; + +/// Information about a Whisper model. +class WhisperModelInfo { + final String name; + final String diskUsage; + final String memoryUsage; + final String Function(AppLocalizations) quality; + + const WhisperModelInfo({ + required this.name, + required this.diskUsage, + required this.memoryUsage, + required this.quality, + }); +} + /// Application-wide constants. class AppConstants { AppConstants._(); static const String appName = 'Caption Trans'; - /// Supported Whisper models with their approximate sizes. - static const Map whisperModels = { - 'tiny': 'Tiny (~75 MB)', - 'base': 'Base (~148 MB)', - 'small': 'Small (~488 MB)', - 'medium': 'Medium (~1.5 GB)', - 'large-v3': 'Large V3 (~3 GB)', - 'large-v3-turbo': 'Large V3 Turbo (~1.6 GB)', + /// Supported Whisper models with detailed information. + static final Map whisperModels = { + 'tiny': WhisperModelInfo( + name: 'tiny', + diskUsage: '~75 MB', + memoryUsage: '~273 MB', + quality: (l) => l.qualityLow, + ), + 'base': WhisperModelInfo( + name: 'base', + diskUsage: '~142 MB', + memoryUsage: '~388 MB', + quality: (l) => l.qualityBasic, + ), + 'small': WhisperModelInfo( + name: 'small', + diskUsage: '~466 MB', + memoryUsage: '~852 MB', + quality: (l) => l.qualityGood, + ), + 'medium': WhisperModelInfo( + name: 'medium', + diskUsage: '~1.5 GB', + memoryUsage: '~2.1 GB', + quality: (l) => l.qualityExcellent, + ), + 'large-v3-turbo': WhisperModelInfo( + name: 'large-v3-turbo', + diskUsage: '~1.5 GB', + memoryUsage: '~2.0 GB', + quality: (l) => l.qualitySuperior, + ), + 'large': WhisperModelInfo( + name: 'large', + diskUsage: '~2.9 GB', + memoryUsage: '~3.9 GB', + quality: (l) => l.qualityBest, + ), }; static const String defaultWhisperModel = 'base'; diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5f7df09..15bd334 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -14,6 +14,15 @@ "clear": "Clear", "stepExtractSubtitles": "Extract Subtitles", "whisperModel": "Whisper Model", + "diskUsage": "Disk Usage", + "memoryUsage": "Memory/VRAM Usage", + "transcriptionQuality": "Transcription Quality", + "qualityLow": "Low", + "qualityBasic": "Basic", + "qualityGood": "Good", + "qualityExcellent": "Excellent", + "qualitySuperior": "Superior (Recommended)", + "qualityBest": "Best", "extract": "Extract", "downloadingModel": "Downloading model {name}...", "@downloadingModel": { diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 0487ded..f8a1f60 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -182,6 +182,60 @@ abstract class AppLocalizations { /// **'Whisper Model'** String get whisperModel; + /// No description provided for @diskUsage. + /// + /// In en, this message translates to: + /// **'Disk Usage'** + String get diskUsage; + + /// No description provided for @memoryUsage. + /// + /// In en, this message translates to: + /// **'Memory/VRAM Usage'** + String get memoryUsage; + + /// No description provided for @transcriptionQuality. + /// + /// In en, this message translates to: + /// **'Transcription Quality'** + String get transcriptionQuality; + + /// No description provided for @qualityLow. + /// + /// In en, this message translates to: + /// **'Low'** + String get qualityLow; + + /// No description provided for @qualityBasic. + /// + /// In en, this message translates to: + /// **'Basic'** + String get qualityBasic; + + /// No description provided for @qualityGood. + /// + /// In en, this message translates to: + /// **'Good'** + String get qualityGood; + + /// No description provided for @qualityExcellent. + /// + /// In en, this message translates to: + /// **'Excellent'** + String get qualityExcellent; + + /// No description provided for @qualitySuperior. + /// + /// In en, this message translates to: + /// **'Superior (Recommended)'** + String get qualitySuperior; + + /// No description provided for @qualityBest. + /// + /// In en, this message translates to: + /// **'Best'** + String get qualityBest; + /// No description provided for @extract. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 65ac65b..5052eb0 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -50,6 +50,33 @@ class AppLocalizationsEn extends AppLocalizations { @override String get whisperModel => 'Whisper Model'; + @override + String get diskUsage => 'Disk Usage'; + + @override + String get memoryUsage => 'Memory/VRAM Usage'; + + @override + String get transcriptionQuality => 'Transcription Quality'; + + @override + String get qualityLow => 'Low'; + + @override + String get qualityBasic => 'Basic'; + + @override + String get qualityGood => 'Good'; + + @override + String get qualityExcellent => 'Excellent'; + + @override + String get qualitySuperior => 'Superior (Recommended)'; + + @override + String get qualityBest => 'Best'; + @override String get extract => 'Extract'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 6bbd644..66c3f83 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -50,6 +50,33 @@ class AppLocalizationsZh extends AppLocalizations { @override String get whisperModel => 'Whisper 模型'; + @override + String get diskUsage => '磁盘占用'; + + @override + String get memoryUsage => '内存/显存占用'; + + @override + String get transcriptionQuality => '转录质量'; + + @override + String get qualityLow => '低'; + + @override + String get qualityBasic => '基础'; + + @override + String get qualityGood => '良好'; + + @override + String get qualityExcellent => '优秀'; + + @override + String get qualitySuperior => '极佳 (推荐)'; + + @override + String get qualityBest => '最好'; + @override String get extract => '提取'; diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 08ec67d..4f0ae12 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -14,6 +14,15 @@ "clear": "清除", "stepExtractSubtitles": "提取字幕", "whisperModel": "Whisper 模型", + "diskUsage": "磁盘占用", + "memoryUsage": "内存/显存占用", + "transcriptionQuality": "转录质量", + "qualityLow": "低", + "qualityBasic": "基础", + "qualityGood": "良好", + "qualityExcellent": "优秀", + "qualitySuperior": "极佳 (推荐)", + "qualityBest": "最好", "extract": "提取", "downloadingModel": "正在下载模型 {name}...", "extractingAudio": "正在从视频中提取音频...", diff --git a/lib/ui/widgets/transcription_panel.dart b/lib/ui/widgets/transcription_panel.dart index 76fddde..bf2dade 100644 --- a/lib/ui/widgets/transcription_panel.dart +++ b/lib/ui/widgets/transcription_panel.dart @@ -53,13 +53,21 @@ class TranscriptionPanel extends StatelessWidget { .map( (e) => DropdownMenuItem( value: e.key, - child: Text( - e.value, - style: const TextStyle(fontSize: 14), - ), + child: _buildModelMenuItem(context, e.value, l10n), ), ) .toList(), + selectedItemBuilder: (context) { + return AppConstants.whisperModels.entries.map((e) { + return Align( + alignment: Alignment.centerLeft, + child: Text( + e.key, + style: const TextStyle(fontSize: 14), + ), + ); + }).toList(); + }, onChanged: _isProcessing ? null : (v) { @@ -218,4 +226,53 @@ class TranscriptionPanel extends StatelessWidget { ], ); } + + Widget _buildModelMenuItem( + BuildContext context, + WhisperModelInfo info, + AppLocalizations l10n, + ) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + children: [ + SizedBox( + width: 80, + child: Text( + info.name, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ), + _buildModelSpecColumn(l10n.diskUsage, info.diskUsage), + _buildModelSpecColumn(l10n.memoryUsage, info.memoryUsage), + _buildModelSpecColumn(l10n.transcriptionQuality, info.quality(l10n)), + ], + ), + ); + } + + Widget _buildModelSpecColumn(String label, String value) { + return Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: TextStyle( + fontSize: 10, + color: Colors.white.withValues(alpha: 0.5), + ), + ), + Text( + value, + style: const TextStyle(fontSize: 12), + ), + ], + ), + ); + } }