@remotion/whisper-webgpu 4.0.527 → 4.0.529

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ import { type WhisperWebGpuModel } from './models';
2
+ export type WhisperModelDownloadProgress = {
3
+ file: string | null;
4
+ progress: number;
5
+ loadedBytes: number;
6
+ totalBytes: number;
7
+ };
8
+ export type DownloadWhisperModelOptions = {
9
+ model: WhisperWebGpuModel;
10
+ onProgress?: (progress: WhisperModelDownloadProgress) => void;
11
+ signal?: AbortSignal;
12
+ };
13
+ export type DownloadWhisperModelResult = {
14
+ alreadyDownloaded: boolean;
15
+ };
16
+ export declare const downloadWhisperModel: ({ model, onProgress, signal, }: DownloadWhisperModelOptions) => Promise<DownloadWhisperModelResult>;
@@ -14,6 +14,16 @@ var __toESM = (mod, isNodeMode, target) => {
14
14
  });
15
15
  return to;
16
16
  };
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, {
20
+ get: all[name],
21
+ enumerable: true,
22
+ configurable: true,
23
+ set: (newValue) => all[name] = () => newValue
24
+ });
25
+ };
26
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
27
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
18
28
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
19
29
  }) : x)(function(x) {
@@ -22,6 +32,159 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
22
32
  throw Error('Dynamic require of "' + x + '" is not supported');
23
33
  });
24
34
 
35
+ // src/import-node-module.ts
36
+ var importNodeModule = (specifier) => {
37
+ const dynamicImport = new Function("specifier", "return import(specifier)");
38
+ return dynamicImport(specifier);
39
+ };
40
+
41
+ // src/probe-node-webgpu.ts
42
+ var exports_probe_node_webgpu = {};
43
+ __export(exports_probe_node_webgpu, {
44
+ probeNodeWebGpu: () => probeNodeWebGpu
45
+ });
46
+ var webGpuProbeModel, probeNodeWebGpu = async () => {
47
+ const { InferenceSession } = await importNodeModule("onnxruntime-node");
48
+ const session = await InferenceSession.create(webGpuProbeModel, {
49
+ executionProviders: ["webgpu"]
50
+ });
51
+ await session.release();
52
+ };
53
+ var init_probe_node_webgpu = __esm(() => {
54
+ webGpuProbeModel = new Uint8Array([
55
+ 8,
56
+ 3,
57
+ 18,
58
+ 6,
59
+ 99,
60
+ 104,
61
+ 101,
62
+ 110,
63
+ 116,
64
+ 97,
65
+ 58,
66
+ 112,
67
+ 10,
68
+ 21,
69
+ 10,
70
+ 1,
71
+ 88,
72
+ 10,
73
+ 1,
74
+ 87,
75
+ 18,
76
+ 1,
77
+ 89,
78
+ 26,
79
+ 5,
80
+ 109,
81
+ 117,
82
+ 108,
83
+ 95,
84
+ 49,
85
+ 34,
86
+ 3,
87
+ 77,
88
+ 117,
89
+ 108,
90
+ 18,
91
+ 8,
92
+ 109,
93
+ 117,
94
+ 108,
95
+ 32,
96
+ 116,
97
+ 101,
98
+ 115,
99
+ 116,
100
+ 42,
101
+ 35,
102
+ 8,
103
+ 3,
104
+ 8,
105
+ 2,
106
+ 16,
107
+ 1,
108
+ 34,
109
+ 24,
110
+ 0,
111
+ 0,
112
+ 128,
113
+ 63,
114
+ 0,
115
+ 0,
116
+ 0,
117
+ 64,
118
+ 0,
119
+ 0,
120
+ 64,
121
+ 64,
122
+ 0,
123
+ 0,
124
+ 128,
125
+ 64,
126
+ 0,
127
+ 0,
128
+ 160,
129
+ 64,
130
+ 0,
131
+ 0,
132
+ 192,
133
+ 64,
134
+ 66,
135
+ 1,
136
+ 87,
137
+ 90,
138
+ 19,
139
+ 10,
140
+ 1,
141
+ 88,
142
+ 18,
143
+ 14,
144
+ 10,
145
+ 12,
146
+ 8,
147
+ 1,
148
+ 18,
149
+ 8,
150
+ 10,
151
+ 2,
152
+ 8,
153
+ 3,
154
+ 10,
155
+ 2,
156
+ 8,
157
+ 2,
158
+ 98,
159
+ 19,
160
+ 10,
161
+ 1,
162
+ 89,
163
+ 18,
164
+ 14,
165
+ 10,
166
+ 12,
167
+ 8,
168
+ 1,
169
+ 18,
170
+ 8,
171
+ 10,
172
+ 2,
173
+ 8,
174
+ 3,
175
+ 10,
176
+ 2,
177
+ 8,
178
+ 2,
179
+ 66,
180
+ 4,
181
+ 10,
182
+ 0,
183
+ 16,
184
+ 7
185
+ ]);
186
+ });
187
+
25
188
  // src/can-use-whisper-webgpu.ts
