1- import { CallbackUrl , createClient } from "@deepgram/sdk" ;
21import * as restate from "@restatedev/restate-sdk-cloudflare-workers/fetch" ;
32import { serde } from "@restatedev/restate-sdk-zod" ;
43import { z } from "zod" ;
54
5+ import {
6+ DeepgramCallback ,
7+ DeepgramCallbackType ,
8+ extractTranscript ,
9+ transcribeWithCallback ,
10+ } from "../deepgram" ;
611import { type Env } from "../env" ;
712import { createSignedUrl , deleteFile } from "../supabase" ;
813import { limiter } from "./rate-limit" ;
@@ -18,63 +23,12 @@ const SttStatus = z.enum(["QUEUED", "TRANSCRIBING", "DONE", "ERROR"]);
1823
1924export type SttStatusType = z . infer < typeof SttStatus > ;
2025
21- const DeepgramCallback = z . object ( {
22- results : z
23- . object ( {
24- channels : z
25- . array (
26- z . object ( {
27- alternatives : z
28- . array ( z . object ( { transcript : z . string ( ) } ) )
29- . optional ( ) ,
30- } ) ,
31- )
32- . optional ( ) ,
33- } )
34- . optional ( ) ,
35- channel : z
36- . object ( {
37- alternatives : z . array ( z . object ( { transcript : z . string ( ) } ) ) . optional ( ) ,
38- } )
39- . optional ( ) ,
40- } ) ;
41-
42- export type DeepgramCallbackType = z . infer < typeof DeepgramCallback > ;
43-
44- interface SttResult {
45- status : SttStatusType ;
46- transcript ?: string ;
47- error ?: string ;
48- }
49-
50- async function transcribe (
51- audioUrl : string ,
52- callbackUrl : string ,
53- apiKey : string ,
54- ) : Promise < string > {
55- const client = createClient ( apiKey ) ;
56- const { result, error } =
57- await client . listen . prerecorded . transcribeUrlCallback (
58- { url : audioUrl } ,
59- new CallbackUrl ( callbackUrl ) ,
60- { model : "nova-3" , smart_format : true } ,
61- ) ;
62-
63- if ( error ) throw new Error ( `Deepgram: ${ error . message } ` ) ;
64- if ( ! result ?. request_id ) throw new Error ( "Deepgram: missing request_id" ) ;
65-
66- return result . request_id ;
67- }
68-
6926export const sttFile = restate . workflow ( {
7027 name : "SttFile" ,
7128 handlers : {
7229 run : restate . handlers . workflow . workflow (
7330 { input : serde . zod ( SttFileInput ) } ,
74- async (
75- ctx : restate . WorkflowContext ,
76- input : SttFileInputType ,
77- ) : Promise < SttResult > => {
31+ async ( ctx : restate . WorkflowContext , input : SttFileInputType ) => {
7832 ctx . set ( "status" , "QUEUED" as SttStatusType ) ;
7933 ctx . set ( "fileId" , input . fileId ) ;
8034
@@ -95,15 +49,15 @@ export const sttFile = restate.workflow({
9549 const callbackUrl = `${ env . RESTATE_INGRESS_URL . replace ( / \/ + $ / , "" ) } /SttFile/${ encodeURIComponent ( ctx . key ) } /onTranscript` ;
9650
9751 const requestId = await ctx . run ( "transcribe" , ( ) =>
98- transcribe ( audioUrl , callbackUrl , env . DEEPGRAM_API_KEY ) ,
52+ transcribeWithCallback ( audioUrl , callbackUrl , env . DEEPGRAM_API_KEY ) ,
9953 ) ;
10054 ctx . set ( "deepgramRequestId" , requestId ) ;
10155
10256 const transcript = await ctx . promise < string > ( "transcript" ) ;
10357 ctx . set ( "transcript" , transcript ) ;
10458 ctx . set ( "status" , "DONE" as SttStatusType ) ;
10559
106- return { status : "DONE" , transcript } ;
60+ return { status : "DONE" as const , transcript } ;
10761 } catch ( err ) {
10862 const error = err instanceof Error ? err . message : "Unknown error" ;
10963 ctx . set ( "status" , "ERROR" as SttStatusType ) ;
@@ -126,18 +80,13 @@ export const sttFile = restate.workflow({
12680 const existing = await ctx . get < string > ( "transcript" ) ;
12781 if ( existing !== undefined ) return ;
12882
129- const transcript =
130- payload . results ?. channels ?. [ 0 ] ?. alternatives ?. [ 0 ] ?. transcript ??
131- payload . channel ?. alternatives ?. [ 0 ] ?. transcript ??
132- "" ;
133-
134- ctx . promise < string > ( "transcript" ) . resolve ( transcript ) ;
83+ ctx . promise < string > ( "transcript" ) . resolve ( extractTranscript ( payload ) ) ;
13584 } ,
13685 ) ,
13786
13887 getStatus : restate . handlers . workflow . shared (
13988 { } ,
140- async ( ctx : restate . WorkflowSharedContext ) : Promise < SttResult > => {
89+ async ( ctx : restate . WorkflowSharedContext ) => {
14190 const status = ( await ctx . get < SttStatusType > ( "status" ) ) ?? "QUEUED" ;
14291 const transcript = await ctx . get < string > ( "transcript" ) ;
14392 const error = await ctx . get < string > ( "error" ) ;
0 commit comments