fix(speech): generate TXT/JSON/MD locally from transcription result
Download buttons now use the already-completed transcription result instead of re-sending the audio to the server for re-transcription. This eliminates redundant server work and prevents download failures when the second transcription attempt errors out. Also wires up suppressNonSpeech and noSpeechThreshold options through the API and server pipeline.
This commit is contained in:
1 parent
a0bbd9a035
commit
b15bd7794e
3 files changed
+125
-42
No files matched your search
@@ -2560,6 +2560,15 @@ function transcribeWavBuffer(buffer, options = {}) {
|
||||
if (options.translate) {
|
||||
args.push("-tr");
|
||||
}
|
||||
// Suppress non-speech tokens (e.g. [Musica], [Applauso]) that appear
|
||||
// when the model misidentifies compressed/noisy audio as non-speech
|
||||
if (options.suppressNonSpeech !== false) {
|
||||
args.push("-sns");
|
||||
}
|
||||
// Lower no-speech threshold (default 0.60) so the model is less likely
|
||||
// to label quiet or compressed speech as non-speech
|
||||
const noSpeechThreshold = options.noSpeechThreshold || "0.30";
|
||||
args.push("-nth", String(noSpeechThreshold));
|
||||
|
||||
const startedAt = Date.now();
|
||||
console.log(" [speech] Starting:", backend.cli, args.join(" "));
|
||||
@@ -6030,14 +6039,19 @@ const server = http.createServer(async (req, res) => {
|
||||
const parsed = new URL(req.url, `http://${req.headers.host || "localhost"}`);
|
||||
try {
|
||||
const audio = await readBinaryBody(req);
|
||||
const result = await runExclusiveSpeechOperation(() => transcribeAudioBuffer(audio, {
|
||||
const suppressNonSpeech = parsed.searchParams.get("suppressNonSpeech");
|
||||
const noSpeechThreshold = parsed.searchParams.get("noSpeechThreshold");
|
||||
const transcribeOptions = {
|
||||
model: parsed.searchParams.get("model") || speechSettings.model,
|
||||
language: parsed.searchParams.get("language") || "auto",
|
||||
filename: parsed.searchParams.get("filename") || req.headers["x-filename"] || "recording",
|
||||
threads: parsed.searchParams.get("threads") || speechSettings.threads,
|
||||
backendPreference: parsed.searchParams.get("backendPreference") || speechSettings.backendPreference,
|
||||
translate: parsed.searchParams.get("translate") === "true",
|
||||
}));
|
||||
};
|
||||
if (suppressNonSpeech !== null) transcribeOptions.suppressNonSpeech = suppressNonSpeech !== "false";
|
||||
if (noSpeechThreshold !== null) transcribeOptions.noSpeechThreshold = noSpeechThreshold;
|
||||
const result = await runExclusiveSpeechOperation(() => transcribeAudioBuffer(audio, transcribeOptions));
|
||||
return json(res, 200, { ok: true, transcription: result });
|
||||
} catch (err) {
|
||||
speechError = err.message || String(err);
|
||||
@@ -6052,14 +6066,19 @@ const server = http.createServer(async (req, res) => {
|
||||
try {
|
||||
const audio = await readBinaryBody(req);
|
||||
const outputFormat = parsed.searchParams.get("format") || "txt";
|
||||
const result = await runExclusiveSpeechOperation(() => transcribeAudioBuffer(audio, {
|
||||
const suppressNonSpeech = parsed.searchParams.get("suppressNonSpeech");
|
||||
const noSpeechThreshold = parsed.searchParams.get("noSpeechThreshold");
|
||||
const transcribeOptions = {
|
||||
model: parsed.searchParams.get("model") || speechSettings.model,
|
||||
language: parsed.searchParams.get("language") || "auto",
|
||||
filename: parsed.searchParams.get("filename") || req.headers["x-filename"] || "recording",
|
||||
threads: parsed.searchParams.get("threads") || speechSettings.threads,
|
||||
backendPreference: parsed.searchParams.get("backendPreference") || speechSettings.backendPreference,
|
||||
translate: parsed.searchParams.get("translate") === "true",
|
||||
}));
|
||||
};
|
||||
if (suppressNonSpeech !== null) transcribeOptions.suppressNonSpeech = suppressNonSpeech !== "false";
|
||||
if (noSpeechThreshold !== null) transcribeOptions.noSpeechThreshold = noSpeechThreshold;
|
||||
const result = await runExclusiveSpeechOperation(() => transcribeAudioBuffer(audio, transcribeOptions));
|
||||
|
||||
const filename = parsed.searchParams.get("output_filename") || `transcription-${Date.now()}`;
|
||||
let fileContent = "";
|
||||
|
||||
Reference in new issue
Block a user