From ee4982d61eb72c06a99595c399b109e6943ab76d Mon Sep 17 00:00:00 2001 From: dadukhankevin Date: Thu, 19 Feb 2026 19:02:33 -0600 Subject: [PATCH 1/3] feat: improve transcription with language hints and batch UX (#647) - Pass language code (lang param) to ASR endpoint for better transcription quality - Include language in getAsrConfig response from extension to webview - Add "Transcribe All" button alongside per-cell "Transcribe" to encourage batching - Reuse single WhisperTranscriptionClient across batch to leverage warmed Modal container - Default batch command to "all untranscribed cells" instead of requiring count - Show cold-start warning (~45s) in transcription info messages - Save actual language code instead of "unknown" in transcription metadata Co-Authored-By: Claude Opus 4.6 --- src/extension.ts | 19 ++++++---- .../codexCellEditorMessagehandling.ts | 18 ++++++++-- .../AudioWaveformWithTranscription.tsx | 36 +++++++++++++------ .../src/CodexCellEditor/CodexCellEditor.tsx | 15 ++++---- .../src/CodexCellEditor/TextCellEditor.tsx | 15 ++++++-- .../WhisperTranscriptionClient.ts | 6 +++- 6 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 2baf9308f..4c7e48260 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -802,12 +802,16 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.commands.registerCommand("codex-editor-extension.generateTranscriptions", async () => { const countInput = await vscode.window.showInputBox({ - prompt: "How many cells to transcribe?", - placeHolder: "e.g., 5", - validateInput: (val) => (val && !isNaN(Number(val)) && Number(val) >= 1 ? undefined : "Enter a positive number"), + prompt: "How many cells to transcribe? (0 or blank = all untranscribed cells)", + placeHolder: "0 for all, or a specific number", + value: "0", + validateInput: (val) => { + if (!val || val.trim() === "") return undefined; + return !isNaN(Number(val)) && Number(val) >= 0 ? undefined : "Enter 0 for all, or a positive number"; + }, }); - if (!countInput) return; - const count = Math.max(1, Math.floor(Number(countInput))); + if (countInput === undefined) return; // user cancelled + const count = Math.max(0, Math.floor(Number(countInput || 0))); const provider = GlobalProvider.getInstance().getProvider("codex-cell-editor") as CodexCellEditorProvider | undefined; if (!provider) { @@ -816,7 +820,10 @@ export async function activate(context: vscode.ExtensionContext) { } provider.postMessageToWebviews({ type: "startBatchTranscription", content: { count } } as any); - vscode.window.showInformationMessage(`Starting transcription for up to ${count} cells...`); + const label = count > 0 ? `up to ${count}` : "all untranscribed"; + vscode.window.showInformationMessage( + `Starting transcription for ${label} cells... First request may take ~45s to warm up.` + ); }) ); diff --git a/src/providers/codexCellEditorProvider/codexCellEditorMessagehandling.ts b/src/providers/codexCellEditorProvider/codexCellEditorMessagehandling.ts index faa2f68d0..ef34910f4 100644 --- a/src/providers/codexCellEditorProvider/codexCellEditorMessagehandling.ts +++ b/src/providers/codexCellEditorProvider/codexCellEditorMessagehandling.ts @@ -394,10 +394,11 @@ const messageHandlers: Record Promise("asrLanguage", "eng"); + debug(`[getAsrConfig] Sending config: endpoint=${endpoint}, hasToken=${!!authToken}, language=${language}`); safePostMessageToPanel(webviewPanel, { type: "asrConfig", - content: { endpoint, authToken } + content: { endpoint, authToken, language } }); } catch (error) { console.error("Error sending ASR config:", error); @@ -417,6 +418,19 @@ const messageHandlers: Record Promise { + const count = (event as any).content?.count ?? 0; + // Forward to the webview as a startBatchTranscription message + safePostMessageToPanel(webviewPanel, { + type: "startBatchTranscription", + content: { count }, + } as any); + const label = count > 0 ? `up to ${count}` : "all untranscribed"; + vscode.window.showInformationMessage( + `Starting transcription for ${label} cells... First request may take ~45s to warm up.` + ); + }, + updateCellAfterTranscription: async ({ event, document, webviewPanel, provider }) => { const typedEvent = event as Extract; const { cellId, transcribedText, language } = typedEvent.content; diff --git a/webviews/codex-webviews/src/CodexCellEditor/AudioWaveformWithTranscription.tsx b/webviews/codex-webviews/src/CodexCellEditor/AudioWaveformWithTranscription.tsx index e658762c4..47978831f 100644 --- a/webviews/codex-webviews/src/CodexCellEditor/AudioWaveformWithTranscription.tsx +++ b/webviews/codex-webviews/src/CodexCellEditor/AudioWaveformWithTranscription.tsx @@ -33,6 +33,7 @@ interface AudioWaveformWithTranscriptionProps { isTranscribing: boolean; transcriptionProgress: number; onTranscribe: () => void; + onTranscribeAll?: () => void; onInsertTranscription: () => void; disabled?: boolean; onRequestRemove?: () => void; @@ -50,6 +51,7 @@ const AudioWaveformWithTranscription: React.FC {!transcription && !isTranscribing && ( - + <> + + {onTranscribeAll && ( + + )} + )}