feat(speech): accept response_format=ogg as an opus alias (#10822)

Merged — validated together with a batch of related RaviTharuma PRs in one combined worktree (typecheck:core clean, complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
This commit is contained in:
Ravi Tharuma
2026-08-20 16:47:53 +02:00
committed by GitHub
parent 8b52596d7c
commit 6f08a089e7
3 changed files with 54 additions and 1 deletions

View File

@@ -0,0 +1 @@
- **feat(providers):** accept `response_format=ogg` on `/v1/audio/speech` as an alias for the existing Opus/Ogg encoder ([#10587](https://github.com/diegosouzapw/OmniRoute/issues/10587))

View File

@@ -229,6 +229,16 @@ async function handleDeepgramSpeech(providerConfig, body, modelId, token) {
return audioStreamResponse(res);
}
/**
* Voice-note clients send response_format=ogg. OpenAI TTS documents opus, not ogg.
* OmniRoute already returns Ogg/Opus bytes for opus — alias ogg → opus (#10587).
*/
export function normalizeSpeechResponseFormat(fmt) {
if (typeof fmt !== "string" || !fmt) return "mp3";
const lower = fmt.toLowerCase();
return lower === "ogg" ? "opus" : lower;
}
/**
* Handle Soniox TTS (OpenAI speech shape → Soniox /tts, returns raw audio bytes)
*/
@@ -963,7 +973,7 @@ export async function handleAudioSpeech({
model: modelId,
input: body.input,
voice: body.voice || "alloy",
response_format: body.response_format || "mp3",
response_format: normalizeSpeechResponseFormat(body.response_format),
speed: body.speed || 1.0,
}),
});

View File

@@ -0,0 +1,42 @@
import test from "node:test";
import assert from "node:assert/strict";
const { normalizeSpeechResponseFormat, handleAudioSpeech } = await import(
"../../open-sse/handlers/audioSpeech.ts"
);
test("normalizeSpeechResponseFormat aliases ogg to opus (#10587)", () => {
assert.equal(normalizeSpeechResponseFormat("ogg"), "opus");
assert.equal(normalizeSpeechResponseFormat("OGG"), "opus");
assert.equal(normalizeSpeechResponseFormat("opus"), "opus");
assert.equal(normalizeSpeechResponseFormat("mp3"), "mp3");
assert.equal(normalizeSpeechResponseFormat(undefined), "mp3");
});
test("OpenAI-compat speech path remaps ogg to opus before upstream", async () => {
const originalFetch = globalThis.fetch;
let captured;
globalThis.fetch = async (_url, options = {}) => {
captured = JSON.parse(String(options.body || "{}"));
return new Response(new Uint8Array([1, 2, 3]), {
status: 200,
headers: { "content-type": "audio/opus" },
});
};
try {
const response = await handleAudioSpeech({
body: {
model: "openai/tts-1",
input: "format check",
voice: "alloy",
response_format: "ogg",
},
credentials: { apiKey: "openai-key" },
});
assert.equal(response.status, 200);
assert.equal(captured.response_format, "opus");
assert.equal(captured.model, "tts-1");
} finally {
globalThis.fetch = originalFetch;
}
});