Skip to content

Commit 23fbb65

Browse files
author
Aleksander Grygier
committed
feat: Transcribe after saving
1 parent 6593152 commit 23fbb65

File tree

7 files changed

+527
-91
lines changed

7 files changed

+527
-91
lines changed

apps/web/src/lib/components/Recorder.svelte

Lines changed: 25 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<script lang="ts">
22
import { browser } from '$app/environment';
3-
import { invalidate } from '$app/navigation';
4-
import { page } from '$app/stores';
53
import { onMount } from 'svelte';
64
import WaveSurfer from 'wavesurfer.js';
75
import RecordPlugin from 'wavesurfer.js/dist/plugins/record.esm.js';
@@ -13,18 +11,29 @@
1311
import ButtonStop from './ButtonStop.svelte';
1412
1513
interface RecorderProps {
14+
deleteRecording: () => void;
15+
recordingBlob?: Blob | MediaSource;
16+
recordingFileName?: string;
17+
recordingUrl?: string;
18+
saveRecording: () => void;
1619
scrollingWaveform?: boolean;
1720
}
1821
19-
let { scrollingWaveform = true }: RecorderProps = $props();
22+
let {
23+
deleteRecording,
24+
recordingBlob = $bindable(),
25+
recordingFileName = $bindable(''),
26+
recordingUrl = $bindable(''),
27+
saveRecording,
28+
scrollingWaveform = true
29+
}: RecorderProps = $props();
2030
2131
let defaultDeviceId: string | undefined = $state(undefined);
2232
let isPaused = $state(false);
2333
let isRecording = $state(false);
2434
let isStopped = $state(false);
2535
let progress = $state('00:00');
2636
let record: RecordPlugin = $state({} as RecordPlugin);
27-
let recordingUrl = $state('');
2837
let progressColor = $state(
2938
browser && window.matchMedia('(prefers-color-scheme: dark)').matches
3039
? '#ffffff'
@@ -75,15 +84,22 @@
7584
});
7685
}
7786
78-
async function deleteRecording() {
87+
async function handleDeleteRecording() {
7988
if (recordingUrl) {
80-
URL.revokeObjectURL(recordingUrl);
81-
recordingUrl = '';
89+
deleteRecording();
90+
8291
progress = '00:00';
8392
wavesurfer.empty();
8493
}
8594
}
8695
96+
async function handleSaveRecording() {
97+
saveRecording();
98+
99+
progress = '00:00';
100+
wavesurfer.empty();
101+
}
102+
87103
async function startPlayback() {
88104
wavesurfer.playPause();
89105
}
@@ -135,79 +151,6 @@
135151
}
136152
}
137153
138-
async function saveRecording() {
139-
if (recordingUrl) {
140-
const fileName = `${new Date().toISOString()}-${crypto.randomUUID()}.webm`;
141-
const response = await fetch(recordingUrl);
142-
const blob = await response.blob();
143-
const userId = $page.data.user?.id;
144-
145-
if (!userId) {
146-
alert('You must be logged in to save recordings');
147-
return;
148-
}
149-
150-
const { error: uploadError } = await $page.data.supabase.storage
151-
.from('user_recordings_audio_files')
152-
.upload(`${userId}/${fileName}`, blob, {
153-
contentType: 'audio/webm'
154-
});
155-
156-
if (uploadError) {
157-
console.error('Error uploading file:', uploadError.message);
158-
return;
159-
}
160-
161-
const transcriptionResult = await getTranscriptionFromBackend(blob);
162-
const transcription = transcriptionResult ? transcriptionResult.text : '';
163-
164-
const { error: insertError } = await $page.data.supabase.from('user_recordings').insert([
165-
{
166-
id: crypto.randomUUID(),
167-
created_at: new Date().toISOString(),
168-
user_id: userId,
169-
audio_file_name: fileName,
170-
transcription: transcription
171-
}
172-
]);
173-
174-
if (insertError) {
175-
console.error('Error inserting record into database:', insertError.message);
176-
return;
177-
}
178-
179-
progress = '00:00';
180-
recordingUrl = '';
181-
wavesurfer.empty();
182-
183-
await invalidate('get_user_recordings');
184-
}
185-
}
186-
187-
async function getTranscriptionFromBackend(audioBlob: Blob): Promise<{ text: string } | null> {
188-
try {
189-
const formData = new FormData();
190-
const newBlob = new Blob([audioBlob], { type: 'audio/webm' });
191-
formData.append('audio', newBlob, 'audio.webm');
192-
193-
const response = await fetch('/api/transcribe', {
194-
method: 'POST',
195-
body: formData
196-
});
197-
198-
if (!response.ok) {
199-
throw new Error('Error in transcription request');
200-
}
201-
202-
const result = await response.json();
203-
204-
return result;
205-
} catch (error) {
206-
console.error('Error fetching transcription:', error);
207-
return null;
208-
}
209-
}
210-
211154
function updateProgress(time: number) {
212155
const formattedTime = [
213156
Math.floor((time % 3600000) / 60000), // minutes
@@ -252,9 +195,9 @@
252195
</div>
253196

254197
<div class="recording-actions">
255-
<Button label="Save & transcribe recording" onclick={saveRecording} />
198+
<Button label="Save recording" onclick={handleSaveRecording} />
256199

257-
<Button kind="danger" label="Delete recording" onclick={deleteRecording} />
200+
<Button kind="danger" label="Delete recording" onclick={handleDeleteRecording} />
258201
</div>
259202
{:else}
260203
<ButtonRecord onclick={startRecording} />

0 commit comments

Comments
 (0)