feat: Implement transcription progress reporting and display preprocessing status in the UI.
This commit is contained in:
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
@@ -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": {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user