mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-10 07:42:39 +02:00
feat: transcribe voice memos with Deepgram and save as .txt
After saving a voice memo, send the audio to Deepgram's Nova-2 STT API and write the transcript as a .txt file alongside the audio in ~/.rowboat/voice_memos/. Reads the API key from config/deepgram.json. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5c4b7ca182
commit
158d90f415
1 changed files with 44 additions and 0 deletions
|
|
@ -143,6 +143,35 @@ export function SidebarContentPanel({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function transcribeWithDeepgram(audioBlob: Blob): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
const configResult = await window.ipc.invoke('workspace:readFile', {
|
||||||
|
path: 'config/deepgram.json',
|
||||||
|
encoding: 'utf8',
|
||||||
|
})
|
||||||
|
const { api_key } = JSON.parse(configResult.data) as { api_key: string }
|
||||||
|
if (!api_key) throw new Error('No api_key in deepgram.json')
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
'https://api.deepgram.com/v1/listen?model=nova-2&smart_format=true',
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Token ${api_key}`,
|
||||||
|
'Content-Type': audioBlob.type,
|
||||||
|
},
|
||||||
|
body: audioBlob,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error(`Deepgram API error: ${response.status}`)
|
||||||
|
const result = await response.json()
|
||||||
|
return result.results?.channels?.[0]?.alternatives?.[0]?.transcript ?? null
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Voice Note Recording Button
|
// Voice Note Recording Button
|
||||||
function VoiceNoteButton() {
|
function VoiceNoteButton() {
|
||||||
const [isRecording, setIsRecording] = React.useState(false)
|
const [isRecording, setIsRecording] = React.useState(false)
|
||||||
|
|
@ -191,6 +220,21 @@ function VoiceNoteButton() {
|
||||||
toast('Voice memo saved', 'success')
|
toast('Voice memo saved', 'success')
|
||||||
} catch {
|
} catch {
|
||||||
toast('Failed to save voice memo', 'error')
|
toast('Failed to save voice memo', 'error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transcribe and save transcript alongside the audio file
|
||||||
|
const transcript = await transcribeWithDeepgram(blob)
|
||||||
|
if (transcript) {
|
||||||
|
const txtFilename = filename.replace(/\.[^.]+$/, '.txt')
|
||||||
|
await window.ipc.invoke('workspace:writeFile', {
|
||||||
|
path: `voice_memos/${txtFilename}`,
|
||||||
|
data: transcript,
|
||||||
|
opts: { encoding: 'utf8' },
|
||||||
|
})
|
||||||
|
toast('Transcription saved', 'success')
|
||||||
|
} else {
|
||||||
|
toast('Transcription failed', 'error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue