@qvac/sdk 0.10.2 → 0.12.0
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.
- package/NOTICE +1455 -29
- package/README.md +2 -0
- package/dist/client/api/cancel.d.ts +24 -32
- package/dist/client/api/cancel.js +58 -31
- package/dist/client/api/classify.d.ts +23 -0
- package/dist/client/api/classify.js +43 -0
- package/dist/client/api/client-request-id.d.ts +17 -0
- package/dist/client/api/client-request-id.js +27 -0
- package/dist/client/api/completion-stream.d.ts +1 -1
- package/dist/client/api/completion-stream.js +34 -3
- package/dist/client/api/diffusion.d.ts +46 -0
- package/dist/client/api/diffusion.js +50 -1
- package/dist/client/api/download-asset.d.ts +12 -2
- package/dist/client/api/download-asset.js +21 -3
- package/dist/client/api/embed.d.ts +8 -4
- package/dist/client/api/embed.js +14 -1
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/index.d.ts +5 -0
- package/dist/client/api/index.js +5 -0
- package/dist/client/api/load-model.d.ts +12 -4
- package/dist/client/api/load-model.js +49 -2
- package/dist/client/api/rag.d.ts +9 -3
- package/dist/client/api/rag.js +23 -3
- package/dist/client/api/transcribe.d.ts +23 -8
- package/dist/client/api/transcribe.js +69 -4
- package/dist/client/api/unload-model.d.ts +5 -2
- package/dist/client/api/unload-model.js +9 -4
- package/dist/client/api/upscale.d.ts +45 -0
- package/dist/client/api/upscale.js +99 -0
- package/dist/client/api/video.d.ts +64 -0
- package/dist/client/api/video.js +147 -0
- package/dist/client/api/vla-helpers.d.ts +45 -0
- package/dist/client/api/vla-helpers.js +130 -0
- package/dist/client/api/vla.d.ts +65 -0
- package/dist/client/api/vla.js +109 -0
- package/dist/client/config-loader/resolve-config.node.d.ts +16 -0
- package/dist/client/config-loader/resolve-config.node.js +77 -23
- package/dist/client/plugins-factory.d.ts +8 -0
- package/dist/client/plugins-factory.js +10 -0
- package/dist/client/rpc/bare-client.js +62 -66
- package/dist/client/rpc/ensure-worker-ready.d.ts +9 -0
- package/dist/client/rpc/ensure-worker-ready.js +17 -0
- package/dist/client/rpc/expo-rpc-client.js +2 -1
- package/dist/client/rpc/node-rpc-client.js +22 -8
- package/dist/client/rpc/rpc-client.d.ts +2 -2
- package/dist/client/rpc/rpc-client.js +10 -4
- package/dist/client/rpc/rpc-error.d.ts +9 -0
- package/dist/client/rpc/rpc-error.js +105 -0
- package/dist/commands/bundle/bare-pack.d.ts +13 -0
- package/dist/commands/bundle/bare-pack.js +54 -0
- package/dist/commands/bundle/constants.d.ts +7 -0
- package/dist/commands/bundle/constants.js +23 -0
- package/dist/commands/bundle/entry-gen.d.ts +2 -0
- package/dist/commands/bundle/entry-gen.js +48 -0
- package/dist/commands/bundle/index.d.ts +20 -0
- package/dist/commands/bundle/index.js +141 -0
- package/dist/commands/bundle/manifest.d.ts +21 -0
- package/dist/commands/bundle/manifest.js +193 -0
- package/dist/commands/bundle/plugins.d.ts +9 -0
- package/dist/commands/bundle/plugins.js +51 -0
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/verify/abi.d.ts +52 -0
- package/dist/commands/verify/abi.js +125 -0
- package/dist/commands/verify/addon-source.d.ts +43 -0
- package/dist/commands/verify/addon-source.js +75 -0
- package/dist/commands/verify/bundle-source.d.ts +12 -0
- package/dist/commands/verify/bundle-source.js +53 -0
- package/dist/commands/verify/index.d.ts +59 -0
- package/dist/commands/verify/index.js +371 -0
- package/dist/commands/verify/node-modules-source.d.ts +11 -0
- package/dist/commands/verify/node-modules-source.js +76 -0
- package/dist/commands/verify/prebuilds.d.ts +15 -0
- package/dist/commands/verify/prebuilds.js +39 -0
- package/dist/examples/cancel-by-request-id.d.ts +38 -0
- package/dist/examples/cancel-by-request-id.js +103 -0
- package/dist/examples/classification/classify-image.d.ts +2 -0
- package/dist/examples/classification/classify-image.js +23 -0
- package/dist/examples/diffusion-esrgan-upscale.d.ts +2 -0
- package/dist/examples/diffusion-esrgan-upscale.js +78 -0
- package/dist/examples/diffusion-txt2vid.d.ts +2 -0
- package/dist/examples/diffusion-txt2vid.js +81 -0
- package/dist/examples/download-with-cancel.js +10 -10
- package/dist/examples/embed-multi-gpu.d.ts +2 -0
- package/dist/examples/embed-multi-gpu.js +46 -0
- package/dist/examples/llamacpp-multi-gpu.d.ts +2 -0
- package/dist/examples/llamacpp-multi-gpu.js +57 -0
- package/dist/examples/plugins.js +3 -7
- package/dist/examples/rag/rag-hyperdb/cancellation.js +20 -17
- package/dist/examples/tools/llamacpp-tools-gemma4.d.ts +2 -0
- package/dist/examples/tools/llamacpp-tools-gemma4.js +73 -0
- package/dist/examples/tools/llamacpp-tools-qwen35.d.ts +2 -0
- package/dist/examples/tools/llamacpp-tools-qwen35.js +69 -0
- package/dist/examples/transcription/parakeet-ctc-filesystem.js +18 -12
- package/dist/examples/transcription/parakeet-microphone-record.js +7 -12
- package/dist/examples/transcription/parakeet-microphone-stream.d.ts +2 -0
- package/dist/examples/transcription/parakeet-microphone-stream.js +79 -0
- package/dist/examples/transcription/parakeet-sortformer-streaming.d.ts +2 -0
- package/dist/examples/transcription/parakeet-sortformer-streaming.js +121 -0
- package/dist/examples/transcription/parakeet-sortformer.js +58 -55
- package/dist/examples/transcription/parakeet-tdt-filesystem.js +18 -15
- package/dist/examples/transcription/whispercpp-microphone-conversation.d.ts +2 -0
- package/dist/examples/transcription/whispercpp-microphone-conversation.js +107 -0
- package/dist/examples/tts/chatterbox.js +7 -16
- package/dist/examples/tts/llm-to-tts-streaming.js +3 -10
- package/dist/examples/tts/supertonic-multilingual.js +4 -12
- package/dist/examples/tts/supertonic.js +5 -12
- package/dist/examples/vla-smolvla.d.ts +2 -0
- package/dist/examples/vla-smolvla.js +75 -0
- package/dist/examples/voice-assistant/voice-assistant.js +3 -10
- package/dist/expo/plugins/find-in-ancestor-node-modules.d.ts +14 -0
- package/dist/expo/plugins/find-in-ancestor-node-modules.js +24 -0
- package/dist/expo/plugins/get-project-root.d.ts +22 -0
- package/dist/expo/plugins/get-project-root.js +23 -0
- package/dist/expo/plugins/index.d.ts +4 -0
- package/dist/expo/plugins/index.js +4 -0
- package/dist/expo/plugins/resolve-sdk-package-dir.d.ts +9 -2
- package/dist/expo/plugins/resolve-sdk-package-dir.js +38 -11
- package/dist/expo/plugins/withDeviceInfo.js +2 -1
- package/dist/expo/plugins/withMobileBundle.d.ts +5 -4
- package/dist/expo/plugins/withMobileBundle.js +42 -58
- package/dist/index.d.ts +6 -2
- package/dist/index.js +23 -2
- package/dist/models/registry/models.d.ts +3725 -514
- package/dist/models/registry/models.js +7269 -3910
- package/dist/models/update-models/naming.js +22 -8
- package/dist/pear/pre.d.ts +3 -0
- package/dist/pear/pre.js +9 -2
- package/dist/schemas/cancel.d.ts +172 -28
- package/dist/schemas/cancel.js +120 -19
- package/dist/schemas/classification.d.ts +53 -0
- package/dist/schemas/classification.js +33 -0
- package/dist/schemas/common.d.ts +860 -1379
- package/dist/schemas/common.js +8 -1
- package/dist/schemas/completion-event.d.ts +17 -0
- package/dist/schemas/completion-event.js +12 -1
- package/dist/schemas/completion-stream.d.ts +16 -1
- package/dist/schemas/completion-stream.js +25 -7
- package/dist/schemas/download-asset.d.ts +25 -9
- package/dist/schemas/download-asset.js +17 -6
- package/dist/schemas/embed.d.ts +1 -0
- package/dist/schemas/embed.js +5 -0
- package/dist/schemas/engine-addon-map.d.ts +3 -0
- package/dist/schemas/engine-addon-map.js +18 -5
- package/dist/schemas/error.d.ts +31 -0
- package/dist/schemas/error.js +29 -1
- package/dist/schemas/finetune.d.ts +2 -0
- package/dist/schemas/finetune.js +5 -0
- package/dist/schemas/get-model-info.d.ts +10 -6
- package/dist/schemas/get-model-info.js +2 -0
- package/dist/schemas/index.d.ts +3 -0
- package/dist/schemas/index.js +3 -0
- package/dist/schemas/llamacpp-config.d.ts +64 -8
- package/dist/schemas/llamacpp-config.js +12 -0
- package/dist/schemas/load-model.d.ts +4644 -8605
- package/dist/schemas/load-model.js +90 -7
- package/dist/schemas/model-src-utils.d.ts +34 -14
- package/dist/schemas/model-types.d.ts +54 -14
- package/dist/schemas/model-types.js +28 -5
- package/dist/schemas/ocr.d.ts +8 -3
- package/dist/schemas/plugin.d.ts +60 -6
- package/dist/schemas/plugin.js +31 -5
- package/dist/schemas/rag.d.ts +9 -0
- package/dist/schemas/rag.js +17 -9
- package/dist/schemas/registry.d.ts +74 -30
- package/dist/schemas/registry.js +5 -0
- package/dist/schemas/reload-config.d.ts +34 -14
- package/dist/schemas/sdcpp-config.d.ts +445 -16
- package/dist/schemas/sdcpp-config.js +387 -26
- package/dist/schemas/sdk-config.d.ts +2431 -2723
- package/dist/schemas/sdk-config.js +16 -1
- package/dist/schemas/sdk-errors-client.d.ts +6 -0
- package/dist/schemas/sdk-errors-client.js +31 -1
- package/dist/schemas/sdk-errors-server.d.ts +8 -1
- package/dist/schemas/sdk-errors-server.js +45 -5
- package/dist/schemas/text-to-speech.d.ts +81 -698
- package/dist/schemas/text-to-speech.js +46 -19
- package/dist/schemas/transcription-config.d.ts +40 -229
- package/dist/schemas/transcription-config.js +76 -15
- package/dist/schemas/transcription.d.ts +108 -2
- package/dist/schemas/transcription.js +81 -0
- package/dist/schemas/translate.d.ts +2 -0
- package/dist/schemas/translate.js +13 -2
- package/dist/schemas/translation-config.d.ts +90 -40
- package/dist/schemas/unload-model.d.ts +2 -1
- package/dist/schemas/unload-model.js +4 -1
- package/dist/schemas/vla.d.ts +87 -0
- package/dist/schemas/vla.js +108 -0
- package/dist/scripts/run-unit-tests.js +22 -3
- package/dist/server/bare/ops/cancel.d.ts +27 -1
- package/dist/server/bare/ops/cancel.js +36 -10
- package/dist/server/bare/ops/embed.d.ts +3 -3
- package/dist/server/bare/ops/embed.js +144 -28
- package/dist/server/bare/ops/kv-cache-utils.d.ts +0 -7
- package/dist/server/bare/ops/kv-cache-utils.js +8 -47
- package/dist/server/bare/ops/transcribe.d.ts +11 -5
- package/dist/server/bare/ops/transcribe.js +230 -50
- package/dist/server/bare/ops/translate.d.ts +1 -1
- package/dist/server/bare/ops/translate.js +197 -88
- package/dist/server/bare/plugins/ggml-classification/ops/classify.d.ts +6 -0
- package/dist/server/bare/plugins/ggml-classification/ops/classify.js +30 -0
- package/dist/server/bare/plugins/ggml-classification/plugin.d.ts +32 -0
- package/dist/server/bare/plugins/ggml-classification/plugin.js +55 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.d.ts +3 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.js +12 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-run.d.ts +3 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-run.js +75 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +54 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.js +57 -0
- package/dist/server/bare/plugins/index.d.ts +3 -1
- package/dist/server/bare/plugins/index.js +3 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +12 -3
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +173 -172
- package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.d.ts +29 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.js +65 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +125 -21
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +154 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +448 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +21 -73
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +18 -101
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +36 -3
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +183 -85
- package/dist/server/bare/plugins/llamacpp-completion/transform.d.ts +10 -0
- package/dist/server/bare/plugins/llamacpp-completion/transform.js +34 -0
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +7 -0
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -1
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +42 -15
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +5 -1
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +8 -3
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +3 -0
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +73 -244
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +68 -96
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +8 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.d.ts +3 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.js +40 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/video.d.ts +3 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/video.js +199 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +288 -15
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +150 -7
- package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.js +2 -15
- package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.js +2 -1
- package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +75 -0
- package/dist/server/bare/plugins/tts-ggml/plugin.js +189 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +47 -3
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +61 -14
- package/dist/server/bare/rag-hyperdb/index.d.ts +1 -1
- package/dist/server/bare/rag-hyperdb/index.js +1 -1
- package/dist/server/bare/rag-hyperdb/rag-operation-manager.d.ts +26 -4
- package/dist/server/bare/rag-hyperdb/rag-operation-manager.js +65 -28
- package/dist/server/bare/registry/model-config-utils.js +7 -0
- package/dist/server/bare/runtime/disposable-scope.d.ts +36 -0
- package/dist/server/bare/runtime/disposable-scope.js +69 -0
- package/dist/server/bare/runtime/index.d.ts +8 -0
- package/dist/server/bare/runtime/index.js +3 -0
- package/dist/server/bare/runtime/request-context.d.ts +49 -0
- package/dist/server/bare/runtime/request-context.js +1 -0
- package/dist/server/bare/runtime/request-id.d.ts +12 -0
- package/dist/server/bare/runtime/request-id.js +14 -0
- package/dist/server/bare/runtime/request-registry-singleton.d.ts +4 -0
- package/dist/server/bare/runtime/request-registry-singleton.js +27 -0
- package/dist/server/bare/runtime/request-registry.d.ts +136 -0
- package/dist/server/bare/runtime/request-registry.js +297 -0
- package/dist/server/bare/runtime/with-request-context.d.ts +22 -0
- package/dist/server/bare/runtime/with-request-context.js +53 -0
- package/dist/server/bare/runtime-lifecycle.js +9 -9
- package/dist/server/bare/types/addon-responses.d.ts +12 -1
- package/dist/server/env.js +4 -1
- package/dist/server/plugins/index.d.ts +1 -1
- package/dist/server/plugins/index.js +1 -1
- package/dist/server/plugins/registry.d.ts +1 -0
- package/dist/server/plugins/registry.js +5 -0
- package/dist/server/rpc/handler-registry.js +30 -7
- package/dist/server/rpc/handler-selection.d.ts +9 -0
- package/dist/server/rpc/handler-selection.js +14 -0
- package/dist/server/rpc/handler-utils.js +5 -13
- package/dist/server/rpc/handlers/cancel-delegated.js +28 -31
- package/dist/server/rpc/handlers/cancelHandler.d.ts +30 -1
- package/dist/server/rpc/handlers/cancelHandler.js +54 -22
- package/dist/server/rpc/handlers/classify.d.ts +3 -0
- package/dist/server/rpc/handlers/classify.js +4 -0
- package/dist/server/rpc/handlers/delete-cache.d.ts +9 -0
- package/dist/server/rpc/handlers/delete-cache.js +13 -15
- package/dist/server/rpc/handlers/download-asset.js +133 -40
- package/dist/server/rpc/handlers/index.d.ts +4 -0
- package/dist/server/rpc/handlers/index.js +4 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +60 -2
- package/dist/server/rpc/handlers/load-model/download-manager.js +141 -8
- package/dist/server/rpc/handlers/load-model/handler.js +216 -98
- package/dist/server/rpc/handlers/load-model/http.js +3 -3
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +1 -1
- package/dist/server/rpc/handlers/load-model/registry.js +1 -1
- package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +20 -1
- package/dist/server/rpc/handlers/load-model/resolve-session.js +6 -5
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -2
- package/dist/server/rpc/handlers/load-model/resolve.js +18 -6
- package/dist/server/rpc/handlers/load-model/types.d.ts +24 -0
- package/dist/server/rpc/handlers/rag.js +133 -15
- package/dist/server/rpc/handlers/upscale-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/upscale-stream.js +4 -0
- package/dist/server/rpc/handlers/video-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/video-stream.js +4 -0
- package/dist/server/rpc/profiling/operation-metrics.js +23 -0
- package/dist/server/utils/completion-normalizer.js +8 -0
- package/dist/server/utils/config-transform.js +1 -1
- package/dist/server/utils/tools/dialect.js +4 -0
- package/dist/server/utils/tools/parser.js +16 -1
- package/dist/server/utils/tools/parsers/gemma4native.d.ts +4 -0
- package/dist/server/utils/tools/parsers/gemma4native.js +60 -0
- package/dist/server/utils/tools/parsers/qwen35.d.ts +4 -0
- package/dist/server/utils/tools/parsers/qwen35.js +120 -0
- package/dist/server/worker.js +14 -11
- package/dist/utils/aggregate-events.d.ts +9 -0
- package/dist/utils/aggregate-events.js +18 -3
- package/dist/utils/decorate-promise.d.ts +34 -0
- package/dist/utils/decorate-promise.js +35 -0
- package/dist/utils/errors-client.d.ts +18 -0
- package/dist/utils/errors-client.js +31 -0
- package/dist/utils/errors-server.d.ts +115 -2
- package/dist/utils/errors-server.js +148 -3
- package/package.json +68 -77
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +0 -490
- package/dist/server/bare/plugins/onnx-tts/plugin.js +0 -266
- package/dist/server/bare/plugins/onnx-tts/wav-helper.d.ts +0 -14
- package/dist/server/bare/plugins/onnx-tts/wav-helper.js +0 -107
- /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.d.ts +0 -0
- /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.d.ts +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microphone → Parakeet duplex streaming (`transcribeStream`).
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* bun run examples/transcription/parakeet-microphone-stream.ts
|
|
6
|
+
*
|
|
7
|
+
* Streams microphone audio through `transcribeStream` with
|
|
8
|
+
* `parakeetStreamingConfig`. Uses the EOU checkpoint so you may see
|
|
9
|
+
* `{ type: "endOfTurn", source: "parakeet" }` events; CTC/TDT models
|
|
10
|
+
* emit transcript text only. Parakeet does not yield standalone VAD events.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: FFmpeg installed, microphone access.
|
|
13
|
+
*/
|
|
14
|
+
import { loadModel, unloadModel, transcribeStream, PARAKEET_EOU_120M_V1_Q8_0, } from "@qvac/sdk";
|
|
15
|
+
import { spawnSync } from "child_process";
|
|
16
|
+
import { startMicrophone } from "../audio/mic-input";
|
|
17
|
+
const SAMPLE_RATE = 16000;
|
|
18
|
+
try {
|
|
19
|
+
const r = spawnSync("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
20
|
+
if (r.error || r.status !== 0)
|
|
21
|
+
throw new Error("FFmpeg not found");
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
console.error("Error: FFmpeg is required. Install it and try again.");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
let modelId = null;
|
|
28
|
+
let ffmpeg = null;
|
|
29
|
+
async function cleanup() {
|
|
30
|
+
console.log("\n\nStopping...");
|
|
31
|
+
ffmpeg?.kill();
|
|
32
|
+
if (modelId)
|
|
33
|
+
await unloadModel({ modelId });
|
|
34
|
+
console.log("Done.");
|
|
35
|
+
}
|
|
36
|
+
process.on("SIGINT", () => {
|
|
37
|
+
void cleanup().finally(() => process.exit(0));
|
|
38
|
+
});
|
|
39
|
+
process.on("SIGTERM", () => {
|
|
40
|
+
void cleanup().finally(() => process.exit(0));
|
|
41
|
+
});
|
|
42
|
+
try {
|
|
43
|
+
console.log("Loading Parakeet (EOU) streaming model...");
|
|
44
|
+
modelId = await loadModel({
|
|
45
|
+
modelSrc: PARAKEET_EOU_120M_V1_Q8_0,
|
|
46
|
+
modelType: "parakeet",
|
|
47
|
+
onProgress: (p) => console.log(`Download: ${p.percentage.toFixed(1)}%`),
|
|
48
|
+
});
|
|
49
|
+
console.log("Model loaded.\n");
|
|
50
|
+
ffmpeg = startMicrophone({ sampleRate: SAMPLE_RATE, format: "s16le" });
|
|
51
|
+
const session = await transcribeStream({
|
|
52
|
+
modelId,
|
|
53
|
+
parakeetStreamingConfig: {
|
|
54
|
+
chunkMs: 1000,
|
|
55
|
+
emitPartials: true,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
|
|
59
|
+
console.log("Listening... speak and pause to see transcripts. End-of-turn boundaries fire when the EOU model emits an <EOU> token.\n");
|
|
60
|
+
for await (const event of session) {
|
|
61
|
+
switch (event.type) {
|
|
62
|
+
case "text":
|
|
63
|
+
if (event.text.trim()) {
|
|
64
|
+
process.stdout.write(`${event.text}`);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
case "endOfTurn":
|
|
68
|
+
console.log("\n[endOfTurn] turn boundary detected\n");
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
await cleanup();
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error("Error:", error);
|
|
77
|
+
await cleanup();
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sortformer v2.1 streaming diarization via duplex `transcribeStream` + AOSC.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* bun run examples/transcription/parakeet-sortformer-streaming.ts <wav-file> [sortformer-gguf]
|
|
6
|
+
*
|
|
7
|
+
* Streams 16 kHz mono s16le audio in real-time-paced chunks (required for parakeet
|
|
8
|
+
* duplex streaming). Loads v2.1 with AOSC knobs in `modelConfig`. Omit the model
|
|
9
|
+
* argument to use `PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0`.
|
|
10
|
+
*
|
|
11
|
+
* For offline batch diarization (Sortformer + TDT), see `parakeet-sortformer.ts`.
|
|
12
|
+
*/
|
|
13
|
+
import { loadModel, unloadModel, transcribeStream, PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0, } from "@qvac/sdk";
|
|
14
|
+
import { spawn } from "child_process";
|
|
15
|
+
const SAMPLE_RATE = 16000;
|
|
16
|
+
const BYTES_PER_S16_SAMPLE = 2;
|
|
17
|
+
const STREAM_CHUNK_MS = 2000;
|
|
18
|
+
/** NeMo-port AOSC defaults for v2.1 Sortformer (`parakeet.model_variant` in GGUF). */
|
|
19
|
+
const SORTFORMER_V21_AOSC_LOAD_CONFIG = {
|
|
20
|
+
streaming: true,
|
|
21
|
+
streamingChunkMs: 2000,
|
|
22
|
+
streamingChunkRightContextMs: 560,
|
|
23
|
+
streamingSpkCacheEnable: true,
|
|
24
|
+
streamingSpkCacheLen: 188,
|
|
25
|
+
streamingFifoLen: 188,
|
|
26
|
+
streamingChunkLeftContextMs: 80,
|
|
27
|
+
streamingSpkCacheUpdatePeriod: 144,
|
|
28
|
+
};
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
if (!args[0]) {
|
|
31
|
+
console.error("Usage: bun run examples/transcription/parakeet-sortformer-streaming.ts <wav-file-path> [sortformer-gguf]");
|
|
32
|
+
console.error("\nDefaults to the v2.1 q8_0 registry model (PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0).");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const audioFilePath = args[0];
|
|
36
|
+
const sortformerOverride = args[1];
|
|
37
|
+
const chunkBytes = Math.floor((STREAM_CHUNK_MS / 1000) * SAMPLE_RATE) * BYTES_PER_S16_SAMPLE;
|
|
38
|
+
let modelId = null;
|
|
39
|
+
async function cleanup() {
|
|
40
|
+
if (modelId) {
|
|
41
|
+
await unloadModel({ modelId });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function readS16leFromWav(wavPath) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const chunks = [];
|
|
47
|
+
const proc = spawn("ffmpeg", [
|
|
48
|
+
"-i",
|
|
49
|
+
wavPath,
|
|
50
|
+
"-ar",
|
|
51
|
+
String(SAMPLE_RATE),
|
|
52
|
+
"-ac",
|
|
53
|
+
"1",
|
|
54
|
+
"-f",
|
|
55
|
+
"s16le",
|
|
56
|
+
"pipe:1",
|
|
57
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
58
|
+
proc.stdout.on("data", (buf) => chunks.push(buf));
|
|
59
|
+
proc.on("error", reject);
|
|
60
|
+
proc.on("close", (code) => {
|
|
61
|
+
if (code !== 0) {
|
|
62
|
+
reject(new Error(`ffmpeg exited with code ${code}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const merged = Buffer.concat(chunks);
|
|
66
|
+
resolve(new Uint8Array(merged.buffer, merged.byteOffset, merged.byteLength));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const loadOptions = {
|
|
71
|
+
modelType: "parakeet-transcription",
|
|
72
|
+
modelConfig: { ...SORTFORMER_V21_AOSC_LOAD_CONFIG },
|
|
73
|
+
onProgress: (p) => console.log(`Download: ${p.percentage.toFixed(1)}%`),
|
|
74
|
+
...(sortformerOverride
|
|
75
|
+
? { modelSrc: sortformerOverride }
|
|
76
|
+
: { modelSrc: PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0 }),
|
|
77
|
+
};
|
|
78
|
+
try {
|
|
79
|
+
console.log("Loading Sortformer v2.1 with streaming + AOSC (load-time config)...");
|
|
80
|
+
modelId = await loadModel(loadOptions);
|
|
81
|
+
console.log(`Model loaded: ${modelId}\n`);
|
|
82
|
+
const session = await transcribeStream({
|
|
83
|
+
modelId,
|
|
84
|
+
parakeetStreamingConfig: { chunkMs: STREAM_CHUNK_MS },
|
|
85
|
+
});
|
|
86
|
+
console.log(`Streaming ${audioFilePath} in ${STREAM_CHUNK_MS}ms chunks (wall-clock paced)...\n`);
|
|
87
|
+
const pcm = await readS16leFromWav(audioFilePath);
|
|
88
|
+
const trailingSilenceMs = 1500;
|
|
89
|
+
const trailingBytes = new Uint8Array(Math.floor((trailingSilenceMs / 1000) * SAMPLE_RATE) * BYTES_PER_S16_SAMPLE);
|
|
90
|
+
for (let offset = 0; offset < pcm.length; offset += chunkBytes) {
|
|
91
|
+
const end = Math.min(offset + chunkBytes, pcm.length);
|
|
92
|
+
session.write(pcm.subarray(offset, end));
|
|
93
|
+
if (end < pcm.length) {
|
|
94
|
+
await new Promise((resolve) => setTimeout(resolve, STREAM_CHUNK_MS));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (let offset = 0; offset < trailingBytes.length; offset += chunkBytes) {
|
|
98
|
+
const end = Math.min(offset + chunkBytes, trailingBytes.length);
|
|
99
|
+
session.write(trailingBytes.subarray(offset, end));
|
|
100
|
+
if (end < trailingBytes.length) {
|
|
101
|
+
await new Promise((resolve) => setTimeout(resolve, STREAM_CHUNK_MS));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
session.end();
|
|
105
|
+
const lines = [];
|
|
106
|
+
for await (const event of session) {
|
|
107
|
+
if (event.type === "text" && event.text.trim()) {
|
|
108
|
+
lines.push(event.text.trim());
|
|
109
|
+
console.log(event.text.trim());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
console.log("\n=== Streaming diarization transcript ===");
|
|
113
|
+
console.log(lines.join("\n") || "(no speaker lines emitted)");
|
|
114
|
+
await cleanup();
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error("❌ Error:", error);
|
|
119
|
+
await cleanup();
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
@@ -1,75 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Parakeet Sortformer diarization + TDT transcription
|
|
2
|
+
* Parakeet Sortformer diarization + TDT transcription pipeline.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* bun examples/transcription/parakeet-sortformer.ts [sortformer-
|
|
5
|
+
* bun run examples/transcription/parakeet-sortformer.ts [sortformer-gguf] [wav-file]
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Two-step flow: Sortformer v2.1 diarizes the audio, then TDT transcribes each
|
|
8
|
+
* speaker segment. Defaults to registry GGUFs and
|
|
9
|
+
* `examples/audio/diarization-sample-16k.wav`. For live streaming + AOSC, see
|
|
10
|
+
* `parakeet-sortformer-streaming.ts`.
|
|
11
|
+
*
|
|
12
|
+
* Sample audio is in the QVAC source repo but not the published npm package.
|
|
13
|
+
* Download the default file into `examples/audio/`:
|
|
10
14
|
* https://github.com/tetherto/qvac/blob/main/packages/sdk/examples/audio/diarization-sample-16k.wav
|
|
11
15
|
*/
|
|
12
|
-
import { loadModel, unloadModel, transcribe,
|
|
16
|
+
import { loadModel, unloadModel, transcribe, PARAKEET_TDT_0_6B_V3_Q8_0, PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0, } from "@qvac/sdk";
|
|
13
17
|
import { dirname, join } from "path";
|
|
14
18
|
import { fileURLToPath } from "url";
|
|
15
19
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
16
20
|
import { tmpdir } from "os";
|
|
17
21
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
22
|
const args = process.argv.slice(2);
|
|
19
|
-
const sortformerSrc = args[0] ??
|
|
23
|
+
const sortformerSrc = args[0] ?? PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0;
|
|
20
24
|
const defaultAudioPath = join(__dirname, "..", "audio", "diarization-sample-16k.wav");
|
|
21
25
|
const audioFilePath = args[1] ?? defaultAudioPath;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
modelId: sfModelId
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
26
|
+
try {
|
|
27
|
+
// ── Step 1: Diarize with Sortformer ──
|
|
28
|
+
const sfModelId = await loadModel({
|
|
29
|
+
modelSrc: sortformerSrc,
|
|
30
|
+
modelType: "parakeet",
|
|
31
|
+
});
|
|
32
|
+
const diarization = await transcribe({
|
|
33
|
+
modelId: sfModelId,
|
|
34
|
+
audioChunk: audioFilePath,
|
|
35
|
+
});
|
|
36
|
+
await unloadModel({ modelId: sfModelId });
|
|
37
|
+
const segments = parseDiarization(diarization);
|
|
38
|
+
// ── Step 2: Transcribe each segment with TDT ──
|
|
39
|
+
const tdtModelId = await loadModel({
|
|
40
|
+
modelSrc: PARAKEET_TDT_0_6B_V3_Q8_0,
|
|
41
|
+
modelType: "parakeet",
|
|
42
|
+
});
|
|
43
|
+
const pcm = readPcm(audioFilePath);
|
|
44
|
+
const sliceDir = join(tmpdir(), `qvac-diarize-${Date.now()}`);
|
|
45
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
46
|
+
const results = [];
|
|
47
|
+
for (let i = 0; i < segments.length; i++) {
|
|
48
|
+
const seg = segments[i];
|
|
49
|
+
const slicePath = join(sliceDir, `seg-${i}.wav`);
|
|
50
|
+
if (!writeWavSlice(pcm, seg.start, seg.end, slicePath)) {
|
|
51
|
+
results.push({ ...seg, text: "[No speech detected]" });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const text = await transcribe({
|
|
55
|
+
modelId: tdtModelId,
|
|
56
|
+
audioChunk: slicePath,
|
|
57
|
+
});
|
|
58
|
+
results.push({ ...seg, text: text.trim() || "[No speech detected]" });
|
|
59
|
+
}
|
|
60
|
+
await unloadModel({ modelId: tdtModelId });
|
|
61
|
+
// ── Step 3: Merge consecutive same-speaker segments and print ──
|
|
62
|
+
const merged = mergeSpeakers(results);
|
|
63
|
+
console.log("\n=== DIARIZED TRANSCRIPTION ===");
|
|
64
|
+
console.log("=".repeat(60));
|
|
65
|
+
for (const entry of merged) {
|
|
66
|
+
console.log(`Speaker ${entry.speaker} (${entry.start.toFixed(2)}s - ${entry.end.toFixed(2)}s):`);
|
|
67
|
+
console.log(` ${entry.text}\n`);
|
|
58
68
|
}
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
console.log("=".repeat(60));
|
|
70
|
+
console.log("\nDone!");
|
|
61
71
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.log("\n=== DIARIZED TRANSCRIPTION ===");
|
|
66
|
-
console.log("=".repeat(60));
|
|
67
|
-
for (const entry of merged) {
|
|
68
|
-
console.log(`Speaker ${entry.speaker} (${entry.start.toFixed(2)}s - ${entry.end.toFixed(2)}s):`);
|
|
69
|
-
console.log(` ${entry.text}\n`);
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error("❌ Error:", error);
|
|
74
|
+
process.exit(1);
|
|
70
75
|
}
|
|
71
|
-
console.log("=".repeat(60));
|
|
72
|
-
console.log("\nDone!");
|
|
73
76
|
// ── Helpers ──
|
|
74
77
|
function parseDiarization(text) {
|
|
75
78
|
const segs = [];
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Parakeet TDT transcription from a WAV file.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* bun run examples/transcription/parakeet-tdt-filesystem.ts <wav-file> [parakeet-tdt-gguf]
|
|
6
|
+
*
|
|
7
|
+
* Loads a single GGUF checkpoint (`PARAKEET_TDT_0_6B_V3_Q8_0` by default) and
|
|
8
|
+
* transcribes the file with the batch `transcribe` API. Omit the model
|
|
9
|
+
* argument to use the registry constant.
|
|
10
|
+
*
|
|
11
|
+
* Audio should be 16 kHz mono PCM in a WAV container.
|
|
12
|
+
*/
|
|
13
|
+
import { loadModel, unloadModel, transcribe, PARAKEET_TDT_0_6B_V3_Q8_0, } from "@qvac/sdk";
|
|
2
14
|
const args = process.argv.slice(2);
|
|
3
15
|
if (!args[0]) {
|
|
4
16
|
console.error("Usage: bun run examples/transcription/parakeet-tdt-filesystem.ts <wav-file-path> " +
|
|
5
|
-
"[
|
|
6
|
-
console.error("\nIf model
|
|
17
|
+
"[parakeet-tdt-gguf]");
|
|
18
|
+
console.error("\nIf the model path is omitted, defaults to the registry model.");
|
|
7
19
|
process.exit(1);
|
|
8
20
|
}
|
|
9
21
|
const audioFilePath = args[0];
|
|
10
|
-
const
|
|
11
|
-
const parakeetDecoderSrc = args[2] ?? PARAKEET_TDT_DECODER_FP32;
|
|
12
|
-
const parakeetVocabSrc = args[3] ?? PARAKEET_TDT_VOCAB;
|
|
13
|
-
const parakeetPreprocessorSrc = args[4] ?? PARAKEET_TDT_PREPROCESSOR_FP32;
|
|
22
|
+
const parakeetModelSrc = args[1] ?? PARAKEET_TDT_0_6B_V3_Q8_0;
|
|
14
23
|
try {
|
|
15
24
|
console.log("Starting Parakeet transcription example...");
|
|
16
25
|
console.log("Loading Parakeet model...");
|
|
17
26
|
const modelId = await loadModel({
|
|
18
|
-
modelSrc:
|
|
27
|
+
modelSrc: parakeetModelSrc,
|
|
19
28
|
modelType: "parakeet",
|
|
20
|
-
modelConfig: {
|
|
21
|
-
parakeetEncoderSrc,
|
|
22
|
-
parakeetDecoderSrc,
|
|
23
|
-
parakeetVocabSrc,
|
|
24
|
-
parakeetPreprocessorSrc,
|
|
25
|
-
},
|
|
26
29
|
onProgress: (progress) => {
|
|
27
30
|
console.log(`Download progress: ${progress.percentage.toFixed(1)}%`);
|
|
28
31
|
},
|
|
@@ -37,6 +40,6 @@ try {
|
|
|
37
40
|
console.log("Parakeet model unloaded successfully");
|
|
38
41
|
}
|
|
39
42
|
catch (error) {
|
|
40
|
-
console.error("Error:", error);
|
|
43
|
+
console.error("❌ Error:", error);
|
|
41
44
|
process.exit(1);
|
|
42
45
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microphone → Whisper streaming transcription with conversation events
|
|
3
|
+
* (VAD state updates + end-of-turn detection).
|
|
4
|
+
*
|
|
5
|
+
* Demonstrates the opt-in conversation API:
|
|
6
|
+
* transcribeStream({ modelId, emitVadEvents: true, endOfTurnSilenceMs: N })
|
|
7
|
+
*
|
|
8
|
+
* The session yields a discriminated union of events:
|
|
9
|
+
* - { type: "text", text } transcript chunks
|
|
10
|
+
* - { type: "vad", speaking, probability } VAD state updates
|
|
11
|
+
* - { type: "endOfTurn", silenceDurationMs } silence boundary
|
|
12
|
+
*
|
|
13
|
+
* Speak into your mic; transcripts appear as you pause, VAD ticks while
|
|
14
|
+
* you speak, and an end-of-turn event fires after 800ms of silence.
|
|
15
|
+
* Press Ctrl+C to quit.
|
|
16
|
+
*
|
|
17
|
+
* Requirements: FFmpeg installed, microphone access.
|
|
18
|
+
*/
|
|
19
|
+
import { loadModel, unloadModel, transcribeStream, WHISPER_TINY, VAD_SILERO_5_1_2, } from "@qvac/sdk";
|
|
20
|
+
import { spawnSync } from "child_process";
|
|
21
|
+
import { startMicrophone } from "../audio/mic-input";
|
|
22
|
+
const SAMPLE_RATE = 16000;
|
|
23
|
+
try {
|
|
24
|
+
const r = spawnSync("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
25
|
+
if (r.error || r.status !== 0)
|
|
26
|
+
throw new Error("FFmpeg not found");
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
console.error("❌ Error: FFmpeg is required. Install it and try again.");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
let modelId = null;
|
|
33
|
+
let ffmpeg = null;
|
|
34
|
+
async function cleanup() {
|
|
35
|
+
console.log("\n\nStopping...");
|
|
36
|
+
ffmpeg?.kill();
|
|
37
|
+
if (modelId)
|
|
38
|
+
await unloadModel({ modelId });
|
|
39
|
+
console.log("Done.");
|
|
40
|
+
}
|
|
41
|
+
process.on("SIGINT", () => {
|
|
42
|
+
void cleanup().finally(() => process.exit(0));
|
|
43
|
+
});
|
|
44
|
+
process.on("SIGTERM", () => {
|
|
45
|
+
void cleanup().finally(() => process.exit(0));
|
|
46
|
+
});
|
|
47
|
+
try {
|
|
48
|
+
console.log("Loading model (whisper-tiny + Silero VAD)...");
|
|
49
|
+
modelId = await loadModel({
|
|
50
|
+
modelSrc: WHISPER_TINY,
|
|
51
|
+
modelType: "whisper",
|
|
52
|
+
modelConfig: {
|
|
53
|
+
vadModelSrc: VAD_SILERO_5_1_2,
|
|
54
|
+
audio_format: "f32le",
|
|
55
|
+
strategy: "greedy",
|
|
56
|
+
n_threads: 4,
|
|
57
|
+
language: "en",
|
|
58
|
+
no_timestamps: true,
|
|
59
|
+
suppress_blank: true,
|
|
60
|
+
suppress_nst: true,
|
|
61
|
+
temperature: 0.0,
|
|
62
|
+
vad_params: {
|
|
63
|
+
threshold: 0.6,
|
|
64
|
+
min_speech_duration_ms: 250,
|
|
65
|
+
min_silence_duration_ms: 300,
|
|
66
|
+
max_speech_duration_s: 15.0,
|
|
67
|
+
speech_pad_ms: 100,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
console.log("Model loaded.\n");
|
|
72
|
+
ffmpeg = startMicrophone({ sampleRate: SAMPLE_RATE, format: "f32le" });
|
|
73
|
+
const session = await transcribeStream({
|
|
74
|
+
modelId,
|
|
75
|
+
emitVadEvents: true,
|
|
76
|
+
endOfTurnSilenceMs: 800,
|
|
77
|
+
});
|
|
78
|
+
ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
|
|
79
|
+
console.log("Listening... speak and pause to see transcripts, VAD events, and end-of-turn signals.\n");
|
|
80
|
+
let lastSpeaking = false;
|
|
81
|
+
for await (const event of session) {
|
|
82
|
+
switch (event.type) {
|
|
83
|
+
case "text":
|
|
84
|
+
console.log(`> ${event.text.trim()}`);
|
|
85
|
+
break;
|
|
86
|
+
case "vad":
|
|
87
|
+
if (event.speaking !== lastSpeaking) {
|
|
88
|
+
console.log(`[vad] speaking=${event.speaking} probability=${event.probability.toFixed(2)}`);
|
|
89
|
+
lastSpeaking = event.speaking;
|
|
90
|
+
}
|
|
91
|
+
break;
|
|
92
|
+
case "endOfTurn":
|
|
93
|
+
if (event.source === "whisper") {
|
|
94
|
+
console.log(`[endOfTurn] silence ${event.silenceDurationMs}ms — turn complete\n`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
console.log(`[endOfTurn] turn complete (token-driven EOU)\n`);
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error("❌ Error:", error);
|
|
105
|
+
await cleanup();
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
@@ -1,28 +1,19 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_T3_TURBO_EN_CHATTERBOX_Q8_0, TTS_S3GEN_EN_CHATTERBOX, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Chatterbox TTS: voice cloning with reference audio.
|
|
4
|
-
// Uses registry model constants
|
|
5
|
-
//
|
|
6
|
-
// Usage: node chatterbox-filesystem.js <referenceAudioSrc>
|
|
3
|
+
// Chatterbox TTS (GGML): voice cloning with optional reference audio.
|
|
4
|
+
// Uses registry model constants — downloads automatically from QVAC Registry.
|
|
5
|
+
// Usage: node chatterbox.ts [referenceAudioSrc]
|
|
7
6
|
const [referenceAudioSrc] = process.argv.slice(2);
|
|
8
|
-
if (!referenceAudioSrc) {
|
|
9
|
-
console.error("Usage: node chatterbox-filesystem.js <referenceAudioSrc>");
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
7
|
const CHATTERBOX_SAMPLE_RATE = 24000;
|
|
13
8
|
try {
|
|
14
9
|
const modelId = await loadModel({
|
|
15
|
-
modelSrc:
|
|
10
|
+
modelSrc: TTS_T3_TURBO_EN_CHATTERBOX_Q8_0.src,
|
|
16
11
|
modelType: "tts",
|
|
17
12
|
modelConfig: {
|
|
18
13
|
ttsEngine: "chatterbox",
|
|
19
14
|
language: "en",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ttsEmbedTokensSrc: TTS_EMBED_TOKENS_EN_CHATTERBOX_FP32.src,
|
|
23
|
-
ttsConditionalDecoderSrc: TTS_CONDITIONAL_DECODER_EN_CHATTERBOX_FP32.src,
|
|
24
|
-
ttsLanguageModelSrc: TTS_LANGUAGE_MODEL_EN_CHATTERBOX_FP32.src,
|
|
25
|
-
referenceAudioSrc,
|
|
15
|
+
s3genModelSrc: TTS_S3GEN_EN_CHATTERBOX.src,
|
|
16
|
+
...(referenceAudioSrc ? { referenceAudioSrc } : {}),
|
|
26
17
|
},
|
|
27
18
|
onProgress: (progress) => {
|
|
28
19
|
console.log(progress);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Usage:
|
|
13
13
|
* bun run examples/tts/llm-to-tts-streaming.ts
|
|
14
14
|
*/
|
|
15
|
-
import { completion, loadModel, textToSpeechStream, unloadModel, LLAMA_3_2_1B_INST_Q4_0,
|
|
15
|
+
import { completion, loadModel, textToSpeechStream, unloadModel, LLAMA_3_2_1B_INST_Q4_0, TTS_EN_SUPERTONIC_Q8_0, } from "@qvac/sdk";
|
|
16
16
|
import { createWav, playPcmInt16Chunk } from "./utils.js";
|
|
17
17
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
18
18
|
/**
|
|
@@ -69,21 +69,14 @@ try {
|
|
|
69
69
|
console.log(`LLM ready: ${llmModelId}`);
|
|
70
70
|
console.log("Loading Supertonic TTS (registry)…");
|
|
71
71
|
const ttsModelId = await loadModel({
|
|
72
|
-
modelSrc:
|
|
72
|
+
modelSrc: TTS_EN_SUPERTONIC_Q8_0.src,
|
|
73
73
|
modelType: "tts",
|
|
74
74
|
modelConfig: {
|
|
75
75
|
ttsEngine: "supertonic",
|
|
76
76
|
language: "en",
|
|
77
|
+
voice: "F1",
|
|
77
78
|
ttsSpeed: 1.05,
|
|
78
79
|
ttsNumInferenceSteps: 10,
|
|
79
|
-
ttsSupertonicMultilingual: true,
|
|
80
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
81
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
82
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
83
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
84
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
85
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
86
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
87
80
|
},
|
|
88
81
|
onProgress: (progress) => console.log(`TTS load: ${progress.percentage.toFixed(1)}%`),
|
|
89
82
|
});
|
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_MULTILINGUAL_SUPERTONIC2_Q8_0, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Supertonic TTS:
|
|
4
|
-
// Uses registry model constants - downloads automatically from QVAC Registry.
|
|
3
|
+
// Supertonic 2 TTS (GGML): multilingual synthesis (en/ko/es/pt/fr).
|
|
5
4
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
6
5
|
try {
|
|
7
6
|
const modelId = await loadModel({
|
|
8
|
-
modelSrc:
|
|
7
|
+
modelSrc: TTS_MULTILINGUAL_SUPERTONIC2_Q8_0.src,
|
|
9
8
|
modelType: "tts",
|
|
10
9
|
modelConfig: {
|
|
11
10
|
ttsEngine: "supertonic",
|
|
12
11
|
language: "es",
|
|
12
|
+
voice: "F1",
|
|
13
13
|
ttsSpeed: 1.05,
|
|
14
14
|
ttsNumInferenceSteps: 5,
|
|
15
|
-
ttsSupertonicMultilingual: true, //false for English quality.
|
|
16
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
17
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
18
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
19
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
20
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
21
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
22
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
23
15
|
},
|
|
24
16
|
onProgress: (progress) => {
|
|
25
17
|
console.log(progress);
|
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_EN_SUPERTONIC_Q8_0, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Supertonic TTS:
|
|
4
|
-
// Uses registry model constants
|
|
3
|
+
// Supertonic TTS (GGML): fast English synthesis with baked-in voices.
|
|
4
|
+
// Uses registry model constants — downloads automatically from QVAC Registry.
|
|
5
5
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
6
6
|
try {
|
|
7
7
|
const modelId = await loadModel({
|
|
8
|
-
modelSrc:
|
|
8
|
+
modelSrc: TTS_EN_SUPERTONIC_Q8_0.src,
|
|
9
9
|
modelType: "tts",
|
|
10
10
|
modelConfig: {
|
|
11
11
|
ttsEngine: "supertonic",
|
|
12
12
|
language: "en",
|
|
13
|
+
voice: "F1",
|
|
13
14
|
ttsSpeed: 1.05,
|
|
14
15
|
ttsNumInferenceSteps: 5,
|
|
15
|
-
ttsSupertonicMultilingual: false, //false for English quality.
|
|
16
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
17
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
18
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
19
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
20
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
21
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
22
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
23
16
|
},
|
|
24
17
|
onProgress: (progress) => {
|
|
25
18
|
console.log(progress);
|