11import { error , json } from '@sveltejs/kit' ;
22import type { RequestHandler } from './$types' ;
33import { env as envPrivate } from '$env/dynamic/private' ;
4+ import { ElevenLabsClient } from 'elevenlabs' ;
45
56const CLOUDFLARE_API_URL = `https://api.cloudflare.com/client/v4/accounts/${ envPrivate . CLOUDFLARE_ACCOUNT_ID } /ai/run/@cf/openai/whisper` ;
67
@@ -16,33 +17,69 @@ export const POST: RequestHandler = async ({ request, url }) => {
1617 try {
1718 const data = await request . formData ( ) ;
1819 const audioFile = data . get ( 'audio' ) as File ;
20+ const model = data . get ( 'model' ) as string ;
1921
2022 if ( ! audioFile ) {
2123 return json ( { error : 'No audio file provided' } , { status : 400 } ) ;
2224 }
2325
24- const controller = new AbortController ( ) ;
25- const timeoutId = setTimeout ( ( ) => controller . abort ( ) , 60000 ) ;
26+ switch ( model ) {
27+ case 'openai-whisper' : {
28+ const controller = new AbortController ( ) ;
29+ const timeoutId = setTimeout ( ( ) => controller . abort ( ) , 60000 ) ;
2630
27- const response = await fetch ( CLOUDFLARE_API_URL , {
28- method : 'POST' ,
29- headers : {
30- Authorization : `Bearer ${ envPrivate . CLOUDFLARE_WORKERS_AI_API_TOKEN } ` ,
31- 'Content-Type' : 'application/octet-stream'
32- } ,
33- body : audioFile ,
34- signal : controller . signal
35- } ) ;
31+ const response = await fetch ( CLOUDFLARE_API_URL , {
32+ method : 'POST' ,
33+ headers : {
34+ Authorization : `Bearer ${ envPrivate . CLOUDFLARE_WORKERS_AI_API_TOKEN } ` ,
35+ 'Content-Type' : 'application/octet-stream'
36+ } ,
37+ body : audioFile ,
38+ signal : controller . signal
39+ } ) ;
3640
37- clearTimeout ( timeoutId ) ;
41+ clearTimeout ( timeoutId ) ;
3842
39- if ( ! response . ok ) {
40- throw new Error ( `Cloudflare API error: ${ response . statusText } ` ) ;
41- }
43+ if ( ! response . ok ) {
44+ throw new Error ( `Cloudflare API error: ${ response . statusText } ` ) ;
45+ }
46+
47+ const res = await response . json ( ) ;
48+
49+ return json ( { ...res . result } ) ;
50+ }
51+
52+ case 'elevenlabs-scribe-v1' :
53+ default : {
54+ if ( ! envPrivate . ELEVENLABS_API_KEY ) {
55+ return error ( 500 , 'ElevenLabs API key not provided' ) ;
56+ }
4257
43- const res = await response . json ( ) ;
58+ try {
59+ const client = new ElevenLabsClient ( {
60+ apiKey : envPrivate . ELEVENLABS_API_KEY
61+ } ) ;
4462
45- return json ( { ...res . result } ) ;
63+ const audioBlob = new Blob ( [ await audioFile . arrayBuffer ( ) ] , { type : audioFile . type } ) ;
64+
65+ const transcription = await client . speechToText . convert ( {
66+ file : audioBlob ,
67+ model_id : 'scribe_v1' ,
68+ tag_audio_events : true ,
69+ language_code : 'en' ,
70+ diarize : true
71+ } ) ;
72+
73+ return json ( {
74+ text : transcription . words . map ( ( { text } ) => text ) . toString ( ) ,
75+ words : transcription . words
76+ } ) ;
77+ } catch ( elevenLabsError : any ) {
78+ console . error ( 'ElevenLabs API error:' , elevenLabsError ) ;
79+ return error ( 500 , `ElevenLabs API error: ${ elevenLabsError . message } ` ) ;
80+ }
81+ }
82+ }
4683 } catch ( err : any ) {
4784 if ( err . name === 'AbortError' ) {
4885 console . error ( 'Request timed out:' , err ) ;
0 commit comments