26
189
  var WhisperWebGpuUnsupportedReason;
27
190
  ((WhisperWebGpuUnsupportedReason2) => {
@@ -31,10 +194,24 @@ var WhisperWebGpuUnsupportedReason;
31
194
  })(WhisperWebGpuUnsupportedReason ||= {});
32
195
  var canUseWhisperWebGpu = async () => {
33
196
  if (typeof window === "undefined") {
197
+ if (typeof process !== "undefined" && process.release?.name === "node") {
198
+ try {
199
+ const { probeNodeWebGpu: probeNodeWebGpu2 } = await Promise.resolve().then(() => (init_probe_node_webgpu(), exports_probe_node_webgpu));
200
+ await probeNodeWebGpu2();
201
+ return { supported: true };
202
+ } catch (error) {
203
+ const message = error instanceof Error ? error.message : String(error);
204
+ return {
205
+ supported: false,
206
+ reason: "webgpu-unavailable" /* WebGpuUnavailable */,
207
+ detailedReason: `ONNX Runtime could not initialize WebGPU: ${message}`
208
+ };
209
+ }
210
+ }
34
211
  return {
35
212
  supported: false,
36
213
  reason: "window-undefined" /* WindowUndefined */,
37
- detailedReason: "`window` is not defined. @remotion/whisper-webgpu is intended for browser environments."
214
+ detailedReason: "WebGPU is not available in this environment."
38
215
  };
39
216
  }
40
217
  if (typeof navigator === "undefined" || !("gpu" in navigator)) {
@@ -253,6 +430,140 @@ var withRemotionModelHost = async (operation) => {
253
430
  }
254
431
  };
255
432
 
433
+ // src/download-whisper-model.ts
434
+ var downloadWhisperModel = async ({
435
+ model,
436
+ onProgress,
437
+ signal
438
+ }) => {
439
+ signal?.throwIfAborted();
440
+ const totalBytes = getModelInfo(model).webGpuDownloadSize;
441
+ const hostedModelId = getHostedModelId(model);
442
+ const result = await withRemotionModelHost(async ({ env, ModelRegistry }) => {
443
+ signal?.throwIfAborted();
444
+ const cache = env.useCustomCache ? env.customCache : env.useBrowserCache && typeof caches !== "undefined" ? await caches.open(env.cacheKey) : null;
445
+ const useFileCache = cache === null && env.useFSCache;
446
+ if (cache === null && !useFileCache) {
447
+ throw new Error("A Transformers.js model cache is required to download a Whisper model.");
448
+ }
449
+ const registryOptions = {
450
+ device: "webgpu",
451
+ dtype: getWhisperWebGpuDtype(model)
452
+ };
453
+ const cacheStatus = await ModelRegistry.is_pipeline_cached_files("automatic-speech-recognition", hostedModelId, registryOptions);
454
+ signal?.throwIfAborted();
455
+ if (cacheStatus.allCached) {
456
+ onProgress?.({
457
+ file: null,
458
+ progress: 1,
459
+ loadedBytes: totalBytes,
460
+ totalBytes
461
+ });
462
+ return { alreadyDownloaded: true };
463
+ }
464
+ let loadedBytes = 0;
465
+ const emitProgress = (file) => {
466
+ onProgress?.({
467
+ file,
468
+ progress: Math.min(loadedBytes / totalBytes, 0.99),
469
+ loadedBytes,
470
+ totalBytes
471
+ });
472
+ };
473
+ emitProgress(null);
474
+ for (const { file, cached } of cacheStatus.files) {
475
+ signal?.throwIfAborted();
476
+ if (cached) {
477
+ continue;
478
+ }
479
+ const url = `${env.remoteHost}${env.remotePathTemplate.replace("{model}", hostedModelId)}${file}`;
480
+ const cacheKey = cache === null ? `${hostedModelId}/${file}` : url;
481
+ const response = await env.fetch(url, { signal });
482
+ if (!response.ok || response.body === null) {
483
+ throw new Error(`Could not download ${url}: HTTP ${response.status}.`);
484
+ }
485
+ const reader = response.body.getReader();
486
+ try {
487
+ if (cache !== null) {
488
+ const stream = new ReadableStream({
489
+ async pull(controller) {
490
+ try {
491
+ signal?.throwIfAborted();
492
+ const { done, value } = await reader.read();
493
+ signal?.throwIfAborted();
494
+ if (done) {
495
+ controller.close();
496
+ return;
497
+ }
498
+ loadedBytes += value.byteLength;
499
+ emitProgress(file);
500
+ signal?.throwIfAborted();
501
+ controller.enqueue(value);
502
+ } catch (error) {
503
+ controller.error(error);
504
+ }
505
+ },
506
+ cancel: () => reader.cancel()
507
+ });
508
+ await cache.put(cacheKey, new Response(stream, { headers: response.headers }));
509
+ } else {
510
+ const [{ mkdir, open, rename, unlink }, { join, dirname }, { randomUUID }] = await Promise.all([
511
+ importNodeModule("node:fs/promises"),
512
+ importNodeModule("node:path"),
513
+ importNodeModule("node:crypto")
514
+ ]);
515
+ if (env.cacheDir === null) {
516
+ throw new Error("Transformers.js env.cacheDir must be set.");
517
+ }
518
+ const destination = join(env.cacheDir, cacheKey);
519
+ const temporary = `${destination}.tmp.${randomUUID()}`;
520
+ await mkdir(dirname(destination), { recursive: true });
521
+ const handle = await open(temporary, "wx");
522
+ try {
523
+ while (true) {
524
+ signal?.throwIfAborted();
525
+ const { done, value } = await reader.read();
526
+ signal?.throwIfAborted();
527
+ if (done) {
528
+ break;
529
+ }
530
+ await handle.writeFile(value);
531
+ loadedBytes += value.byteLength;
532
+ emitProgress(file);
533
+ }
534
+ await handle.close();
535
+ signal?.throwIfAborted();
536
+ await rename(temporary, destination);
537
+ } catch (error) {
538
+ await handle.close();
539
+ await unlink(temporary);
540
+ throw error;
541
+ }
542
+ }
543
+ } finally {
544
+ await reader.cancel().catch(() => {});
545
+ reader.releaseLock();
546
+ }
547
+ }
548
+ signal?.throwIfAborted();
549
+ if (!await ModelRegistry.is_pipeline_cached("automatic-speech-recognition", hostedModelId, registryOptions)) {
550
+ throw new Error(`The Whisper model "${model}" was not fully cached.`);
551
+ }
552
+ signal?.throwIfAborted();
553
+ onProgress?.({
554
+ file: null,
555
+ progress: 1,
556
+ loadedBytes: totalBytes,
557
+ totalBytes
558
+ });
559
+ return { alreadyDownloaded: false };
560
+ }).catch((error) => {
561
+ signal?.throwIfAborted();
562
+ throw error;
563
+ });
564
+ signal?.throwIfAborted();
565
+ return result;
566
+ };
256
567
  // src/is-whisper-model-cached.ts
257
568
  var isWhisperModelCached = ({
258
569
  model
@@ -264,14 +575,22 @@ var isWhisperModelCached = ({
264
575
  });
265
576
  });
266
577
  };
