@qvac/sdk 0.13.5 → 0.14.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 +95 -1151
- package/README.md +1 -2
- package/bare-imports.json +0 -5
- package/dist/client/api/bci-transcribe.js +2 -1
- package/dist/client/api/download-asset.js +2 -1
- package/dist/client/api/finetune.js +6 -5
- package/dist/client/api/index.d.ts +1 -0
- package/dist/client/api/index.js +1 -0
- package/dist/client/api/load-model.d.ts +11 -8
- package/dist/client/api/load-model.js +6 -6
- package/dist/client/api/subscribe-logs.d.ts +28 -0
- package/dist/client/api/subscribe-logs.js +43 -0
- package/dist/client/api/text-to-speech.js +2 -1
- package/dist/client/config-loader/config-utils.js +2 -4
- package/dist/client/config-loader/resolve-config.bare.js +4 -3
- package/dist/client/parse-input.d.ts +3 -0
- package/dist/client/parse-input.js +14 -0
- package/dist/client/rpc/expo-rpc-client.js +2 -11
- package/dist/client/rpc/node-rpc-client.js +8 -2
- package/dist/client/rpc/rpc-client.js +39 -7
- package/dist/commands/bundle/constants.js +2 -1
- package/dist/examples/bci/bci-filesystem-streaming.js +14 -14
- package/dist/examples/bci/bci-filesystem.js +17 -13
- package/dist/examples/cache-management.js +38 -38
- package/dist/examples/cancel-by-request-id.js +9 -9
- package/dist/examples/completion-events.js +20 -14
- package/dist/examples/completion-stop-reason.js +13 -7
- package/dist/examples/concurrent-completion-collision.js +7 -7
- package/dist/examples/config-reload.js +7 -8
- package/dist/examples/default-config-usage.js +4 -4
- package/dist/examples/delegated-inference/composite.js +14 -10
- package/dist/examples/delegated-inference/consumer-profiled.js +13 -13
- package/dist/examples/delegated-inference/consumer.js +16 -12
- package/dist/examples/delegated-inference/provider.js +12 -12
- package/dist/examples/diffusion-esrgan-upscale.js +19 -15
- package/dist/examples/diffusion-flux2-klein-img2img.js +16 -11
- package/dist/examples/diffusion-flux2-klein.js +14 -9
- package/dist/examples/diffusion-img2img.js +9 -10
- package/dist/examples/diffusion-img2vid.js +17 -12
- package/dist/examples/diffusion-simple.js +1 -1
- package/dist/examples/diffusion-txt2img.js +14 -9
- package/dist/examples/diffusion-txt2vid.js +15 -10
- package/dist/examples/download-with-blind-relays.js +16 -21
- package/dist/examples/download-with-cancel.js +15 -16
- package/dist/examples/embed-multi-gpu.js +3 -4
- package/dist/examples/embed-p2p.js +11 -7
- package/dist/examples/finetune/llamacpp-finetune.js +7 -7
- package/dist/examples/kv-cache-cleanup.js +35 -35
- package/dist/examples/kv-cache-custom-key.js +24 -24
- package/dist/examples/kv-cache-example.js +9 -9
- package/dist/examples/llamacpp-cache.js +18 -14
- package/dist/examples/llamacpp-dynamic-tools.js +15 -9
- package/dist/examples/llamacpp-filesystem.js +15 -9
- package/dist/examples/llamacpp-http.js +12 -10
- package/dist/examples/llamacpp-multi-gpu.js +4 -4
- package/dist/examples/llamacpp-multimodal.js +13 -9
- package/dist/examples/llamacpp-p2p.js +8 -4
- package/dist/examples/llamacpp-sharded.js +5 -5
- package/dist/examples/llamacpp-structured-output.js +15 -9
- package/dist/examples/logging-file-transport.js +3 -3
- package/dist/examples/logging-global.d.ts +2 -0
- package/dist/examples/logging-global.js +34 -0
- package/dist/examples/logging-streaming.js +7 -10
- package/dist/examples/mcp-websearch.js +24 -18
- package/dist/examples/multi-model-demo.js +17 -11
- package/dist/examples/ocr-fasttext.js +14 -16
- package/dist/examples/parallel-download.js +7 -7
- package/dist/examples/plugins.js +40 -28
- package/dist/examples/profiling/basic.js +16 -10
- package/dist/examples/profiling/per-call.js +17 -11
- package/dist/examples/quickstart.bare.d.ts +2 -0
- package/dist/examples/quickstart.bare.js +18 -0
- package/dist/examples/quickstart.js +10 -3
- package/dist/examples/rag/rag-chromadb.js +18 -14
- package/dist/examples/rag/rag-hyperdb/cancellation.js +17 -14
- package/dist/examples/rag/rag-hyperdb/ingest.js +14 -12
- package/dist/examples/rag/rag-hyperdb/pipeline.js +19 -17
- package/dist/examples/rag/rag-hyperdb/workspaces.js +31 -27
- package/dist/examples/rag/rag-lancedb.js +12 -8
- package/dist/examples/rag/rag-sqlite.js +11 -7
- package/dist/examples/registry-query.js +17 -17
- package/dist/examples/seed-p2p.js +10 -6
- package/dist/examples/suspend-resume.js +20 -16
- package/dist/examples/tools/llamacpp-native-tools.js +24 -18
- package/dist/examples/tools/llamacpp-tools-gemma4.js +14 -8
- package/dist/examples/tools/llamacpp-tools-harmony-multiturn.js +20 -14
- package/dist/examples/tools/llamacpp-tools-pythonic.js +14 -8
- package/dist/examples/tools/llamacpp-tools-qwen35.js +14 -8
- package/dist/examples/transcription/parakeet-ctc-filesystem.js +12 -9
- package/dist/examples/transcription/parakeet-microphone-record.js +15 -9
- package/dist/examples/transcription/parakeet-microphone-stream.js +15 -9
- package/dist/examples/transcription/parakeet-sortformer-streaming.js +12 -6
- package/dist/examples/transcription/parakeet-sortformer.js +3 -5
- package/dist/examples/transcription/parakeet-tdt-filesystem.js +13 -10
- package/dist/examples/transcription/whispercpp-filesystem-streaming.js +16 -17
- package/dist/examples/transcription/whispercpp-filesystem.js +14 -10
- package/dist/examples/transcription/whispercpp-microphone-conversation.js +10 -10
- package/dist/examples/transcription/whispercpp-microphone-record.js +6 -6
- package/dist/examples/transcription/whispercpp-prompt.js +14 -10
- package/dist/examples/translation/translation-bergamot-batch.js +11 -7
- package/dist/examples/translation/translation-bergamot-pivot.js +13 -9
- package/dist/examples/translation/translation-bergamot.js +8 -4
- package/dist/examples/translation/translation-indic.js +8 -4
- package/dist/examples/translation/translation-llm-afriquegemma.js +7 -3
- package/dist/examples/translation/translation-llm-context.js +8 -4
- package/dist/examples/translation/translation-llm.js +7 -3
- package/dist/examples/translation/translation-stream.js +4 -4
- package/dist/examples/tts/chatterbox.js +19 -11
- package/dist/examples/tts/llm-to-tts-streaming.js +27 -14
- package/dist/examples/tts/supertonic-multilingual.js +18 -14
- package/dist/examples/tts/supertonic.js +19 -15
- package/dist/examples/tts/utils.js +1 -1
- package/dist/examples/vla-pi05.js +18 -14
- package/dist/examples/vla-smolvla.js +18 -14
- package/dist/examples/voice-assistant/voice-assistant.js +12 -12
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/logging/client-logger.js +2 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/logging/namespaces.d.ts +1 -0
- package/dist/logging/namespaces.js +2 -0
- package/dist/logging/server-logger.js +1 -4
- package/dist/logging/utils.js +6 -1
- package/dist/models/registry/index.d.ts +17 -0
- package/dist/models/registry/index.js +20 -1
- package/dist/models/registry/models.d.ts +1062 -38
- package/dist/models/registry/models.js +3546 -2490
- package/dist/pear/pre.js +2 -2
- package/dist/schemas/bci-config.d.ts +37 -0
- package/dist/schemas/bci-config.js +2 -0
- package/dist/schemas/bci.d.ts +2 -0
- package/dist/schemas/common.d.ts +171 -94
- package/dist/schemas/completion-stream.d.ts +6 -3
- package/dist/schemas/completion-stream.js +10 -2
- package/dist/schemas/download-asset.d.ts +5 -5
- package/dist/schemas/engine-addon-map.d.ts +1 -1
- package/dist/schemas/engine-addon-map.js +6 -3
- package/dist/schemas/error.js +6 -1
- package/dist/schemas/llamacpp-config.d.ts +27 -8
- package/dist/schemas/llamacpp-config.js +19 -2
- package/dist/schemas/load-model.d.ts +4170 -570
- package/dist/schemas/load-model.js +85 -26
- package/dist/schemas/logging-stream.js +7 -1
- package/dist/schemas/model-src-utils.d.ts +6 -6
- package/dist/schemas/model-types.d.ts +14 -15
- package/dist/schemas/model-types.js +10 -11
- package/dist/schemas/ocr.d.ts +10 -8
- package/dist/schemas/ocr.js +8 -6
- package/dist/schemas/plugin.d.ts +6 -5
- package/dist/schemas/plugin.js +4 -4
- package/dist/schemas/rag.d.ts +4 -4
- package/dist/schemas/registry.d.ts +8 -8
- package/dist/schemas/registry.js +1 -1
- package/dist/schemas/reload-config.d.ts +6 -6
- package/dist/schemas/sdcpp-config.d.ts +12 -12
- package/dist/schemas/sdk-config.d.ts +171 -117
- package/dist/schemas/sdk-config.js +5 -5
- package/dist/schemas/sdk-errors-client.d.ts +1 -0
- package/dist/schemas/sdk-errors-client.js +7 -2
- package/dist/schemas/text-to-speech.d.ts +157 -13
- package/dist/schemas/text-to-speech.js +70 -7
- package/dist/schemas/transcription-config.d.ts +5 -1
- package/dist/schemas/transcription-config.js +2 -0
- package/dist/schemas/transcription.d.ts +3 -0
- package/dist/schemas/transcription.js +2 -1
- package/dist/schemas/translate.d.ts +6 -6
- package/dist/schemas/translate.js +2 -3
- package/dist/schemas/translation-config.d.ts +20 -20
- package/dist/server/bare/hyperswarm.js +3 -3
- package/dist/server/bare/ops/transcribe.js +46 -15
- package/dist/server/bare/plugins/bci-whispercpp-transcription/args.d.ts +3 -0
- package/dist/server/bare/plugins/bci-whispercpp-transcription/args.js +13 -0
- package/dist/server/bare/plugins/bci-whispercpp-transcription/plugin.d.ts +41 -0
- package/dist/server/bare/plugins/bci-whispercpp-transcription/plugin.js +6 -11
- package/dist/server/bare/plugins/bci-whispercpp-transcription/resolve-config.d.ts +75 -0
- package/dist/server/bare/plugins/bci-whispercpp-transcription/resolve-config.js +11 -0
- package/dist/server/bare/plugins/{onnx-ocr → ggml-ocr}/plugin.d.ts +16 -10
- package/dist/server/bare/plugins/{onnx-ocr → ggml-ocr}/plugin.js +25 -18
- package/dist/server/bare/plugins/index.d.ts +1 -1
- package/dist/server/bare/plugins/index.js +1 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.d.ts +10 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.js +29 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +4 -22
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +15 -7
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +7 -7
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +2 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +10 -10
- package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +14 -8
- package/dist/server/bare/plugins/tts-ggml/plugin.js +12 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +3 -1
- package/dist/server/bare/registry/logging-stream-registry.d.ts +4 -2
- package/dist/server/bare/registry/logging-stream-registry.js +12 -7
- package/dist/server/bare/registry/model-config-utils.js +2 -2
- package/dist/server/bare/registry/registry-client.js +1 -1
- package/dist/server/bare/runtime-lifecycle.d.ts +9 -0
- package/dist/server/bare/runtime-lifecycle.js +24 -0
- package/dist/server/bare/types/addon-responses.d.ts +1 -0
- package/dist/server/env.js +7 -10
- package/dist/server/plugins/registry.js +2 -4
- package/dist/server/rpc/handlers/load-model/handler.js +2 -4
- package/dist/server/rpc/handlers/load-model/http.js +253 -51
- package/dist/server/rpc/handlers/logging-stream.js +4 -2
- package/dist/server/rpc/handlers/plugin-invoke.js +5 -16
- package/dist/server/utils/completion-normalizer.js +13 -4
- package/dist/server/utils/worker-lock.js +5 -5
- package/dist/server/worker-core.d.ts +1 -1
- package/dist/server/worker-core.js +28 -18
- package/dist/utils/errors-client.d.ts +3 -0
- package/dist/utils/errors-client.js +5 -0
- package/dist/utils/errors-server.d.ts +2 -0
- package/dist/utils/errors-server.js +3 -0
- package/dist/utils/zod-error.d.ts +3 -0
- package/dist/utils/zod-error.js +4 -0
- package/package.json +21 -24
- package/dist/polyfills/bare-globals.d.ts +0 -2
- package/dist/polyfills/bare-globals.js +0 -4
- package/dist/polyfills/bare-globals.noop.d.ts +0 -2
- package/dist/polyfills/bare-globals.noop.js +0 -1
- /package/dist/server/bare/plugins/{onnx-ocr → ggml-ocr}/ops/ocr-stream.d.ts +0 -0
- /package/dist/server/bare/plugins/{onnx-ocr → ggml-ocr}/ops/ocr-stream.js +0 -0
|
@@ -26,17 +26,17 @@ try {
|
|
|
26
26
|
throw new Error("FFmpeg not found");
|
|
27
27
|
}
|
|
28
28
|
catch {
|
|
29
|
-
console.error("
|
|
29
|
+
console.error("✖ FFmpeg is required. Install it and try again.");
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
let modelId = null;
|
|
33
33
|
let ffmpeg = null;
|
|
34
34
|
async function cleanup() {
|
|
35
|
-
console.log("\n\
|
|
35
|
+
console.log("\n\n▸ Stopping...");
|
|
36
36
|
ffmpeg?.kill();
|
|
37
37
|
if (modelId)
|
|
38
38
|
await unloadModel({ modelId });
|
|
39
|
-
console.log("Done.");
|
|
39
|
+
console.log("▸ Done.");
|
|
40
40
|
}
|
|
41
41
|
process.on("SIGINT", () => {
|
|
42
42
|
void cleanup().finally(() => process.exit(0));
|
|
@@ -45,7 +45,7 @@ process.on("SIGTERM", () => {
|
|
|
45
45
|
void cleanup().finally(() => process.exit(0));
|
|
46
46
|
});
|
|
47
47
|
try {
|
|
48
|
-
console.log("Loading model (whisper-tiny + Silero VAD)...");
|
|
48
|
+
console.log("▸ Loading model (whisper-tiny + Silero VAD)...");
|
|
49
49
|
modelId = await loadModel({
|
|
50
50
|
modelSrc: WHISPER_TINY,
|
|
51
51
|
modelConfig: {
|
|
@@ -67,7 +67,7 @@ try {
|
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
});
|
|
70
|
-
console.log("Model loaded.\n");
|
|
70
|
+
console.log("▸ Model loaded.\n");
|
|
71
71
|
ffmpeg = startMicrophone({ sampleRate: SAMPLE_RATE, format: "f32le" });
|
|
72
72
|
const session = await transcribeStream({
|
|
73
73
|
modelId,
|
|
@@ -75,7 +75,7 @@ try {
|
|
|
75
75
|
endOfTurnSilenceMs: 800,
|
|
76
76
|
});
|
|
77
77
|
ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
|
|
78
|
-
console.log("Listening... speak and pause to see transcripts, VAD events, and end-of-turn signals.\n");
|
|
78
|
+
console.log("▸ Listening... speak and pause to see transcripts, VAD events, and end-of-turn signals.\n");
|
|
79
79
|
let lastSpeaking = false;
|
|
80
80
|
for await (const event of session) {
|
|
81
81
|
switch (event.type) {
|
|
@@ -84,23 +84,23 @@ try {
|
|
|
84
84
|
break;
|
|
85
85
|
case "vad":
|
|
86
86
|
if (event.speaking !== lastSpeaking) {
|
|
87
|
-
console.log(
|
|
87
|
+
console.log(`▸ [vad] speaking=${event.speaking} probability=${event.probability.toFixed(2)}`);
|
|
88
88
|
lastSpeaking = event.speaking;
|
|
89
89
|
}
|
|
90
90
|
break;
|
|
91
91
|
case "endOfTurn":
|
|
92
92
|
if (event.source === "whisper") {
|
|
93
|
-
console.log(
|
|
93
|
+
console.log(`▸ [endOfTurn] silence ${event.silenceDurationMs}ms — turn complete\n`);
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
|
-
console.log(
|
|
96
|
+
console.log(`▸ [endOfTurn] turn complete (token-driven EOU)\n`);
|
|
97
97
|
}
|
|
98
98
|
break;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
catch (error) {
|
|
103
|
-
console.error("
|
|
103
|
+
console.error("✖", error);
|
|
104
104
|
await cleanup();
|
|
105
105
|
process.exit(1);
|
|
106
106
|
}
|
|
@@ -19,10 +19,10 @@ try {
|
|
|
19
19
|
throw new Error("FFmpeg not found");
|
|
20
20
|
}
|
|
21
21
|
catch {
|
|
22
|
-
console.error("FFmpeg is required. Install it and try again.");
|
|
22
|
+
console.error("✖ FFmpeg is required. Install it and try again.");
|
|
23
23
|
process.exit(1);
|
|
24
24
|
}
|
|
25
|
-
console.log("Loading model (whisper-tiny + Silero VAD)...");
|
|
25
|
+
console.log("▸ Loading model (whisper-tiny + Silero VAD)...");
|
|
26
26
|
const modelId = await loadModel({
|
|
27
27
|
modelSrc: WHISPER_TINY,
|
|
28
28
|
modelConfig: {
|
|
@@ -44,22 +44,22 @@ const modelId = await loadModel({
|
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
46
|
});
|
|
47
|
-
console.log("Model loaded.\n");
|
|
47
|
+
console.log("▸ Model loaded.\n");
|
|
48
48
|
const ffmpeg = startMicrophone({
|
|
49
49
|
sampleRate: SAMPLE_RATE,
|
|
50
50
|
format: "f32le",
|
|
51
51
|
});
|
|
52
52
|
const session = await transcribeStream({ modelId });
|
|
53
53
|
ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
|
|
54
|
-
console.log("Listening... speak and pause to see transcriptions.\n");
|
|
54
|
+
console.log("▸ Listening... speak and pause to see transcriptions.\n");
|
|
55
55
|
for await (const text of session) {
|
|
56
56
|
console.log(`> ${text.trim()}`);
|
|
57
57
|
}
|
|
58
58
|
async function cleanup() {
|
|
59
|
-
console.log("\n\
|
|
59
|
+
console.log("\n\n▸ Stopping...");
|
|
60
60
|
ffmpeg.kill();
|
|
61
61
|
await unloadModel({ modelId });
|
|
62
|
-
console.log("Done.");
|
|
62
|
+
console.log("▸ Done.");
|
|
63
63
|
}
|
|
64
64
|
process.on("SIGINT", () => void cleanup());
|
|
65
65
|
process.on("SIGTERM", () => void cleanup());
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { loadModel, unloadModel, transcribe, WHISPER_TINY } from "@qvac/sdk";
|
|
13
13
|
try {
|
|
14
|
-
console.log("
|
|
14
|
+
console.log("▸ Starting Whisper transcription with prompt example...");
|
|
15
15
|
// Load the Whisper model
|
|
16
|
-
console.log("
|
|
16
|
+
console.log("▸ Loading Whisper model...");
|
|
17
17
|
const modelId = await loadModel({
|
|
18
18
|
modelSrc: WHISPER_TINY,
|
|
19
19
|
modelConfig: {
|
|
@@ -51,27 +51,31 @@ try {
|
|
|
51
51
|
gpu_device: 0,
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
|
-
onProgress: (
|
|
55
|
-
|
|
54
|
+
onProgress: (p) => {
|
|
55
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
56
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
57
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
58
|
+
if (p.percentage >= 100)
|
|
59
|
+
process.stderr.write("\n");
|
|
56
60
|
},
|
|
57
61
|
});
|
|
58
|
-
console.log(
|
|
62
|
+
console.log(`▸ Whisper model loaded with ID: ${modelId}`);
|
|
59
63
|
// Perform transcription
|
|
60
|
-
console.log("
|
|
64
|
+
console.log("▸ Transcribing audio...");
|
|
61
65
|
const text = await transcribe({
|
|
62
66
|
modelId,
|
|
63
67
|
audioChunk: "examples/audio/sample-16khz.wav",
|
|
64
68
|
prompt: "This is a test recording with clear speech and proper punctuation.",
|
|
65
69
|
});
|
|
66
|
-
console.log("
|
|
70
|
+
console.log("▸ Transcription result:");
|
|
67
71
|
console.log(text);
|
|
68
72
|
// Unload the model when done
|
|
69
|
-
console.log("
|
|
73
|
+
console.log("▸ Unloading Whisper model...");
|
|
70
74
|
await unloadModel({ modelId });
|
|
71
|
-
console.log("
|
|
75
|
+
console.log("▸ Whisper model unloaded successfully");
|
|
72
76
|
process.exit(0);
|
|
73
77
|
}
|
|
74
78
|
catch (error) {
|
|
75
|
-
console.error("
|
|
79
|
+
console.error("✖", error);
|
|
76
80
|
process.exit(1);
|
|
77
81
|
}
|
|
@@ -12,11 +12,15 @@ try {
|
|
|
12
12
|
norepeatngramsize: 3,
|
|
13
13
|
lengthpenalty: 1.2,
|
|
14
14
|
},
|
|
15
|
-
onProgress: (
|
|
16
|
-
|
|
15
|
+
onProgress: (p) => {
|
|
16
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
17
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
18
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
19
|
+
if (p.percentage >= 100)
|
|
20
|
+
process.stderr.write("\n");
|
|
17
21
|
},
|
|
18
22
|
});
|
|
19
|
-
console.log(
|
|
23
|
+
console.log(`▸ Bergamot model loaded: ${modelId}`);
|
|
20
24
|
// Test with array of texts for batch processing
|
|
21
25
|
const texts = [
|
|
22
26
|
"Hello world",
|
|
@@ -24,8 +28,8 @@ try {
|
|
|
24
28
|
"This is a test of batch translation",
|
|
25
29
|
"The weather is nice",
|
|
26
30
|
];
|
|
27
|
-
console.log("
|
|
28
|
-
texts.forEach((text, i) => console.log(
|
|
31
|
+
console.log("▸ Translating batch of texts:");
|
|
32
|
+
texts.forEach((text, i) => console.log(`▸ ${i + 1}. ${text}`));
|
|
29
33
|
const result = translate({
|
|
30
34
|
modelId,
|
|
31
35
|
text: texts, // Pass array for batch processing
|
|
@@ -34,7 +38,7 @@ try {
|
|
|
34
38
|
});
|
|
35
39
|
const translatedText = await result.text;
|
|
36
40
|
const translations = translatedText.split("\n");
|
|
37
|
-
console.log("
|
|
41
|
+
console.log("▸ Translations:");
|
|
38
42
|
translations.forEach((translation, i) => {
|
|
39
43
|
if (i < texts.length) {
|
|
40
44
|
console.log(` ${i + 1}. ${texts[i]} -> "${translation}"`);
|
|
@@ -43,6 +47,6 @@ try {
|
|
|
43
47
|
await unloadModel({ modelId });
|
|
44
48
|
}
|
|
45
49
|
catch (error) {
|
|
46
|
-
console.error("
|
|
50
|
+
console.error("✖", error);
|
|
47
51
|
process.exit(1);
|
|
48
52
|
}
|
|
@@ -36,18 +36,22 @@ try {
|
|
|
36
36
|
lengthpenalty: 1.2,
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
|
-
onProgress: (
|
|
40
|
-
|
|
39
|
+
onProgress: (p) => {
|
|
40
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
41
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
42
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
43
|
+
if (p.percentage >= 100)
|
|
44
|
+
process.stderr.write("\n");
|
|
41
45
|
},
|
|
42
46
|
});
|
|
43
|
-
console.log(
|
|
44
|
-
console.log("
|
|
45
|
-
console.log("
|
|
47
|
+
console.log(`▸ Pivot translation model loaded: ${modelId}`);
|
|
48
|
+
console.log("▸ Primary: Spanish → English");
|
|
49
|
+
console.log("▸ Pivot: English → Italian");
|
|
46
50
|
// Spanish text to translate
|
|
47
51
|
const spanishText = `Era una mañana soleada cuando María decidió visitar el mercado local.
|
|
48
52
|
Compró frutas frescas, verduras y flores para su casa.
|
|
49
53
|
El vendedor le recomendó las mejores manzanas de la temporada.`;
|
|
50
|
-
console.log("
|
|
54
|
+
console.log("▸ Original Spanish text:");
|
|
51
55
|
console.log(spanishText);
|
|
52
56
|
// Translate Spanish → English → Italian
|
|
53
57
|
const result = translate({
|
|
@@ -57,16 +61,16 @@ try {
|
|
|
57
61
|
stream: false,
|
|
58
62
|
});
|
|
59
63
|
const italianText = await result.text;
|
|
60
|
-
console.log("
|
|
64
|
+
console.log("▸ Translated to Italian (via English):");
|
|
61
65
|
console.log(italianText);
|
|
62
66
|
// Expected output (approximate):
|
|
63
67
|
// "Era una mattina di sole quando Maria decise di visitare il mercato locale.
|
|
64
68
|
// Ha comprato frutta fresca, verdura e fiori per la sua casa.
|
|
65
69
|
// Il venditore ha consigliato le migliori mele della stagione."
|
|
66
70
|
await unloadModel({ modelId });
|
|
67
|
-
console.log("
|
|
71
|
+
console.log("▸ Model unloaded successfully");
|
|
68
72
|
}
|
|
69
73
|
catch (error) {
|
|
70
|
-
console.error("
|
|
74
|
+
console.error("✖", error);
|
|
71
75
|
process.exit(1);
|
|
72
76
|
}
|
|
@@ -16,11 +16,15 @@ try {
|
|
|
16
16
|
norepeatngramsize: 3,
|
|
17
17
|
lengthpenalty: 1.2,
|
|
18
18
|
},
|
|
19
|
-
onProgress: (
|
|
20
|
-
|
|
19
|
+
onProgress: (p) => {
|
|
20
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
21
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
22
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
23
|
+
if (p.percentage >= 100)
|
|
24
|
+
process.stderr.write("\n");
|
|
21
25
|
},
|
|
22
26
|
});
|
|
23
|
-
console.log(
|
|
27
|
+
console.log(`▸ Bergamot model loaded: ${modelId}`);
|
|
24
28
|
const text = "This is a test of the Bergamot translation model.";
|
|
25
29
|
const result = translate({
|
|
26
30
|
modelId,
|
|
@@ -33,6 +37,6 @@ try {
|
|
|
33
37
|
await unloadModel({ modelId });
|
|
34
38
|
}
|
|
35
39
|
catch (error) {
|
|
36
|
-
console.error("
|
|
40
|
+
console.error("✖", error);
|
|
37
41
|
process.exit(1);
|
|
38
42
|
}
|
|
@@ -5,8 +5,12 @@ import { loadModel, translate, unloadModel, MARIAN_EN_HI_INDIC_1B_Q4_0, } from "
|
|
|
5
5
|
try {
|
|
6
6
|
const modelId = await loadModel({
|
|
7
7
|
modelSrc: MARIAN_EN_HI_INDIC_1B_Q4_0,
|
|
8
|
-
onProgress: (
|
|
9
|
-
|
|
8
|
+
onProgress: (p) => {
|
|
9
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
10
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
11
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
12
|
+
if (p.percentage >= 100)
|
|
13
|
+
process.stderr.write("\n");
|
|
10
14
|
},
|
|
11
15
|
modelConfig: {
|
|
12
16
|
engine: "IndicTrans",
|
|
@@ -14,7 +18,7 @@ try {
|
|
|
14
18
|
to: "hin_Deva",
|
|
15
19
|
},
|
|
16
20
|
});
|
|
17
|
-
console.log(
|
|
21
|
+
console.log(`▸ Model loaded: ${modelId}`);
|
|
18
22
|
const text = "Hello, how are you today?";
|
|
19
23
|
const result = translate({
|
|
20
24
|
modelId,
|
|
@@ -27,6 +31,6 @@ try {
|
|
|
27
31
|
await unloadModel({ modelId });
|
|
28
32
|
}
|
|
29
33
|
catch (error) {
|
|
30
|
-
console.error("
|
|
34
|
+
console.error("✖", error);
|
|
31
35
|
process.exit(1);
|
|
32
36
|
}
|
|
@@ -2,8 +2,12 @@ import { translate, loadModel, unloadModel, AFRICAN_4B_TRANSLATION_Q4_K_M, } fro
|
|
|
2
2
|
try {
|
|
3
3
|
const modelId = await loadModel({
|
|
4
4
|
modelSrc: AFRICAN_4B_TRANSLATION_Q4_K_M,
|
|
5
|
-
onProgress: (
|
|
6
|
-
|
|
5
|
+
onProgress: (p) => {
|
|
6
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
7
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
8
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
9
|
+
if (p.percentage >= 100)
|
|
10
|
+
process.stderr.write("\n");
|
|
7
11
|
},
|
|
8
12
|
// IMPORTANT: these parameters are validated to be optimal
|
|
9
13
|
modelConfig: {
|
|
@@ -33,6 +37,6 @@ try {
|
|
|
33
37
|
await unloadModel({ modelId, clearStorage: false });
|
|
34
38
|
}
|
|
35
39
|
catch (error) {
|
|
36
|
-
console.error("
|
|
40
|
+
console.error("✖", error);
|
|
37
41
|
process.exit(1);
|
|
38
42
|
}
|
|
@@ -2,11 +2,15 @@ import { translate, loadModel, unloadModel, SALAMANDRATA_2B_INST_Q8, } from "@qv
|
|
|
2
2
|
try {
|
|
3
3
|
const modelId = await loadModel({
|
|
4
4
|
modelSrc: SALAMANDRATA_2B_INST_Q8,
|
|
5
|
-
onProgress: (
|
|
6
|
-
|
|
5
|
+
onProgress: (p) => {
|
|
6
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
7
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
8
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
9
|
+
if (p.percentage >= 100)
|
|
10
|
+
process.stderr.write("\n");
|
|
7
11
|
},
|
|
8
12
|
});
|
|
9
|
-
console.log(
|
|
13
|
+
console.log(`▸ Model loaded: ${modelId}`);
|
|
10
14
|
// With explicit source language
|
|
11
15
|
const engText = "bank";
|
|
12
16
|
const resultExplicit = translate({
|
|
@@ -23,6 +27,6 @@ try {
|
|
|
23
27
|
await unloadModel({ modelId, clearStorage: false });
|
|
24
28
|
}
|
|
25
29
|
catch (error) {
|
|
26
|
-
console.error("
|
|
30
|
+
console.error("✖", error);
|
|
27
31
|
process.exit(1);
|
|
28
32
|
}
|
|
@@ -2,8 +2,12 @@ import { translate, loadModel, unloadModel, SALAMANDRATA_2B_INST_Q4, } from "@qv
|
|
|
2
2
|
try {
|
|
3
3
|
const modelId = await loadModel({
|
|
4
4
|
modelSrc: SALAMANDRATA_2B_INST_Q4,
|
|
5
|
-
onProgress: (
|
|
6
|
-
|
|
5
|
+
onProgress: (p) => {
|
|
6
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
7
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
8
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
9
|
+
if (p.percentage >= 100)
|
|
10
|
+
process.stderr.write("\n");
|
|
7
11
|
},
|
|
8
12
|
});
|
|
9
13
|
// With explicit source language
|
|
@@ -32,6 +36,6 @@ try {
|
|
|
32
36
|
await unloadModel({ modelId, clearStorage: false });
|
|
33
37
|
}
|
|
34
38
|
catch (error) {
|
|
35
|
-
console.error("
|
|
39
|
+
console.error("✖", error);
|
|
36
40
|
process.exit(1);
|
|
37
41
|
}
|
|
@@ -8,9 +8,9 @@ try {
|
|
|
8
8
|
to: "es",
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
|
-
console.log(
|
|
11
|
+
console.log(`▸ Model loaded: ${modelId}`);
|
|
12
12
|
const text = "Hello, how are you today? I hope you are having a wonderful day!";
|
|
13
|
-
console.log("
|
|
13
|
+
console.log("▸ Streaming Translation");
|
|
14
14
|
const streamResult = translate({
|
|
15
15
|
modelId,
|
|
16
16
|
text,
|
|
@@ -24,11 +24,11 @@ try {
|
|
|
24
24
|
console.log();
|
|
25
25
|
const stats = await streamResult.stats;
|
|
26
26
|
if (stats) {
|
|
27
|
-
console.log(
|
|
27
|
+
console.log(`▸ Processing stats:`, stats);
|
|
28
28
|
}
|
|
29
29
|
await unloadModel({ modelId, clearStorage: false });
|
|
30
30
|
}
|
|
31
31
|
catch (error) {
|
|
32
|
-
console.error("
|
|
32
|
+
console.error("✖", error);
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
@@ -12,14 +12,22 @@ try {
|
|
|
12
12
|
ttsEngine: "chatterbox",
|
|
13
13
|
language: "en",
|
|
14
14
|
s3genModelSrc: TTS_S3GEN_EN_CHATTERBOX.src,
|
|
15
|
+
streamChunkTokens: 25,
|
|
16
|
+
streamFirstChunkTokens: 10,
|
|
17
|
+
cfmSteps: 1,
|
|
18
|
+
threads: 8,
|
|
15
19
|
...(referenceAudioSrc ? { referenceAudioSrc } : {}),
|
|
16
20
|
},
|
|
17
|
-
onProgress: (
|
|
18
|
-
|
|
21
|
+
onProgress: (p) => {
|
|
22
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
23
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
24
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
25
|
+
if (p.percentage >= 100)
|
|
26
|
+
process.stderr.write("\n");
|
|
19
27
|
},
|
|
20
28
|
});
|
|
21
|
-
console.log(
|
|
22
|
-
console.log("
|
|
29
|
+
console.log(`▸ Model loaded: ${modelId}`);
|
|
30
|
+
console.log("▸ Testing Text-to-Speech...");
|
|
23
31
|
const result = textToSpeech({
|
|
24
32
|
modelId,
|
|
25
33
|
text: `QVAC SDK is the canonical entry point to QVAC. Written in TypeScript, it provides all QVAC capabilities through a unified interface while also abstracting away the complexity of running your application in a JS environment other than Bare. Supported JS environments include Bare, Node.js, Expo and Bun.`,
|
|
@@ -27,23 +35,23 @@ try {
|
|
|
27
35
|
stream: false,
|
|
28
36
|
});
|
|
29
37
|
const audioBuffer = await result.buffer;
|
|
30
|
-
console.log(
|
|
31
|
-
console.log("
|
|
38
|
+
console.log(`▸ TTS complete. Total bytes: ${audioBuffer.length}`);
|
|
39
|
+
console.log("▸ Saving audio to file...");
|
|
32
40
|
createWav(audioBuffer, CHATTERBOX_SAMPLE_RATE, "tts-output.wav");
|
|
33
|
-
console.log("
|
|
34
|
-
console.log("
|
|
41
|
+
console.log("▸ Audio saved to tts-output.wav");
|
|
42
|
+
console.log("▸ Playing audio...");
|
|
35
43
|
const audioData = int16ArrayToBuffer(audioBuffer);
|
|
36
44
|
const wavBuffer = Buffer.concat([
|
|
37
45
|
createWavHeader(audioData.length, CHATTERBOX_SAMPLE_RATE),
|
|
38
46
|
audioData,
|
|
39
47
|
]);
|
|
40
48
|
playAudio(wavBuffer);
|
|
41
|
-
console.log("
|
|
49
|
+
console.log("▸ Audio playback complete");
|
|
42
50
|
await unloadModel({ modelId });
|
|
43
|
-
console.log("Model unloaded");
|
|
51
|
+
console.log("▸ Model unloaded");
|
|
44
52
|
process.exit(0);
|
|
45
53
|
}
|
|
46
54
|
catch (error) {
|
|
47
|
-
console.error("
|
|
55
|
+
console.error("✖", error);
|
|
48
56
|
process.exit(1);
|
|
49
57
|
}
|
|
@@ -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_MULTILINGUAL_SUPERTONIC3_Q8_0, } from "@qvac/sdk";
|
|
16
16
|
import { createWav, playPcmInt16Chunk } from "./utils.js";
|
|
17
17
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
18
18
|
/**
|
|
@@ -57,18 +57,24 @@ function appendPcmSamples(target, chunk) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
try {
|
|
60
|
-
console.log(
|
|
60
|
+
console.log(`▸ Loading LLM from registry: ${LLAMA_3_2_1B_INST_Q4_0.name}`);
|
|
61
61
|
const llmModelId = await loadModel({
|
|
62
62
|
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
63
63
|
modelConfig: {
|
|
64
64
|
ctx_size: 2048,
|
|
65
65
|
},
|
|
66
|
-
onProgress: (
|
|
66
|
+
onProgress: (p) => {
|
|
67
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
68
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
69
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
70
|
+
if (p.percentage >= 100)
|
|
71
|
+
process.stderr.write("\n");
|
|
72
|
+
},
|
|
67
73
|
});
|
|
68
|
-
console.log(
|
|
69
|
-
console.log("Loading Supertonic TTS (registry)…");
|
|
74
|
+
console.log(`▸ LLM ready: ${llmModelId}`);
|
|
75
|
+
console.log("▸ Loading Supertonic TTS (registry)…");
|
|
70
76
|
const ttsModelId = await loadModel({
|
|
71
|
-
modelSrc:
|
|
77
|
+
modelSrc: TTS_MULTILINGUAL_SUPERTONIC3_Q8_0,
|
|
72
78
|
modelConfig: {
|
|
73
79
|
ttsEngine: "supertonic",
|
|
74
80
|
language: "en",
|
|
@@ -76,11 +82,18 @@ try {
|
|
|
76
82
|
ttsSpeed: 1.05,
|
|
77
83
|
ttsNumInferenceSteps: 10,
|
|
78
84
|
},
|
|
79
|
-
onProgress: (
|
|
85
|
+
onProgress: (p) => {
|
|
86
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
87
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
88
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
89
|
+
if (p.percentage >= 100)
|
|
90
|
+
process.stderr.write("\n");
|
|
91
|
+
},
|
|
80
92
|
});
|
|
81
|
-
console.log(
|
|
93
|
+
console.log(`▸ TTS ready: ${ttsModelId}`);
|
|
82
94
|
const prompt = "What is a constellation?";
|
|
83
|
-
console.log(
|
|
95
|
+
console.log(`▸ User: ${prompt}`);
|
|
96
|
+
console.log("▸ Assistant (streaming):");
|
|
84
97
|
const result = completion({
|
|
85
98
|
modelId: llmModelId,
|
|
86
99
|
history: [{ role: "user", content: prompt }],
|
|
@@ -102,7 +115,7 @@ try {
|
|
|
102
115
|
const preview = typeof m.sentenceChunk === "string"
|
|
103
116
|
? m.sentenceChunk.replace(/\s+/g, " ").trim().slice(0, 72)
|
|
104
117
|
: "";
|
|
105
|
-
console.log(`\n[TTS phrase ${phraseIndex}] ${m.buffer.length} samples${preview ? ` — "${preview}${preview.length >= 72 ? "..." : ""}"` : ""}`);
|
|
118
|
+
console.log(`\n▸ [TTS phrase ${phraseIndex}] ${m.buffer.length} samples${preview ? ` — "${preview}${preview.length >= 72 ? "..." : ""}"` : ""}`);
|
|
106
119
|
await playPcmInt16Chunk(m.buffer, SUPERTONIC_SAMPLE_RATE);
|
|
107
120
|
}
|
|
108
121
|
}
|
|
@@ -118,17 +131,17 @@ try {
|
|
|
118
131
|
await drainPcm;
|
|
119
132
|
const stats = await result.stats;
|
|
120
133
|
if (stats) {
|
|
121
|
-
console.log("\
|
|
134
|
+
console.log("\n▸ LLM stats:", stats);
|
|
122
135
|
}
|
|
123
136
|
const outWav = "llm-to-tts-streaming-output.wav";
|
|
124
|
-
console.log(`\
|
|
137
|
+
console.log(`\n▸ Writing ${combinedPcm.length} samples to ${outWav} (full utterance; phrases were already played above).`);
|
|
125
138
|
createWav(combinedPcm, SUPERTONIC_SAMPLE_RATE, outWav);
|
|
126
139
|
await unloadModel({ modelId: llmModelId, clearStorage: false });
|
|
127
140
|
await unloadModel({ modelId: ttsModelId, clearStorage: false });
|
|
128
|
-
console.log("Models unloaded.");
|
|
141
|
+
console.log("▸ Models unloaded.");
|
|
129
142
|
process.exit(0);
|
|
130
143
|
}
|
|
131
144
|
catch (error) {
|
|
132
|
-
console.error("
|
|
145
|
+
console.error("✖", error);
|
|
133
146
|
process.exit(1);
|
|
134
147
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_MULTILINGUAL_SUPERTONIC3_Q8_0, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Supertonic
|
|
3
|
+
// Supertonic 3 TTS (GGML): multilingual synthesis across 31 languages.
|
|
4
4
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
5
5
|
try {
|
|
6
6
|
const modelId = await loadModel({
|
|
7
|
-
modelSrc:
|
|
7
|
+
modelSrc: TTS_MULTILINGUAL_SUPERTONIC3_Q8_0,
|
|
8
8
|
modelConfig: {
|
|
9
9
|
ttsEngine: "supertonic",
|
|
10
10
|
language: "es",
|
|
@@ -12,12 +12,16 @@ try {
|
|
|
12
12
|
ttsSpeed: 1.05,
|
|
13
13
|
ttsNumInferenceSteps: 5,
|
|
14
14
|
},
|
|
15
|
-
onProgress: (
|
|
16
|
-
|
|
15
|
+
onProgress: (p) => {
|
|
16
|
+
const mb = (n) => (n / 1e6).toFixed(1);
|
|
17
|
+
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
|
|
18
|
+
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
|
|
19
|
+
if (p.percentage >= 100)
|
|
20
|
+
process.stderr.write("\n");
|
|
17
21
|
},
|
|
18
22
|
});
|
|
19
|
-
console.log(
|
|
20
|
-
console.log("
|
|
23
|
+
console.log(`▸ Model loaded: ${modelId}`);
|
|
24
|
+
console.log("▸ Testing Text-to-Speech...");
|
|
21
25
|
const result = textToSpeech({
|
|
22
26
|
modelId,
|
|
23
27
|
text: `Hola mundo. Esta es una demostración de síntesis de voz con Supertonic en español.`,
|
|
@@ -25,23 +29,23 @@ try {
|
|
|
25
29
|
stream: false,
|
|
26
30
|
});
|
|
27
31
|
const audioBuffer = await result.buffer;
|
|
28
|
-
console.log(
|
|
29
|
-
console.log("
|
|
32
|
+
console.log(`▸ TTS complete. Total samples: ${audioBuffer.length}`);
|
|
33
|
+
console.log("▸ Saving audio to file...");
|
|
30
34
|
createWav(audioBuffer, SUPERTONIC_SAMPLE_RATE, "supertonic-multilingual-output.wav");
|
|
31
|
-
console.log("
|
|
32
|
-
console.log("
|
|
35
|
+
console.log("▸ Audio saved to supertonic-multilingual-output.wav");
|
|
36
|
+
console.log("▸ Playing audio...");
|
|
33
37
|
const audioData = int16ArrayToBuffer(audioBuffer);
|
|
34
38
|
const wavBuffer = Buffer.concat([
|
|
35
39
|
createWavHeader(audioData.length, SUPERTONIC_SAMPLE_RATE),
|
|
36
40
|
audioData,
|
|
37
41
|
]);
|
|
38
42
|
playAudio(wavBuffer);
|
|
39
|
-
console.log("
|
|
43
|
+
console.log("▸ Audio playback complete");
|
|
40
44
|
await unloadModel({ modelId });
|
|
41
|
-
console.log("Model unloaded");
|
|
45
|
+
console.log("▸ Model unloaded");
|
|
42
46
|
process.exit(0);
|
|
43
47
|
}
|
|
44
48
|
catch (error) {
|
|
45
|
-
console.error("
|
|
49
|
+
console.error("✖", error);
|
|
46
50
|
process.exit(1);
|
|
47
51
|
}
|