RASMUS commited on
Commit
0626c04
·
verified ·
1 Parent(s): 5670d35

Upload webapp/src/worker.ts with huggingface_hub

Browse files
Files changed (1) hide show
  1. webapp/src/worker.ts +75 -0
webapp/src/worker.ts ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { APP_CONFIG } from './config'
2
+ import { configureOrt, createTtsSessions, ensureWebGpuSupport, fetchCondEmb, fetchTokenizerJson } from './onnx'
3
+ import { runFinnishPipeline, type TtsSessions } from './pipeline'
4
+ import { createTokenizer, type BrowserTokenizer } from './tokenizer'
5
+ import type { WorkerRequest, WorkerResponse } from './types'
6
+
7
+ let sessionsPromise: Promise<TtsSessions> | null = null
8
+ let tokenizerPromise: Promise<BrowserTokenizer> | null = null
9
+ let condEmbPromise: Promise<Float32Array> | null = null
10
+ const workerScope = self as typeof self & {
11
+ postMessage: (message: WorkerResponse, transfer?: Transferable[]) => void
12
+ onmessage: ((event: MessageEvent<WorkerRequest>) => void | Promise<void>) | null
13
+ }
14
+
15
+ function postMessageToMain(message: WorkerResponse, transfer: Transferable[] = []): void {
16
+ workerScope.postMessage(message, transfer)
17
+ }
18
+
19
+ function reportStatus(message: string): void {
20
+ postMessageToMain({ type: 'status', message })
21
+ }
22
+
23
+ async function ensureInitialized(): Promise<{
24
+ sessions: TtsSessions
25
+ tokenizer: BrowserTokenizer
26
+ condEmb: Float32Array
27
+ }> {
28
+ ensureWebGpuSupport()
29
+ configureOrt()
30
+
31
+ sessionsPromise ??= createTtsSessions(reportStatus)
32
+ tokenizerPromise ??= fetchTokenizerJson().then((json) => createTokenizer(json))
33
+ condEmbPromise ??= fetchCondEmb()
34
+
35
+ const [sessions, tokenizer, condEmb] = await Promise.all([
36
+ sessionsPromise,
37
+ tokenizerPromise,
38
+ condEmbPromise,
39
+ ])
40
+ postMessageToMain({ type: 'ready' })
41
+ return { sessions, tokenizer, condEmb }
42
+ }
43
+
44
+ async function handleSpeakRequest(message: Extract<WorkerRequest, { type: 'speak' }>): Promise<void> {
45
+ const { sessions, tokenizer, condEmb } = await ensureInitialized()
46
+ const result = await runFinnishPipeline({
47
+ sessions,
48
+ tokenizer,
49
+ condEmb,
50
+ referenceAudio: message.referenceAudio,
51
+ text: message.text,
52
+ reportStatus,
53
+ })
54
+
55
+ postMessageToMain(
56
+ {
57
+ type: 'result',
58
+ audio: result.audio,
59
+ sampleRate: APP_CONFIG.sampleRate,
60
+ speechTokenCount: result.speechTokenCount,
61
+ },
62
+ [result.audio.buffer],
63
+ )
64
+ }
65
+
66
+ workerScope.onmessage = async (event: MessageEvent<WorkerRequest>) => {
67
+ try {
68
+ if (event.data.type === 'speak') {
69
+ await handleSpeakRequest(event.data)
70
+ }
71
+ } catch (error) {
72
+ const message = error instanceof Error ? error.message : String(error)
73
+ postMessageToMain({ type: 'error', message })
74
+ }
75
+ }