Fix dev runner entry and sherpa TTS initialization
This commit is contained in:
@@ -687,7 +687,7 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
marginBottom: theme.spacing[1],
|
marginBottom: theme.spacing[1],
|
||||||
},
|
},
|
||||||
agentItemUnselected: {
|
agentItemUnselected: {
|
||||||
opacity: 0.75,
|
opacity: 1,
|
||||||
},
|
},
|
||||||
agentItemSelected: {
|
agentItemSelected: {
|
||||||
backgroundColor: theme.colors.surface2,
|
backgroundColor: theme.colors.surface2,
|
||||||
|
|||||||
@@ -2,35 +2,19 @@ import { fileURLToPath } from "url";
|
|||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import { runSupervisor } from "./supervisor.js";
|
import { runSupervisor } from "./supervisor.js";
|
||||||
|
|
||||||
function resolveWorkerEntry(): string {
|
const WORKER_ENTRY = fileURLToPath(new URL("../src/server/index.ts", import.meta.url));
|
||||||
const candidates = [
|
if (!existsSync(WORKER_ENTRY)) {
|
||||||
fileURLToPath(new URL("../server/server/index.js", import.meta.url)),
|
throw new Error(`Dev worker entry not found: ${WORKER_ENTRY}`);
|
||||||
fileURLToPath(new URL("../dist/server/server/index.js", import.meta.url)),
|
|
||||||
fileURLToPath(new URL("../src/server/index.ts", import.meta.url)),
|
|
||||||
fileURLToPath(new URL("../../src/server/index.ts", import.meta.url)),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const candidate of candidates) {
|
|
||||||
if (existsSync(candidate)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidates[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveWorkerExecArgv(): string[] {
|
|
||||||
const workerEntry = resolveWorkerEntry();
|
|
||||||
return workerEntry.endsWith(".ts") ? ["--import", "tsx"] : [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runSupervisor({
|
runSupervisor({
|
||||||
name: "DevRunner",
|
name: "DevRunner",
|
||||||
startupMessage: "Starting server worker (crash restarts enabled)",
|
startupMessage: "Starting server worker (crash restarts enabled)",
|
||||||
resolveWorkerEntry,
|
resolveWorkerEntry: () => WORKER_ENTRY,
|
||||||
workerArgs: process.argv.slice(2),
|
workerArgs: process.argv.slice(2),
|
||||||
workerEnv: process.env,
|
workerEnv: process.env,
|
||||||
workerExecArgv: resolveWorkerExecArgv(),
|
// Always run worker with tsx so dev server uses TypeScript sources directly.
|
||||||
|
workerExecArgv: ["--import", "tsx"],
|
||||||
restartOnCrash: true,
|
restartOnCrash: true,
|
||||||
shutdownReasons: ["cli_shutdown"],
|
shutdownReasons: ["cli_shutdown"],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { existsSync } from "node:fs";
|
|||||||
|
|
||||||
import type { SpeechStreamResult, TextToSpeechProvider } from "../../../speech-provider.js";
|
import type { SpeechStreamResult, TextToSpeechProvider } from "../../../speech-provider.js";
|
||||||
import { chunkBuffer, float32ToPcm16le } from "../../../audio.js";
|
import { chunkBuffer, float32ToPcm16le } from "../../../audio.js";
|
||||||
import { loadSherpaOnnx } from "./sherpa-onnx-loader.js";
|
import { loadSherpaOnnxNode } from "./sherpa-onnx-node-loader.js";
|
||||||
|
|
||||||
export type SherpaTtsPreset = "kokoro-en-v0_19" | "kitten-nano-en-v0_1-fp16";
|
export type SherpaTtsPreset = "kokoro-en-v0_19" | "kitten-nano-en-v0_1-fp16";
|
||||||
|
|
||||||
@@ -37,7 +37,10 @@ export class SherpaOnnxTTS implements TextToSpeechProvider {
|
|||||||
this.speakerId = config.speakerId ?? 0;
|
this.speakerId = config.speakerId ?? 0;
|
||||||
this.speed = config.speed ?? 1.0;
|
this.speed = config.speed ?? 1.0;
|
||||||
|
|
||||||
const sherpa = loadSherpaOnnx();
|
const sherpa = loadSherpaOnnxNode();
|
||||||
|
if (typeof sherpa.OfflineTts !== "function") {
|
||||||
|
throw new Error("sherpa-onnx-node OfflineTts is unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
const modelFile = config.preset === "kokoro-en-v0_19" ? "model.onnx" : "model.fp16.onnx";
|
const modelFile = config.preset === "kokoro-en-v0_19" ? "model.onnx" : "model.fp16.onnx";
|
||||||
const modelPath = `${config.modelDir}/${modelFile}`;
|
const modelPath = `${config.modelDir}/${modelFile}`;
|
||||||
@@ -50,30 +53,35 @@ export class SherpaOnnxTTS implements TextToSpeechProvider {
|
|||||||
assertFileExists(tokensPath, "TTS tokens");
|
assertFileExists(tokensPath, "TTS tokens");
|
||||||
assertFileExists(dataDir, "TTS espeak-ng dataDir");
|
assertFileExists(dataDir, "TTS espeak-ng dataDir");
|
||||||
|
|
||||||
const modelConfigKey =
|
const modelConfig =
|
||||||
config.preset === "kokoro-en-v0_19"
|
config.preset === "kokoro-en-v0_19"
|
||||||
? "offlineTtsKokoroModelConfig"
|
? {
|
||||||
: "offlineTtsKittenModelConfig";
|
kokoro: {
|
||||||
|
model: modelPath,
|
||||||
const modelConfig = {
|
voices: voicesPath,
|
||||||
[modelConfigKey]: {
|
tokens: tokensPath,
|
||||||
model: modelPath,
|
dataDir,
|
||||||
voices: voicesPath,
|
lengthScale: config.lengthScale ?? 1.0,
|
||||||
tokens: tokensPath,
|
},
|
||||||
dataDir,
|
}
|
||||||
lengthScale: config.lengthScale ?? 1.0,
|
: {
|
||||||
},
|
kitten: {
|
||||||
numThreads: config.numThreads ?? 2,
|
model: modelPath,
|
||||||
debug: 0,
|
voices: voicesPath,
|
||||||
provider: "cpu",
|
tokens: tokensPath,
|
||||||
};
|
dataDir,
|
||||||
|
lengthScale: config.lengthScale ?? 1.0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const offlineTtsConfig = {
|
const offlineTtsConfig = {
|
||||||
offlineTtsModelConfig: modelConfig,
|
model: modelConfig,
|
||||||
|
numThreads: config.numThreads ?? 2,
|
||||||
|
provider: "cpu",
|
||||||
maxNumSentences: 1,
|
maxNumSentences: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.tts = sherpa.createOfflineTts(offlineTtsConfig);
|
this.tts = new sherpa.OfflineTts(offlineTtsConfig);
|
||||||
this.logger.info({ preset: config.preset, modelDir: config.modelDir }, "Sherpa offline TTS initialized");
|
this.logger.info({ preset: config.preset, modelDir: config.modelDir }, "Sherpa offline TTS initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user