feat: Implement transcription progress reporting and display preprocessing status in the UI.

This commit is contained in:
lml committed 2026-03-16 16:47:30 +08:00
1 parent 8b3c4395a8
commit 4e890072c5
10 files changed
+46 -26

No files matched your search

@@ -73,6 +73,16 @@ class TranscriptionBloc extends Bloc<TranscriptionEvent, TranscriptionState> {
final result = await _whisperService.transcribe(
videoPath, // Pass video file directly
language: event.language ?? 'auto',
onProgress: (progress) {
if (!emit.isDone) {
emit(Transcribing(
videoPath: videoPath,
fileName: fileName,
statusMessage: 'Transcribing...',
progress: progress,
));
}
},
);
emit(TranscriptionComplete(
@@ -19,10 +19,7 @@ class VideoSelected extends TranscriptionState {
final String videoPath;
final String fileName;
const VideoSelected({
required this.videoPath,
required this.fileName,
});
const VideoSelected({required this.videoPath, required this.fileName});
@override
List<Object?> get props => [videoPath, fileName];
@@ -51,10 +48,7 @@ class AudioExtracting extends TranscriptionState {
final String videoPath;
final String fileName;
const AudioExtracting({
required this.videoPath,
required this.fileName,
});
const AudioExtracting({required this.videoPath, required this.fileName});
@override
List<Object?> get props => [videoPath, fileName];
@@ -65,15 +59,16 @@ class Transcribing extends TranscriptionState {
final String videoPath;
final String fileName;
final String statusMessage;
final int progress;
const Transcribing({
required this.videoPath,
required this.fileName,
this.statusMessage = 'Transcribing...',
this.progress = 0,
});
@override
List<Object?> get props => [videoPath, fileName, statusMessage];
List<Object?> get props => [videoPath, fileName, statusMessage, progress];
}
/// Transcription completed successfully.
+2 -1
View File
@@ -33,7 +33,8 @@
}
},
"extractingAudio": "Extracting audio from video...",
"processingTranscription": "Whisper is processing...",
"processingTranscription": "Transcription in progress...",
"preprocessingStatus": "Preprocessing: Transcoding and silence detection...",
"segmentsExtracted": "{count} segments extracted ({lang})",
"@segmentsExtracted": {
"placeholders": {
+7 -1
View File
@@ -257,9 +257,15 @@ abstract class AppLocalizations {
/// No description provided for @processingTranscription.
///
/// In en, this message translates to:
/// **'Whisper is processing...'**
/// **'Transcription in progress...'**
String get processingTranscription;
/// No description provided for @preprocessingStatus.
///
/// In en, this message translates to:
/// **'Preprocessing: Transcoding and silence detection...'**
String get preprocessingStatus;
/// No description provided for @segmentsExtracted.
///
/// In en, this message translates to:
+5 -1
View File
@@ -89,7 +89,11 @@ class AppLocalizationsEn extends AppLocalizations {
String get extractingAudio => 'Extracting audio from video...';
@override
String get processingTranscription => 'Whisper is processing...';
String get processingTranscription => 'Transcription in progress...';
@override
String get preprocessingStatus =>
'Preprocessing: Transcoding and silence detection...';
@override
String segmentsExtracted(int count, String lang) {
+4 -1
View File
@@ -89,7 +89,10 @@ class AppLocalizationsZh extends AppLocalizations {
String get extractingAudio => '正在从视频中提取音频...';
@override
String get processingTranscription => 'Whisper 正在处理中...';
String get processingTranscription => '字幕转录中...';
@override
String get preprocessingStatus => '预处理:转码和静音检测中...';
@override
String segmentsExtracted(int count, String lang) {
+2 -1
View File
@@ -26,7 +26,8 @@
"extract": "提取",
"downloadingModel": "正在下载模型 {name}...",
"extractingAudio": "正在从视频中提取音频...",
"processingTranscription": "Whisper 正在处理中...",
"processingTranscription": "字幕转录中...",
"preprocessingStatus": "预处理:转码和静音检测中...",
"segmentsExtracted": "已提取 {count} 条字幕段 ({lang})",
"stepTranslate": "翻译",
"geminiApiKey": "API Key",
@@ -49,6 +49,7 @@ class WhisperService {
Future<TranscriptionResult> transcribe(
String mediaPath, {
String language = 'auto',
void Function(int progress)? onProgress,
}) async {
if (_currentModel == null) {
throw StateError('No model loaded. Call loadModel() first.');
@@ -60,6 +61,7 @@ class WhisperService {
lang: language,
withTimestamps: true,
convert: true, // Auto-convert via registered FFmpeg converter
onProgress: onProgress,
);
if (result == null) {
+8 -10
View File
@@ -139,11 +139,15 @@ class TranscriptionPanel extends StatelessWidget {
}
if (state is Transcribing) {
final s = state as Transcribing;
String label = s.progress > 0
? l10n.processingTranscription
: l10n.preprocessingStatus;
return _buildProgressRow(
context,
icon: Icons.mic_rounded,
label: l10n.processingTranscription,
progress: null,
label: label,
progress: s.progress > 0 ? s.progress / 100.0 : null,
color: Colors.purple,
);
}
@@ -240,10 +244,7 @@ class TranscriptionPanel extends StatelessWidget {
width: 80,
child: Text(
info.name,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 13,
),
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
),
),
_buildModelSpecColumn(l10n.diskUsage, info.diskUsage),
@@ -267,10 +268,7 @@ class TranscriptionPanel extends StatelessWidget {
color: Colors.white.withValues(alpha: 0.5),
),
),
Text(
value,
style: const TextStyle(fontSize: 12),
),
Text(value, style: const TextStyle(fontSize: 12)),
],
),
);
+1 -1
View File
@@ -880,7 +880,7 @@ packages:
description:
path: "."
ref: HEAD
resolved-ref: b57159c40d3356e51b32279c6cab12a9cb65cde3
resolved-ref: "649e41882878f2d04d3b087d907161fdb7a2681b"
url: "https://github.com/cddqssc/whisper_ggml_plus.git"
source: git
version: "1.4.1"