@qvac/sdk 0.8.2 → 0.9.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 +267 -63
- package/README.md +2 -0
- package/dist/client/api/diffusion.d.ts +32 -0
- package/dist/client/api/diffusion.js +103 -0
- package/dist/client/api/embed.d.ts +9 -3
- package/dist/client/api/embed.js +4 -1
- package/dist/client/api/finetune.d.ts +69 -0
- package/dist/client/api/finetune.js +139 -0
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/index.d.ts +4 -0
- package/dist/client/api/index.js +4 -0
- package/dist/client/api/rag.d.ts +1 -1
- package/dist/client/api/rag.js +1 -1
- package/dist/client/api/resume.d.ts +14 -0
- package/dist/client/api/resume.js +20 -0
- package/dist/client/api/suspend.d.ts +13 -0
- package/dist/client/api/suspend.js +19 -0
- package/dist/client/api/transcribe.d.ts +25 -17
- package/dist/client/api/transcribe.js +115 -35
- package/dist/client/rpc/bare-client.d.ts +5 -1
- package/dist/client/rpc/bare-client.js +70 -57
- package/dist/client/rpc/expo-rpc-client.d.ts +4 -0
- package/dist/client/rpc/expo-rpc-client.js +8 -0
- package/dist/client/rpc/node-rpc-client.d.ts +4 -0
- package/dist/client/rpc/node-rpc-client.js +8 -0
- package/dist/client/rpc/rpc-client.d.ts +13 -0
- package/dist/client/rpc/rpc-client.js +131 -1
- package/dist/examples/delegated-inference/composite.d.ts +2 -0
- package/dist/examples/delegated-inference/composite.js +99 -0
- package/dist/examples/diffusion-flux2-klein.d.ts +2 -0
- package/dist/examples/diffusion-flux2-klein.js +46 -0
- package/dist/examples/diffusion-simple.d.ts +2 -0
- package/dist/examples/diffusion-simple.js +17 -0
- package/dist/examples/diffusion-txt2img.d.ts +2 -0
- package/dist/examples/diffusion-txt2img.js +40 -0
- package/dist/examples/embed-p2p.js +2 -2
- package/dist/examples/finetune/llamacpp-finetune.d.ts +2 -0
- package/dist/examples/finetune/llamacpp-finetune.js +78 -0
- package/dist/examples/logging-streaming.js +1 -1
- package/dist/examples/mcp-websearch.js +2 -0
- package/dist/examples/ocr-fasttext.js +11 -0
- package/dist/examples/profiling/per-call.js +3 -3
- package/dist/examples/rag/rag-chromadb.js +2 -2
- package/dist/examples/rag/rag-hyperdb/pipeline.js +1 -1
- package/dist/examples/rag/rag-lancedb.js +2 -2
- package/dist/examples/rag/rag-sqlite.js +2 -2
- package/dist/examples/suspend-resume.d.ts +2 -0
- package/dist/examples/suspend-resume.js +52 -0
- package/dist/examples/transcription/parakeet-ctc-filesystem.js +3 -5
- package/dist/examples/transcription/parakeet-microphone-record.js +42 -33
- package/dist/examples/transcription/parakeet-sortformer.js +13 -3
- package/dist/examples/transcription/parakeet-tdt-filesystem.js +5 -7
- package/dist/examples/transcription/whispercpp-filesystem-streaming.d.ts +2 -0
- package/dist/examples/transcription/whispercpp-filesystem-streaming.js +99 -0
- package/dist/examples/transcription/whispercpp-microphone-record.js +78 -299
- package/dist/examples/transcription/whispercpp-prompt.js +11 -0
- package/dist/examples/translation/translation-llm.js +2 -2
- package/dist/examples/tts/supertonic-multilingual.d.ts +2 -0
- package/dist/examples/tts/supertonic-multilingual.js +56 -0
- package/dist/examples/tts/supertonic.js +12 -7
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/logging/utils.js +1 -1
- package/dist/models/registry/models.d.ts +15176 -4264
- package/dist/models/registry/models.js +18657 -7404
- package/dist/models/update-models/codegen.js +2 -2
- package/dist/models/update-models/naming.js +26 -0
- package/dist/pear/pre.js +2 -0
- package/dist/polyfills/bare-globals.d.ts +2 -0
- package/dist/polyfills/bare-globals.js +4 -0
- package/dist/polyfills/bare-globals.noop.d.ts +2 -0
- package/dist/polyfills/bare-globals.noop.js +1 -0
- package/dist/profiling/exporters.js +16 -11
- package/dist/profiling/model-execution.d.ts +16 -0
- package/dist/profiling/model-execution.js +33 -0
- package/dist/schemas/common.d.ts +967 -198
- package/dist/schemas/common.js +16 -1
- package/dist/schemas/completion-stream.d.ts +14 -6
- package/dist/schemas/completion-stream.js +4 -3
- package/dist/schemas/download-asset.d.ts +7 -3
- package/dist/schemas/embed.d.ts +19 -0
- package/dist/schemas/embed.js +7 -0
- package/dist/schemas/engine-addon-map.js +4 -1
- package/dist/schemas/finetune.d.ts +620 -0
- package/dist/schemas/finetune.js +161 -0
- package/dist/schemas/get-model-info.d.ts +2 -0
- package/dist/schemas/get-model-info.js +1 -0
- package/dist/schemas/index.d.ts +5 -1
- package/dist/schemas/index.js +5 -1
- package/dist/schemas/llamacpp-config.d.ts +26 -6
- package/dist/schemas/llamacpp-config.js +12 -0
- package/dist/schemas/load-model.d.ts +4005 -1400
- package/dist/schemas/load-model.js +34 -1
- package/dist/schemas/model-src-utils.d.ts +10 -2
- package/dist/schemas/model-types.d.ts +19 -1
- package/dist/schemas/model-types.js +11 -0
- package/dist/schemas/ocr.d.ts +2 -0
- package/dist/schemas/plugin.d.ts +24 -3
- package/dist/schemas/plugin.js +14 -0
- package/dist/schemas/profiling.d.ts +4 -0
- package/dist/schemas/profiling.js +4 -0
- package/dist/schemas/registry.d.ts +18 -0
- package/dist/schemas/registry.js +2 -0
- package/dist/schemas/reload-config.d.ts +9 -1
- package/dist/schemas/resume.d.ts +10 -0
- package/dist/schemas/resume.js +7 -0
- package/dist/schemas/sdcpp-config.d.ts +327 -0
- package/dist/schemas/sdcpp-config.js +102 -0
- package/dist/schemas/sdk-config.d.ts +1225 -235
- package/dist/schemas/sdk-config.js +4 -0
- package/dist/schemas/sdk-errors-server.d.ts +2 -0
- package/dist/schemas/sdk-errors-server.js +12 -0
- package/dist/schemas/suspend.d.ts +10 -0
- package/dist/schemas/suspend.js +7 -0
- package/dist/schemas/text-to-speech.d.ts +187 -10
- package/dist/schemas/text-to-speech.js +12 -4
- package/dist/schemas/transcription-config.d.ts +16 -56
- package/dist/schemas/transcription-config.js +0 -2
- package/dist/schemas/transcription.d.ts +66 -6
- package/dist/schemas/transcription.js +29 -7
- package/dist/schemas/translate.d.ts +14 -4
- package/dist/schemas/translate.js +10 -2
- package/dist/schemas/translation-config.d.ts +30 -10
- package/dist/server/bare/delegate-rpc-client.js +3 -3
- package/dist/server/bare/hyperswarm.js +15 -3
- package/dist/server/bare/ops/embed.d.ts +8 -4
- package/dist/server/bare/ops/embed.js +15 -4
- package/dist/server/bare/ops/transcribe.d.ts +6 -2
- package/dist/server/bare/ops/transcribe.js +53 -1
- package/dist/server/bare/ops/translate.d.ts +4 -1
- package/dist/server/bare/ops/translate.js +28 -65
- package/dist/server/bare/ops/unload-model.js +2 -0
- package/dist/server/bare/plugins/index.d.ts +1 -0
- package/dist/server/bare/plugins/index.js +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.d.ts +1 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +3 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +3 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +57 -11
- package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.d.ts +11 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +112 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +175 -5
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +45 -35
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +11 -1
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +9 -4
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +17 -2
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +16 -15
- package/dist/server/bare/plugins/onnx-ocr/ops/ocr-stream.d.ts +5 -7
- package/dist/server/bare/plugins/onnx-ocr/ops/ocr-stream.js +11 -3
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +2 -0
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +24 -19
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +7 -2
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +22 -97
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +98 -9
- package/dist/server/bare/plugins/onnx-tts/plugin.js +85 -46
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +30 -60
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +49 -37
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.d.ts +3 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +51 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +278 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +70 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +38 -2
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +43 -22
- package/dist/server/bare/rag-hyperdb/handlers/ingest.js +2 -1
- package/dist/server/bare/rag-hyperdb/handlers/search.js +2 -1
- package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +7 -0
- package/dist/server/bare/registry/model-config-utils.js +3 -0
- package/dist/server/bare/registry/model-registry.d.ts +2 -2
- package/dist/server/bare/registry/model-registry.js +1 -1
- package/dist/server/bare/registry/registry-client.js +21 -0
- package/dist/server/bare/runtime-lifecycle.d.ts +28 -0
- package/dist/server/bare/runtime-lifecycle.js +132 -0
- package/dist/server/bare/types/addon-responses.d.ts +62 -0
- package/dist/server/bare/types/addon-responses.js +1 -0
- package/dist/server/env.js +3 -1
- package/dist/server/rpc/delegate-transport.js +1 -1
- package/dist/server/rpc/handle-request.js +50 -4
- package/dist/server/rpc/handler-registry.js +20 -1
- package/dist/server/rpc/handler-utils.d.ts +5 -3
- package/dist/server/rpc/handler-utils.js +52 -50
- package/dist/server/rpc/handlers/delete-cache.js +3 -0
- package/dist/server/rpc/handlers/diffusion-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/diffusion-stream.js +4 -0
- package/dist/server/rpc/handlers/finetune.d.ts +3 -0
- package/dist/server/rpc/handlers/finetune.js +16 -0
- package/dist/server/rpc/handlers/index.d.ts +10 -0
- package/dist/server/rpc/handlers/index.js +10 -0
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +24 -9
- package/dist/server/rpc/handlers/load-model/registry.d.ts +11 -0
- package/dist/server/rpc/handlers/load-model/registry.js +31 -4
- package/dist/server/rpc/handlers/plugin-dispatch.d.ts +1 -13
- package/dist/server/rpc/handlers/plugin-dispatch.js +21 -21
- package/dist/server/rpc/handlers/resume.d.ts +3 -0
- package/dist/server/rpc/handlers/resume.js +11 -0
- package/dist/server/rpc/handlers/suspend.d.ts +3 -0
- package/dist/server/rpc/handlers/suspend.js +11 -0
- package/dist/server/rpc/handlers/transcribe-stream.d.ts +1 -1
- package/dist/server/rpc/handlers/transcribe-stream.js +2 -2
- package/dist/server/rpc/handlers/transcribe.d.ts +3 -0
- package/dist/server/rpc/handlers/transcribe.js +4 -0
- package/dist/server/rpc/profiling/operation-metrics.js +107 -16
- package/dist/server/rpc/profiling/operation-wrappers.d.ts +1 -1
- package/dist/server/rpc/profiling/operation-wrappers.js +51 -19
- package/dist/server/rpc/progress-throttle.d.ts +8 -0
- package/dist/server/rpc/progress-throttle.js +47 -0
- package/dist/server/rpc/rpc-utils.d.ts +5 -0
- package/dist/server/rpc/rpc-utils.js +11 -0
- package/dist/server/utils/path-security.js +1 -1
- package/dist/server/utils/tool-integration.js +10 -0
- package/dist/server/utils/tool-parser.js +9 -5
- package/dist/server/worker-core.d.ts +2 -0
- package/dist/server/worker-core.js +26 -23
- package/dist/server/worker.js +2 -1
- package/dist/utils/encoding.d.ts +9 -0
- package/dist/utils/encoding.js +14 -0
- package/dist/utils/errors-server.d.ts +6 -0
- package/dist/utils/errors-server.js +11 -0
- package/package.json +81 -25
- package/dist/server/rpc/delegate-utils.d.ts +0 -2
- package/dist/server/rpc/delegate-utils.js +0 -5
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script: pipes a WAV file through transcribeStream to verify
|
|
3
|
+
* the bidirectional streaming + addon processing works end-to-end.
|
|
4
|
+
*
|
|
5
|
+
* Usage: bun run examples/transcription/whispercpp-filesystem-streaming.ts
|
|
6
|
+
*
|
|
7
|
+
* Uses FFmpeg to convert the WAV to raw f32le and streams chunks
|
|
8
|
+
* through the duplex RPC session to the whisper addon.
|
|
9
|
+
*
|
|
10
|
+
* This example requires a test audio file (default: examples/audio/diarization-sample-16k.wav).
|
|
11
|
+
* Sample audio files are available in the QVAC source repository, but not included in the published npm package.
|
|
12
|
+
* Set SAMPLE_FILE to a custom WAV, or download the default audio into examples/audio/:
|
|
13
|
+
* https://github.com/tetherto/qvac/blob/main/packages/sdk/examples/audio/diarization-sample-16k.wav
|
|
14
|
+
*/
|
|
15
|
+
import { loadModel, unloadModel, transcribeStream, WHISPER_TINY, VAD_SILERO_5_1_2, } from "@qvac/sdk";
|
|
16
|
+
import { spawn } from "child_process";
|
|
17
|
+
import path from "path";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = path.dirname(__filename);
|
|
21
|
+
const SAMPLE_FILE = path.resolve(__dirname, "../audio/diarization-sample-16k.wav");
|
|
22
|
+
const SAMPLE_RATE = 16000;
|
|
23
|
+
const BYTES_PER_SAMPLE = 4; // f32le
|
|
24
|
+
const CHUNK_SIZE = Math.floor(0.1 * SAMPLE_RATE) * BYTES_PER_SAMPLE; // 100ms chunks
|
|
25
|
+
try {
|
|
26
|
+
console.log("=== transcribeStream file test ===");
|
|
27
|
+
console.log(`File: ${SAMPLE_FILE}`);
|
|
28
|
+
console.log(`Chunk size: ${CHUNK_SIZE} bytes (100ms)\n`);
|
|
29
|
+
console.log("Loading model...");
|
|
30
|
+
const modelId = await loadModel({
|
|
31
|
+
modelSrc: WHISPER_TINY,
|
|
32
|
+
modelType: "whisper",
|
|
33
|
+
modelConfig: {
|
|
34
|
+
vadModelSrc: VAD_SILERO_5_1_2,
|
|
35
|
+
audio_format: "f32le",
|
|
36
|
+
strategy: "greedy",
|
|
37
|
+
n_threads: 4,
|
|
38
|
+
language: "en",
|
|
39
|
+
no_timestamps: true,
|
|
40
|
+
suppress_blank: true,
|
|
41
|
+
suppress_nst: true,
|
|
42
|
+
temperature: 0.0,
|
|
43
|
+
vad_params: {
|
|
44
|
+
threshold: 0.6,
|
|
45
|
+
min_speech_duration_ms: 250,
|
|
46
|
+
min_silence_duration_ms: 500,
|
|
47
|
+
max_speech_duration_s: 15.0,
|
|
48
|
+
speech_pad_ms: 200,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
console.log(`Model loaded: ${modelId}\n`);
|
|
53
|
+
console.log("Opening live session...");
|
|
54
|
+
const session = await transcribeStream({ modelId });
|
|
55
|
+
console.log("Session open. Streaming audio...\n");
|
|
56
|
+
const ffmpeg = spawn("ffmpeg", [
|
|
57
|
+
"-i", SAMPLE_FILE,
|
|
58
|
+
"-ar", String(SAMPLE_RATE),
|
|
59
|
+
"-ac", "1",
|
|
60
|
+
"-sample_fmt", "flt",
|
|
61
|
+
"-f", "f32le",
|
|
62
|
+
"pipe:1",
|
|
63
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
64
|
+
let totalBytes = 0;
|
|
65
|
+
ffmpeg.stdout.on("data", (raw) => {
|
|
66
|
+
for (let offset = 0; offset < raw.length; offset += CHUNK_SIZE) {
|
|
67
|
+
const chunk = raw.subarray(offset, offset + CHUNK_SIZE);
|
|
68
|
+
session.write(chunk);
|
|
69
|
+
totalBytes += chunk.length;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
ffmpeg.on("close", () => {
|
|
73
|
+
const durationSec = totalBytes / (SAMPLE_RATE * BYTES_PER_SAMPLE);
|
|
74
|
+
console.log(`Audio streamed: ${totalBytes} bytes (~${durationSec.toFixed(1)}s)`);
|
|
75
|
+
console.log("Waiting for transcription...\n");
|
|
76
|
+
session.end();
|
|
77
|
+
});
|
|
78
|
+
const segments = [];
|
|
79
|
+
for await (const text of session) {
|
|
80
|
+
segments.push(text.trim());
|
|
81
|
+
console.log(` [${segments.length}] ${text.trim()}`);
|
|
82
|
+
}
|
|
83
|
+
console.log("\n=== Results ===");
|
|
84
|
+
console.log(`Segments: ${segments.length}`);
|
|
85
|
+
if (segments.length > 0) {
|
|
86
|
+
console.log(`Transcript: ${segments.join(" ")}`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log("WARNING: No transcription segments received!");
|
|
90
|
+
}
|
|
91
|
+
console.log("\nUnloading model...");
|
|
92
|
+
await unloadModel({ modelId });
|
|
93
|
+
console.log("Done.");
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error("Error:", error);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
@@ -1,310 +1,89 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Microphone → Whisper streaming transcription with native VAD.
|
|
3
|
+
*
|
|
4
|
+
* Usage: bun run examples/transcription/whispercpp-microphone-record.ts
|
|
5
|
+
*
|
|
6
|
+
* Speak into your mic; transcriptions appear automatically when you pause.
|
|
7
|
+
* Press Ctrl+C to quit.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: FFmpeg installed, microphone access.
|
|
10
|
+
*/
|
|
11
|
+
import { loadModel, unloadModel, transcribeStream, WHISPER_TINY, VAD_SILERO_5_1_2, } from "@qvac/sdk";
|
|
2
12
|
import { spawn, spawnSync } from "child_process";
|
|
3
|
-
import * as readline from "readline";
|
|
4
13
|
import { platform } from "os";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (result.error || result.status !== 0) {
|
|
9
|
-
throw new Error("FFmpeg not available");
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
throw new Error("FFmpeg is not installed or not available in PATH. Please install FFmpeg to use microphone recording.");
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function getAudioDevice(platformName) {
|
|
17
|
-
switch (platformName) {
|
|
14
|
+
const SAMPLE_RATE = 16000;
|
|
15
|
+
function getAudioInputArgs() {
|
|
16
|
+
switch (platform()) {
|
|
18
17
|
case "darwin":
|
|
19
|
-
return ":0";
|
|
18
|
+
return ["-f", "avfoundation", "-i", ":0"];
|
|
20
19
|
case "win32":
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
return [
|
|
21
|
+
"-f",
|
|
22
|
+
"dshow",
|
|
23
|
+
"-i",
|
|
24
|
+
"audio=@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\\wave_{58C07110-A4FD-4FF8-BA10-5A3C14389F71}",
|
|
25
|
+
];
|
|
23
26
|
case "linux":
|
|
24
|
-
return "default";
|
|
27
|
+
return ["-f", "pulse", "-i", "default"];
|
|
25
28
|
default:
|
|
26
|
-
throw new Error(`Unsupported platform
|
|
29
|
+
throw new Error(`Unsupported platform: ${platform()}`);
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
console.log("🎤 Microphone Transcription Demo");
|
|
35
|
-
console.log("");
|
|
36
|
-
console.log("Usage:");
|
|
37
|
-
console.log(" bun run examples/microphone-record-transcription.ts [options]");
|
|
38
|
-
console.log("");
|
|
39
|
-
console.log("Options:");
|
|
40
|
-
console.log(" --stream Enable real-time streaming transcription");
|
|
41
|
-
console.log(" --help, -h Show this help message");
|
|
42
|
-
console.log("");
|
|
43
|
-
console.log("Default behavior: Record audio, then transcribe when you stop recording");
|
|
44
|
-
console.log("With --stream: Transcribe audio in real-time as you speak");
|
|
45
|
-
process.exit(0);
|
|
46
|
-
}
|
|
47
|
-
// Clean readline-based transcription session
|
|
48
|
-
function startInteractiveSession(rl, modelId) {
|
|
49
|
-
let isRecording = false;
|
|
50
|
-
let ffmpeg = null;
|
|
51
|
-
let audioBuffer = Buffer.alloc(0);
|
|
52
|
-
let audioChunkBuffer = Buffer.alloc(0);
|
|
53
|
-
const chunkSizeBytes = 96000; // ~3 seconds of audio at 16kHz 16-bit mono
|
|
54
|
-
let lastProcessTime = 0;
|
|
55
|
-
const showInstructions = () => {
|
|
56
|
-
if (isStreamingMode) {
|
|
57
|
-
console.log("🎤 Real-Time Transcription Session");
|
|
58
|
-
console.log("📊 Format: 16kHz, 32-bit float, mono, f32le");
|
|
59
|
-
console.log(`🎙️ Using ${platform() === "darwin" ? "macOS" : platform() === "win32" ? "Windows" : "Linux"} microphone`);
|
|
60
|
-
console.log("⏯️ Press Enter to START/STOP real-time transcription");
|
|
61
|
-
console.log("🛑 Type 'q' and press Enter to quit");
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
console.log("🎤 Record-and-Transcribe Session");
|
|
65
|
-
console.log("📊 Format: 16kHz, 32-bit float, mono, f32le");
|
|
66
|
-
console.log(`🎙️ Using ${platform() === "darwin" ? "macOS" : platform() === "win32" ? "Windows" : "Linux"} microphone`);
|
|
67
|
-
console.log("⏯️ Press Enter to START/STOP recording");
|
|
68
|
-
console.log("🛑 Type 'q' and press Enter to quit");
|
|
69
|
-
}
|
|
70
|
-
console.log("");
|
|
71
|
-
};
|
|
72
|
-
const startRecording = () => {
|
|
73
|
-
if (isStreamingMode) {
|
|
74
|
-
console.log("🔴 Starting real-time transcription...");
|
|
75
|
-
audioChunkBuffer = Buffer.alloc(0);
|
|
76
|
-
console.log("\n" + "═".repeat(80));
|
|
77
|
-
console.log("🗣️ REAL-TIME TRANSCRIPTION");
|
|
78
|
-
console.log("═".repeat(80));
|
|
79
|
-
console.log("📝 Speak now, transcription will appear as you talk...");
|
|
80
|
-
console.log("");
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
console.log("🔴 Starting recording...");
|
|
84
|
-
audioBuffer = Buffer.alloc(0);
|
|
85
|
-
}
|
|
86
|
-
const currentPlatform = platform();
|
|
87
|
-
const audioInputArgs = (() => {
|
|
88
|
-
switch (currentPlatform) {
|
|
89
|
-
case "darwin":
|
|
90
|
-
return ["-f", "avfoundation", "-i", getAudioDevice(currentPlatform)];
|
|
91
|
-
case "win32":
|
|
92
|
-
return ["-f", "dshow", "-i", getAudioDevice(currentPlatform)];
|
|
93
|
-
case "linux":
|
|
94
|
-
return ["-f", "pulse", "-i", getAudioDevice(currentPlatform)];
|
|
95
|
-
default:
|
|
96
|
-
throw new Error(`Unsupported platform for audio recording: ${currentPlatform}`);
|
|
97
|
-
}
|
|
98
|
-
})();
|
|
99
|
-
ffmpeg = spawn("ffmpeg", [
|
|
100
|
-
...audioInputArgs,
|
|
101
|
-
"-ar",
|
|
102
|
-
"16000", // 16kHz
|
|
103
|
-
"-ac",
|
|
104
|
-
"1", // Mono
|
|
105
|
-
"-sample_fmt",
|
|
106
|
-
"flt", // 32-bit float
|
|
107
|
-
"-f",
|
|
108
|
-
"f32le", // f32le output format
|
|
109
|
-
"pipe:1", // Output to stdout
|
|
110
|
-
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
111
|
-
if (!ffmpeg.stdout) {
|
|
112
|
-
console.error("Failed to create microphone stream");
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (isStreamingMode) {
|
|
116
|
-
// Process audio chunks in real-time
|
|
117
|
-
ffmpeg.stdout.on("data", (chunk) => {
|
|
118
|
-
audioChunkBuffer = Buffer.concat([audioChunkBuffer, chunk]);
|
|
119
|
-
const now = Date.now();
|
|
120
|
-
if (audioChunkBuffer.length >= chunkSizeBytes &&
|
|
121
|
-
now - lastProcessTime > 1000) {
|
|
122
|
-
const chunkToProcess = audioChunkBuffer.slice(0, chunkSizeBytes);
|
|
123
|
-
audioChunkBuffer = audioChunkBuffer.slice(chunkSizeBytes);
|
|
124
|
-
lastProcessTime = now;
|
|
125
|
-
if (chunkToProcess.length < 32000)
|
|
126
|
-
return;
|
|
127
|
-
void (async () => {
|
|
128
|
-
try {
|
|
129
|
-
for await (const textChunk of transcribeStream({
|
|
130
|
-
modelId,
|
|
131
|
-
audioChunk: chunkToProcess,
|
|
132
|
-
})) {
|
|
133
|
-
if (textChunk.trim() && !textChunk.includes("[BLANK_AUDIO]")) {
|
|
134
|
-
process.stdout.write(textChunk);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
console.error("\n⚠️ Transcription error:", error instanceof Error ? error.message : String(error));
|
|
140
|
-
}
|
|
141
|
-
})();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
// Buffer all audio data for later transcription
|
|
147
|
-
ffmpeg.stdout.on("data", (chunk) => {
|
|
148
|
-
audioBuffer = Buffer.concat([audioBuffer, chunk]);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
isRecording = true;
|
|
152
|
-
if (isStreamingMode) {
|
|
153
|
-
console.log("✅ Real-time transcription active!");
|
|
154
|
-
console.log("⏹️ Press Enter to STOP");
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
console.log("✅ Recording... speak now!");
|
|
158
|
-
console.log("⏹️ Press Enter to STOP and transcribe");
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
const stopRecording = async () => {
|
|
162
|
-
if (!isRecording)
|
|
163
|
-
return;
|
|
164
|
-
if (ffmpeg) {
|
|
165
|
-
ffmpeg.kill();
|
|
166
|
-
}
|
|
167
|
-
isRecording = false;
|
|
168
|
-
if (isStreamingMode) {
|
|
169
|
-
console.log("\n🛑 Stopping real-time transcription...");
|
|
170
|
-
if (audioChunkBuffer.length > 0) {
|
|
171
|
-
try {
|
|
172
|
-
for await (const textChunk of transcribeStream({
|
|
173
|
-
modelId,
|
|
174
|
-
audioChunk: audioChunkBuffer,
|
|
175
|
-
})) {
|
|
176
|
-
if (textChunk.trim() && !textChunk.includes("[BLANK_AUDIO]")) {
|
|
177
|
-
process.stdout.write(textChunk);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
console.error("\n❌ Final transcription failed:", error instanceof Error ? error.message : String(error));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
console.log("\n═".repeat(80));
|
|
186
|
-
console.log("✅ Real-time transcription stopped");
|
|
187
|
-
console.log("⏯️ Press Enter to start again...");
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
console.log("🛑 Stopping recording...");
|
|
191
|
-
console.log(`📦 Recorded ${audioBuffer.length} bytes of audio`);
|
|
192
|
-
console.log("🔄 Transcribing...");
|
|
193
|
-
const startTime = Date.now();
|
|
194
|
-
console.log("\n" + "═".repeat(80));
|
|
195
|
-
console.log("🗣️ TRANSCRIPTION RESULT");
|
|
196
|
-
console.log("═".repeat(80));
|
|
197
|
-
try {
|
|
198
|
-
const text = await transcribe({ modelId, audioChunk: audioBuffer });
|
|
199
|
-
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
200
|
-
console.log(`📝 "${text}"`);
|
|
201
|
-
console.log("═".repeat(80));
|
|
202
|
-
console.log(`✅ Transcription completed in ${elapsed}s`);
|
|
203
|
-
console.log("\n⏯️ Press Enter to record again...");
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
console.error("\n❌ Transcription failed:", error instanceof Error ? error.message : String(error));
|
|
207
|
-
console.log("\n⏯️ Press Enter to record again...");
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
showInstructions();
|
|
212
|
-
const handleInput = (input) => {
|
|
213
|
-
const command = input.trim().toLowerCase();
|
|
214
|
-
if (command === "") {
|
|
215
|
-
// Just pressed Enter - toggle recording
|
|
216
|
-
if (isRecording) {
|
|
217
|
-
void stopRecording();
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
startRecording();
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
else if (command === "q") {
|
|
224
|
-
console.log("\n🛑 Exiting...");
|
|
225
|
-
if (ffmpeg) {
|
|
226
|
-
ffmpeg.kill();
|
|
227
|
-
}
|
|
228
|
-
rl.close();
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
console.log(`❓ Unknown command: ${command}`);
|
|
233
|
-
console.log("💡 Press Enter to start/stop, 'q' to quit");
|
|
234
|
-
}
|
|
235
|
-
rl.prompt();
|
|
236
|
-
};
|
|
237
|
-
rl.on("line", handleInput);
|
|
238
|
-
rl.on("close", () => {
|
|
239
|
-
if (ffmpeg) {
|
|
240
|
-
ffmpeg.kill();
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
rl.prompt();
|
|
32
|
+
// ── Main ──
|
|
33
|
+
try {
|
|
34
|
+
const r = spawnSync("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
35
|
+
if (r.error || r.status !== 0)
|
|
36
|
+
throw new Error("FFmpeg not found");
|
|
244
37
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
// Set up readline interface FIRST to keep event loop alive during model loading
|
|
249
|
-
rl = readline.createInterface({
|
|
250
|
-
input: process.stdin,
|
|
251
|
-
output: process.stdout,
|
|
252
|
-
});
|
|
253
|
-
try {
|
|
254
|
-
if (isStreamingMode) {
|
|
255
|
-
console.log("🎤 Streaming Transcription Microphone Demo");
|
|
256
|
-
console.log("✨ Mode: Real-time streaming transcription");
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
console.log("🎤 Record-and-Transcribe Microphone Demo");
|
|
260
|
-
console.log("✨ Mode: Record first, then transcribe");
|
|
261
|
-
console.log("💡 Tip: Use --stream flag for real-time transcription");
|
|
262
|
-
}
|
|
263
|
-
console.log("⚠️ Requirements:");
|
|
264
|
-
console.log(" - Microphone connected and accessible");
|
|
265
|
-
console.log(" - FFmpeg installed");
|
|
266
|
-
// Check FFmpeg availability
|
|
267
|
-
checkFFmpegAvailable();
|
|
268
|
-
// Load the Whisper model with VAD
|
|
269
|
-
console.log("\n📥 Loading Whisper model with VAD...");
|
|
270
|
-
modelId = await loadModel({
|
|
271
|
-
modelSrc: WHISPER_TINY,
|
|
272
|
-
modelType: "whisper",
|
|
273
|
-
modelConfig: {
|
|
274
|
-
audio_format: "f32le",
|
|
275
|
-
vad_params: {
|
|
276
|
-
threshold: 0.6,
|
|
277
|
-
min_speech_duration_ms: 250,
|
|
278
|
-
min_silence_duration_ms: 2000,
|
|
279
|
-
max_speech_duration_s: 30.0,
|
|
280
|
-
},
|
|
281
|
-
},
|
|
282
|
-
onProgress: (progress) => {
|
|
283
|
-
console.log(progress);
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
console.log(`✅ Whisper model loaded with ID: ${modelId}`);
|
|
287
|
-
// Start interactive session using the existing readline interface
|
|
288
|
-
console.log("\n🎧 Starting interactive session...");
|
|
289
|
-
startInteractiveSession(rl, modelId);
|
|
290
|
-
}
|
|
291
|
-
catch (error) {
|
|
292
|
-
console.error("❌ Error during transcription setup:", error instanceof Error ? error.message : String(error));
|
|
293
|
-
// Clean up on error
|
|
294
|
-
if (rl) {
|
|
295
|
-
rl.close();
|
|
296
|
-
}
|
|
297
|
-
if (modelId) {
|
|
298
|
-
console.log("\n🧹 Unloading Whisper model...");
|
|
299
|
-
await unloadModel({ modelId });
|
|
300
|
-
console.log("✅ Whisper model unloaded successfully");
|
|
301
|
-
}
|
|
302
|
-
process.exit(1);
|
|
303
|
-
}
|
|
38
|
+
catch {
|
|
39
|
+
console.error("FFmpeg is required. Install it and try again.");
|
|
40
|
+
process.exit(1);
|
|
304
41
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
42
|
+
console.log("Loading model (whisper-tiny + Silero VAD)...");
|
|
43
|
+
const modelId = await loadModel({
|
|
44
|
+
modelSrc: WHISPER_TINY,
|
|
45
|
+
modelType: "whisper",
|
|
46
|
+
modelConfig: {
|
|
47
|
+
vadModelSrc: VAD_SILERO_5_1_2,
|
|
48
|
+
audio_format: "f32le",
|
|
49
|
+
strategy: "greedy",
|
|
50
|
+
n_threads: 4,
|
|
51
|
+
language: "en",
|
|
52
|
+
no_timestamps: true,
|
|
53
|
+
suppress_blank: true,
|
|
54
|
+
suppress_nst: true,
|
|
55
|
+
temperature: 0.0,
|
|
56
|
+
vad_params: {
|
|
57
|
+
threshold: 0.6,
|
|
58
|
+
min_speech_duration_ms: 250,
|
|
59
|
+
min_silence_duration_ms: 300,
|
|
60
|
+
max_speech_duration_s: 15.0,
|
|
61
|
+
speech_pad_ms: 100,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
308
64
|
});
|
|
309
|
-
|
|
310
|
-
|
|
65
|
+
console.log("Model loaded.\n");
|
|
66
|
+
const ffmpeg = spawn("ffmpeg", [
|
|
67
|
+
...getAudioInputArgs(),
|
|
68
|
+
"-ar", String(SAMPLE_RATE),
|
|
69
|
+
"-ac", "1",
|
|
70
|
+
"-sample_fmt", "flt",
|
|
71
|
+
"-f", "f32le",
|
|
72
|
+
"pipe:1",
|
|
73
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
74
|
+
if (!ffmpeg.stdout)
|
|
75
|
+
throw new Error("Failed to open microphone");
|
|
76
|
+
const session = await transcribeStream({ modelId });
|
|
77
|
+
ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
|
|
78
|
+
console.log("Listening... speak and pause to see transcriptions.\n");
|
|
79
|
+
for await (const text of session) {
|
|
80
|
+
console.log(`> ${text.trim()}`);
|
|
81
|
+
}
|
|
82
|
+
async function cleanup() {
|
|
83
|
+
console.log("\n\nStopping...");
|
|
84
|
+
ffmpeg.kill();
|
|
85
|
+
await unloadModel({ modelId });
|
|
86
|
+
console.log("Done.");
|
|
87
|
+
}
|
|
88
|
+
process.on("SIGINT", () => void cleanup());
|
|
89
|
+
process.on("SIGTERM", () => void cleanup());
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whisper transcription with prompt example.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* bun examples/transcription/whispercpp-prompt.ts
|
|
6
|
+
*
|
|
7
|
+
* This example requires a test audio file (default: examples/audio/sample-16khz.wav).
|
|
8
|
+
* Sample audio files are available in the QVAC source repository, but not included in the published npm package.
|
|
9
|
+
* Set audioChunk to a custom WAV, or download the default audio into examples/audio/:
|
|
10
|
+
* https://github.com/tetherto/qvac/blob/main/packages/sdk/examples/audio/sample-16khz.wav
|
|
11
|
+
*/
|
|
1
12
|
import { loadModel, unloadModel, transcribe, WHISPER_TINY } from "@qvac/sdk";
|
|
2
13
|
try {
|
|
3
14
|
console.log("🎤 Starting Whisper transcription with prompt example...");
|
|
@@ -17,7 +17,8 @@ try {
|
|
|
17
17
|
modelType: "llm",
|
|
18
18
|
stream: false,
|
|
19
19
|
});
|
|
20
|
-
|
|
20
|
+
const translatedTextExplicit = await resultExplicit.text;
|
|
21
|
+
// With autodetection (must await previous translate — LLM addon runs one job at a time)
|
|
21
22
|
const espText = "Hola, como estas?";
|
|
22
23
|
const resultAutodetect = translate({
|
|
23
24
|
modelId,
|
|
@@ -26,7 +27,6 @@ try {
|
|
|
26
27
|
modelType: "llm",
|
|
27
28
|
stream: false,
|
|
28
29
|
});
|
|
29
|
-
const translatedTextExplicit = await resultExplicit.text;
|
|
30
30
|
const translatedTextAutodetect = await resultAutodetect.text;
|
|
31
31
|
console.log(`Explicit source: ${engText} -> "${translatedTextExplicit}"`);
|
|
32
32
|
console.log(`Autodetected source: ${espText} -> "${translatedTextAutodetect}"`);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE, TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE, TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32, } from "@qvac/sdk";
|
|
2
|
+
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
+
// Supertonic TTS: general-purpose, no voice cloning.
|
|
4
|
+
// Uses registry model constants - downloads automatically from QVAC Registry.
|
|
5
|
+
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
6
|
+
try {
|
|
7
|
+
const modelId = await loadModel({
|
|
8
|
+
modelSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
9
|
+
modelType: "tts",
|
|
10
|
+
modelConfig: {
|
|
11
|
+
ttsEngine: "supertonic",
|
|
12
|
+
language: "es",
|
|
13
|
+
speed: 1.05,
|
|
14
|
+
numInferenceSteps: 5,
|
|
15
|
+
supertonicMultilingual: 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
|
+
},
|
|
24
|
+
onProgress: (progress) => {
|
|
25
|
+
console.log(progress);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
console.log(`Model loaded: ${modelId}`);
|
|
29
|
+
console.log("🎵 Testing Text-to-Speech...");
|
|
30
|
+
const result = textToSpeech({
|
|
31
|
+
modelId,
|
|
32
|
+
text: `Hola mundo. Esta es una demostración de síntesis de voz con Supertonic en español.`,
|
|
33
|
+
inputType: "text",
|
|
34
|
+
stream: false,
|
|
35
|
+
});
|
|
36
|
+
const audioBuffer = await result.buffer;
|
|
37
|
+
console.log(`TTS complete. Total samples: ${audioBuffer.length}`);
|
|
38
|
+
console.log("💾 Saving audio to file...");
|
|
39
|
+
createWav(audioBuffer, SUPERTONIC_SAMPLE_RATE, "supertonic-multilingual-output.wav");
|
|
40
|
+
console.log("✅ Audio saved to supertonic-multilingual-output.wav");
|
|
41
|
+
console.log("🔊 Playing audio...");
|
|
42
|
+
const audioData = int16ArrayToBuffer(audioBuffer);
|
|
43
|
+
const wavBuffer = Buffer.concat([
|
|
44
|
+
createWavHeader(audioData.length, SUPERTONIC_SAMPLE_RATE),
|
|
45
|
+
audioData,
|
|
46
|
+
]);
|
|
47
|
+
playAudio(wavBuffer);
|
|
48
|
+
console.log("✅ Audio playback complete");
|
|
49
|
+
await unloadModel({ modelId });
|
|
50
|
+
console.log("Model unloaded");
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error("❌ Error:", error);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32, TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE, TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
3
|
// Supertonic TTS: general-purpose, no voice cloning.
|
|
4
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_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
9
9
|
modelType: "tts",
|
|
10
10
|
modelConfig: {
|
|
11
11
|
ttsEngine: "supertonic",
|
|
12
12
|
language: "en",
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
speed: 1.05,
|
|
14
|
+
numInferenceSteps: 5,
|
|
15
|
+
supertonicMultilingual: 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,
|
|
18
23
|
},
|
|
19
24
|
onProgress: (progress) => {
|
|
20
25
|
console.log(progress);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import "#polyfill-bare-globals";
|
|
2
|
+
export { completion, deleteCache, loadModel, downloadAsset, heartbeat, startQVACProvider, stopQVACProvider, unloadModel, transcribe, transcribeStream, embed, finetune, translate, cancel, ragChunk, ragIngest, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, ragReindex, ragListWorkspaces, ragCloseWorkspace, ragDeleteWorkspace, textToSpeech, getModelInfo, loggingStream, ocr, invokePlugin, invokePluginStream, diffusion, type DiffusionProgressTick, modelRegistryList, modelRegistrySearch, modelRegistryGetModel, type ModelRegistrySearchParams, suspend, resume, type FinetuneHandle, } from "./client/api/index";
|
|
2
3
|
export { close } from "./client/index";
|
|
3
|
-
export { type ModelProgressUpdate, type LoadModelOptions, type DownloadAssetOptions, type Tool, type ToolCall, type ToolCallWithCall, type ToolCallError, type ToolCallEvent, type CompletionStats, VERBOSITY, type Attachment, type CompletionParams, type RagSearchResult, type RagSaveEmbeddingsResult, type RagReindexResult, type RagEmbeddedDoc, type RagDoc, type RagWorkspaceInfo, type RagCloseWorkspaceParams, type RagDeleteWorkspaceParams, type RagIngestStage, type RagReindexStage, type RagSaveStage, SDK_CLIENT_ERROR_CODES, SDK_SERVER_ERROR_CODES, type QvacConfig, type ModelInfo, type GetModelInfoParams, type LoadedInstance, type CacheFileInfo, toolSchema, type McpClient, type McpClientInput, type OCRClientParams, type OCRTextBlock, type OCROptions, definePlugin, defineHandler, type QvacPlugin, type CreateModelParams, type PluginModelResult, type ModelRegistryEntry, type ModelRegistryEntryAddon, PLUGIN_LLM, PLUGIN_EMBEDDING, PLUGIN_WHISPER, PLUGIN_NMT, PLUGIN_TTS, PLUGIN_OCR, SDK_DEFAULT_PLUGINS, type BuiltinPlugin, type ProfilerMode, } from "./schemas/index";
|
|
4
|
+
export { type ModelProgressUpdate, type LoadModelOptions, type DownloadAssetOptions, type Tool, type ToolCall, type ToolCallWithCall, type ToolCallError, type ToolCallEvent, type CompletionStats, type EmbedStats, VERBOSITY, type Attachment, type TranscribeStreamSession, type CompletionParams, type RagSearchResult, type RagSaveEmbeddingsResult, type RagReindexResult, type RagEmbeddedDoc, type RagDoc, type RagWorkspaceInfo, type RagCloseWorkspaceParams, type RagDeleteWorkspaceParams, type RagIngestStage, type RagReindexStage, type RagSaveStage, SDK_CLIENT_ERROR_CODES, SDK_SERVER_ERROR_CODES, type QvacConfig, type ModelInfo, type GetModelInfoParams, type LoadedInstance, type CacheFileInfo, toolSchema, type McpClient, type McpClientInput, type OCRClientParams, type OCRTextBlock, type OCROptions, type DiffusionClientParams, type DiffusionStreamResponse, type DiffusionStats, definePlugin, defineHandler, defineDuplexHandler, type QvacPlugin, type CreateModelParams, type PluginModelResult, type ModelRegistryEntry, type ModelRegistryEntryAddon, PLUGIN_LLM, PLUGIN_EMBEDDING, PLUGIN_WHISPER, PLUGIN_NMT, PLUGIN_TTS, PLUGIN_OCR, PLUGIN_DIFFUSION, SDK_DEFAULT_PLUGINS, type BuiltinPlugin, type ProfilerMode, type FinetuneValidation, type FinetuneRunParams, type FinetuneGetStateParams, type FinetuneStopParams, type FinetuneParams, type FinetuneStatus, type FinetuneProgress, type FinetuneStats, type FinetuneResult, } from "./schemas/index";
|
|
4
5
|
export { type ToolInput, type ToolHandler } from "./utils/tool-helpers";
|
|
5
6
|
export { MODEL_TYPES, ModelType } from "./schemas/index";
|
|
6
7
|
export * from "./models/registry/index";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import "#polyfill-bare-globals";
|
|
1
2
|
// Public API exports only
|
|
2
|
-
export { completion, deleteCache, loadModel, downloadAsset, heartbeat, startQVACProvider, stopQVACProvider, unloadModel, transcribe, transcribeStream, embed, translate, cancel, ragChunk, ragIngest, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, ragReindex, ragListWorkspaces, ragCloseWorkspace, ragDeleteWorkspace, textToSpeech, getModelInfo, loggingStream, ocr, invokePlugin, invokePluginStream, modelRegistryList, modelRegistrySearch, modelRegistryGetModel, } from "./client/api/index.js";
|
|
3
|
+
export { completion, deleteCache, loadModel, downloadAsset, heartbeat, startQVACProvider, stopQVACProvider, unloadModel, transcribe, transcribeStream, embed, finetune, translate, cancel, ragChunk, ragIngest, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, ragReindex, ragListWorkspaces, ragCloseWorkspace, ragDeleteWorkspace, textToSpeech, getModelInfo, loggingStream, ocr, invokePlugin, invokePluginStream, diffusion, modelRegistryList, modelRegistrySearch, modelRegistryGetModel, suspend, resume, } from "./client/api/index.js";
|
|
3
4
|
export { close } from "./client/index.js";
|
|
4
|
-
export { VERBOSITY, SDK_CLIENT_ERROR_CODES, SDK_SERVER_ERROR_CODES, toolSchema, definePlugin, defineHandler, PLUGIN_LLM, PLUGIN_EMBEDDING, PLUGIN_WHISPER, PLUGIN_NMT, PLUGIN_TTS, PLUGIN_OCR, SDK_DEFAULT_PLUGINS, } from "./schemas/index.js";
|
|
5
|
+
export { VERBOSITY, SDK_CLIENT_ERROR_CODES, SDK_SERVER_ERROR_CODES, toolSchema, definePlugin, defineHandler, defineDuplexHandler, PLUGIN_LLM, PLUGIN_EMBEDDING, PLUGIN_WHISPER, PLUGIN_NMT, PLUGIN_TTS, PLUGIN_OCR, PLUGIN_DIFFUSION, SDK_DEFAULT_PLUGINS, } from "./schemas/index.js";
|
|
5
6
|
export {} from "./utils/tool-helpers.js";
|
|
6
7
|
// Model types - canonical naming with backward-compatible aliases
|
|
7
8
|
export { MODEL_TYPES, ModelType } from "./schemas/index.js";
|
package/dist/logging/utils.js
CHANGED
|
@@ -50,7 +50,7 @@ export function summarizeRequest(request) {
|
|
|
50
50
|
if ("modelId" in request)
|
|
51
51
|
summary["modelId"] = request["modelId"];
|
|
52
52
|
// Only summarize requests with large payloads
|
|
53
|
-
if (request.type === "
|
|
53
|
+
if (request.type === "transcribe") {
|
|
54
54
|
const chunk = request["audioChunk"];
|
|
55
55
|
summary["audioChunk"] = `[${chunk.type}: ${chunk.value.length} bytes]`;
|
|
56
56
|
return summary;
|