578
+ // src/symbol-async-dispose.ts
579
+ if (typeof Symbol.asyncDispose !== "symbol") {
580
+ Object.defineProperty(Symbol, "asyncDispose", {
581
+ value: Symbol.for("asyncDispose")
582
+ });
583
+ }
584
+
267
585
  // src/load-whisper-model.ts
268
586
  var pipelines = new Map;
269
587
  var getOrCreateWhisperPipeline = ({
270
588
  model,
271
589
  onProgress
272
590
  }) => {
273
- const modelInfo = getModelInfo(model);
274
- const totalBytes = modelInfo.webGpuDownloadSize;
591
+ if (!getModelInfo(model)) {
592
+ throw new Error(`Unsupported Whisper model "${model}".`);
593
+ }
275
594
  const existing = pipelines.get(model);
276
595
  if (existing) {
277
596
  if (onProgress) {
@@ -299,7 +618,8 @@ var getOrCreateWhisperPipeline = ({
299
618
  activeTranscriptions: 0,
300
619
  onIdle: [],
301
620
  progressListeners,
302
- latestProgress: null
621
+ latestProgress: null,
622
+ retainedLoadHandles: 0
303
623
  };
304
624
  const emitProgress = (progress) => {
305
625
  state.latestProgress = progress;
@@ -308,43 +628,30 @@ var getOrCreateWhisperPipeline = ({
308
628
  }
309
629
  };
310
630
  const loading = Promise.resolve().then(() => {
311
- return withRemotionModelHost(({ pipeline }) => {
631
+ return withRemotionModelHost(async ({ ModelRegistry, pipeline }) => {
632
+ const hostedModelId = getHostedModelId(model);
633
+ if (!await ModelRegistry.is_pipeline_cached("automatic-speech-recognition", hostedModelId, { device: "webgpu", dtype: getWhisperWebGpuDtype(model) })) {
634
+ throw new Error(`The Whisper model "${model}" is not downloaded. Call downloadWhisperModel() first.`);
635
+ }
312
636
  emitProgress({
313
- status: "loading",
637
+ status: "initializing",
314
638
  file: null,
315
- progress: 0,
316
- loadedBytes: 0,
317
- totalBytes
639
+ progress: null,
640
+ loadedBytes: null,
641
+ totalBytes: null
318
642
  });
319
- const hostedModelId = getHostedModelId(model);
320
- const loadedByFile = new Map;
321
- let lastProgress = 0;
322
- let lastLoadedBytes = 0;
323
643
  return pipeline("automatic-speech-recognition", hostedModelId, {
324
644
  device: "webgpu",
325
645
  dtype: getWhisperWebGpuDtype(model),
326
646
  progress_callback: (event) => {
327
647
  const record = event;
328
- if (record.status === "progress" && typeof record.file === "string" && typeof record.loaded === "number" && Number.isFinite(record.loaded)) {
329
- loadedByFile.set(record.file, Math.max(loadedByFile.get(record.file) ?? 0, record.loaded));
330
- const loadedBytes = [...loadedByFile.values()].reduce((sum, loaded) => sum + loaded, 0);
331
- lastProgress = Math.max(lastProgress, Math.min(loadedBytes / totalBytes, 0.99));
332
- lastLoadedBytes = Math.max(lastLoadedBytes, loadedBytes);
333
- emitProgress({
334
- status: "loading",
335
- file: null,
336
- progress: lastProgress,
337
- loadedBytes: lastLoadedBytes,
338
- totalBytes
339
- });
340
- }
341
648
  if (record.status === "ready") {
342
649
  emitProgress({
343
650
  status: "ready",
344
651
  file: null,
345
652
  progress: 1,
346
- loadedBytes: Math.max(lastLoadedBytes, totalBytes),
347
- totalBytes
653
+ loadedBytes: null,
654
+ totalBytes: null
348
655
  });
349
656
  }
350
657
  }
@@ -368,26 +675,77 @@ var getOrCreateWhisperPipeline = ({
368
675
  }
369
676
  };
370
677
  };
678
+ var disposeWhisperPipelineState = async ({
679
+ model,
680
+ state
681
+ }) => {
682
+ if (pipelines.get(model) !== state) {
683
+ return;
684
+ }
685
+ pipelines.delete(model);
686
+ const loadedPipeline = await state.loading;
687
+ if (state.activeTranscriptions > 0) {
688
+ await new Promise((resolve) => {
689
+ state.onIdle.push(resolve);
690
+ });
691
+ }
692
+ await loadedPipeline.dispose();
693
+ };
371
694
  var loadWhisperModel = async ({
372
695
  model,
373
- onProgress
696
+ onProgress,
697
+ signal
374
698
  }) => {
699
+ signal?.throwIfAborted();
375
700
  const { state, alreadyLoaded, unsubscribe } = getOrCreateWhisperPipeline({
376
701
  model,
377
- onProgress
702
+ onProgress: (progress) => {
703
+ if (!signal?.aborted) {
704
+ onProgress?.(progress);
705
+ }
706
+ }
378
707
  });
708
+ state.retainedLoadHandles++;
379
709
  try {
380
710
  await state.loading;
711
+ signal?.throwIfAborted();
712
+ } catch (error) {
713
+ state.retainedLoadHandles--;
714
+ if (state.retainedLoadHandles === 0 && state.activeTranscriptions === 0) {
715
+ await disposeWhisperPipelineState({ model, state }).catch((disposeError) => {
716
+ signal?.throwIfAborted();
717
+ throw disposeError;
718
+ });
719
+ }
720
+ signal?.throwIfAborted();
721
+ throw error;
381
722
  } finally {
382
723
  unsubscribe();
383
724
  }
384
- return { alreadyLoaded };
725
+ let released = false;
726
+ const result = { alreadyLoaded };
727
+ Object.defineProperty(result, Symbol.asyncDispose, {
728
+ enumerable: false,
729
+ value: async () => {
730
+ if (released) {
731
+ return;
732
+ }
733
+ released = true;
734
+ state.retainedLoadHandles--;
735
+ if (state.retainedLoadHandles === 0) {
736
+ await disposeWhisperPipelineState({ model, state });
737
+ }
738
+ }
739
+ });
740
+ return result;
385
741
  };
386
742
  var withLoadedWhisperPipeline = async ({
387
743
  model,
388
744
  onProgress,
745
+ signal,
389
746
  run
390
747
  }) => {
748
+ signal?.throwIfAborted();
391
749
  const { state, unsubscribe } = getOrCreateWhisperPipeline({
392
750
  model,
393
751
  onProgress
@@ -396,7 +754,11 @@ var withLoadedWhisperPipeline = async ({
396
754
  try {
397
755
  const loaded = await state.loading;
398
756
  unsubscribe();
757
+ signal?.throwIfAborted();
399
758
  return await run(loaded);
759
+ } catch (error) {
760
+ signal?.throwIfAborted();
761
+ throw error;
400
762
  } finally {
401
763
  unsubscribe();
402
764
  state.activeTranscriptions--;
@@ -404,6 +766,11 @@ var withLoadedWhisperPipeline = async ({
404
766
  for (const resolve of state.onIdle.splice(0)) {
405
767
  resolve();
406
768
  }
769
+ if (signal?.aborted && state.retainedLoadHandles === 0) {
770
+ await disposeWhisperPipelineState({ model, state }).catch(() => {
771
+ signal.throwIfAborted();
772
+ });
773
+ }
407
774
  }
408
775
  }
409
776
  };
@@ -413,19 +780,8 @@ var disposeWhisperModel = async ({
413
780
  const matching = [...pipelines.entries()].filter(([loadedModel]) => {
414
781
  return model === undefined || loadedModel === model;
415
782
  });
416
- for (const [key, state] of matching) {
417
- if (pipelines.get(key) === state) {
418
- pipelines.delete(key);
419
- }
420
- }
421
- await Promise.all(matching.map(async ([, state]) => {
422
- const loadedPipeline = await state.loading;
423
- if (state.activeTranscriptions > 0) {
424
- await new Promise((resolve) => {
425
- state.onIdle.push(resolve);
426
- });
427
- }
428
- await loadedPipeline.dispose();
783
+ await Promise.all(matching.map(([key, state]) => {
784
+ return disposeWhisperPipelineState({ model: key, state });
429
785
  }));
430
786
  };
431
787
  // src/remove-whisper-model.ts
@@ -497,8 +853,10 @@ var transcribe = async ({
497
853
  topK = 50,
498
854
  repetitionPenalty = 1,
499
855
  noRepeatNgramSize = 0,
500
- onModelLoadProgress
856
+ onModelLoadProgress,
857
+ signal
501
858
  }) => {
859
+ signal?.throwIfAborted();
502
860
  if (channelWaveform.length === 0) {
503
861
  throw new Error("The audio waveform is empty.");
504
862
  }
@@ -542,7 +900,22 @@ var transcribe = async ({
542
900
  const output = await withLoadedWhisperPipeline({
543
901
  model,
544
902
  onProgress: onModelLoadProgress,
903
+ signal: signal ?? null,
545
904
  run: async (transcriber) => {
905
+ let logitsProcessor = null;
906
+ if (signal) {
907
+ const { LogitsProcessor, LogitsProcessorList } = await import("@huggingface/transformers");
908
+
909
+ class AbortLogitsProcessor extends LogitsProcessor {
910
+ _call(_inputIds, logits) {
911
+ signal?.throwIfAborted();
912
+ return logits;
913
+ }
914
+ }
915
+ logitsProcessor = new LogitsProcessorList;
916
+ logitsProcessor.push(new AbortLogitsProcessor);
917
+ }
918
+ signal?.throwIfAborted();
546
919
  return await transcriber(channelWaveform, {
547
920
  return_timestamps: "word",
548
921
  chunk_length_s: chunkLengthInSeconds,
@@ -553,10 +926,12 @@ var transcribe = async ({
553
926
  top_k: topK,
554
927
  repetition_penalty: repetitionPenalty,
555
928
  no_repeat_ngram_size: noRepeatNgramSize,
929
+ ...logitsProcessor ? { logits_processor: logitsProcessor } : {},
556
930
  ...multilingual ? { language, task } : {}
557
931
  });
558
932
  }
559
933
  });
934
+ signal?.throwIfAborted();
560
935
  if (!output.chunks) {
561
936
  throw new Error("The model did not return word-level timestamps. Use one of the timestamped models returned by getAvailableModels().");
562
937
  }
@@ -594,6 +969,7 @@ export {
594
969
  loadWhisperModel,
595
970
  isWhisperModelCached,
596
971
  getAvailableModels,
972
+ downloadWhisperModel,
597
973
  disposeWhisperModel,
598
974
  clearStaleModels,
599
975
  canUseWhisperWebGpu,
@@ -0,0 +1 @@
1
+ export declare const importNodeModule: <T>(specifier: string) => Promise<T>;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { WhisperWebGpuUnsupportedReason, canUseWhisperWebGpu, } from './can-use-whisper-webgpu';
2
2
  export type { CanUseWhisperWebGpuResult } from './can-use-whisper-webgpu';
3
3
  export { clearStaleModels } from './clear-stale-models';
4
+ export { downloadWhisperModel } from './download-whisper-model';
5
+ export type { DownloadWhisperModelOptions, DownloadWhisperModelResult, WhisperModelDownloadProgress, } from './download-whisper-model';
4
6
  export { isWhisperModelCached } from './is-whisper-model-cached';
5
7
  export type { IsWhisperModelCachedOptions } from './is-whisper-model-cached';
6
8
  export { disposeWhisperModel, loadWhisperModel } from './load-whisper-model';
@@ -1,3 +1,4 @@
1
+ import './symbol-async-dispose';
1
2
  import { type WhisperWebGpuModel } from './models';
2
3
  export type WhisperWebGpuModelLoadProgress = {
3
4
  status: string;
@@ -14,14 +15,16 @@ type LoadedWhisperPipeline = {
14
15
  export type LoadWhisperModelOptions = {
15
16
  model: WhisperWebGpuModel;
16
17
  onProgress?: OnWhisperWebGpuModelLoadProgress;
18
+ signal?: AbortSignal;
17
19
  };
18
- export type LoadWhisperModelResult = {
20
+ export type LoadWhisperModelResult = AsyncDisposable & {
19
21
  alreadyLoaded: boolean;
20
22
  };
21
- export declare const loadWhisperModel: ({ model, onProgress, }: LoadWhisperModelOptions) => Promise<LoadWhisperModelResult>;
22
- export declare const withLoadedWhisperPipeline: <ReturnValue>({ model, onProgress, run, }: {
23
+ export declare const loadWhisperModel: ({ model, onProgress, signal, }: LoadWhisperModelOptions) => Promise<LoadWhisperModelResult>;
24
+ export declare const withLoadedWhisperPipeline: <ReturnValue>({ model, onProgress, signal, run, }: {
23
25
  model: "base" | "base.en" | "large-v3-turbo" | "medium" | "medium.en" | "small" | "small.en" | "tiny" | "tiny.en";
24
26
  onProgress?: OnWhisperWebGpuModelLoadProgress | undefined;
27
+ signal: AbortSignal | null;
25
28
  run: (pipeline: LoadedWhisperPipeline) => Promise<ReturnValue>;
26
29
  }) => Promise<ReturnValue>;
27
30
  export type DisposeWhisperModelOptions = {
@@ -0,0 +1 @@
1
+ export declare const probeNodeWebGpu: () => Promise<void>;
File without changes
@@ -25,5 +25,6 @@ export type TranscribeOptions = {
25
25
  repetitionPenalty?: number;
26
26
  noRepeatNgramSize?: number;
27
27
  onModelLoadProgress?: OnWhisperWebGpuModelLoadProgress;
28
+ signal?: AbortSignal;
28
29
  };
29
- export declare const transcribe: ({ channelWaveform, model, language, task, chunkLengthInSeconds, strideLengthInSeconds, forceFullSequences, doSample, temperature, topK, repetitionPenalty, noRepeatNgramSize, onModelLoadProgress, }: TranscribeOptions) => Promise<WhisperWebGpuTranscription>;
30
+ export declare const transcribe: ({ channelWaveform, model, language, task, chunkLengthInSeconds, strideLengthInSeconds, forceFullSequences, doSample, temperature, topK, repetitionPenalty, noRepeatNgramSize, onModelLoadProgress, signal, }: TranscribeOptions) => Promise<WhisperWebGpuTranscription>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/whisper-webgpu",
3
- "version": "4.0.527",
3
+ "version": "4.0.529",
4
4
  "description": "Transcribe audio in the browser using Whisper and WebGPU",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,7 +24,8 @@
24
24
  "url": "https://github.com/remotion-dev/remotion/issues"
25
25
  },
26
26
  "dependencies": {
27
- "@remotion/captions": "4.0.527"
27
+ "@remotion/captions": "4.0.529",
28
+ "onnxruntime-node": "1.24.3"
28
29
  },
29
30
  "peerDependencies": {
30
31
  "@huggingface/transformers": "4.2.0"
@@ -39,7 +40,7 @@
39
40
  },
40
41
  "devDependencies": {
41
42
  "@huggingface/transformers": "4.2.0",
42
- "@remotion/eslint-config-internal": "4.0.527",
43
+ "@remotion/eslint-config-internal": "4.0.529",
43
44
  "@typescript/native-preview": "7.0.0-dev.20260217.1",
44
45
  "eslint": "9.19.0"
45
46
  },