From e4fef27aac2a99b7e04d69865ce645555927602b Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Fri, 26 Jun 2026 05:00:03 -0700 Subject: [PATCH] fix(gemini): normalize audio input mime --- open-sse/translator/helpers/geminiHelper.ts | 18 +++++++++--------- .../unit/gemini-helper-audio-input-912.test.ts | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/open-sse/translator/helpers/geminiHelper.ts b/open-sse/translator/helpers/geminiHelper.ts index b5bf0780b8..6f054bcb04 100644 --- a/open-sse/translator/helpers/geminiHelper.ts +++ b/open-sse/translator/helpers/geminiHelper.ts @@ -95,6 +95,14 @@ export const DEFAULT_SAFETY_SETTINGS = [ { category: "HARM_CATEGORY_CIVIC_INTEGRITY", threshold: "OFF" }, ]; +function normalizeAudioMimeType(format: unknown): string { + const normalized = String(format || "wav").toLowerCase(); + if (normalized === "mp3") { + return "audio/mpeg"; + } + return `audio/${normalized}`; +} + // Convert OpenAI content to Gemini parts export function convertOpenAIContentToParts(content: unknown): JsonRecord[] { const parts: JsonRecord[] = []; @@ -107,19 +115,11 @@ export function convertOpenAIContentToParts(content: unknown): JsonRecord[] { if (rec.type === "text") { parts.push({ text: rec.text }); } else if (rec.type === "input_audio" || rec.type === "audio") { - // OpenAI Chat Completions audio input shape (ports decolua/9router#912 + #913): - // { type:"input_audio", input_audio:{data,format} } — some clients use the - // { type:"audio", audio:{data,format} } shape — -> Gemini - // `inlineData: { mimeType: "audio/", data }`. mp3 normalizes to the - // canonical `audio/mpeg`; a leading `data:;base64,` prefix is stripped so - // Gemini receives raw base64. const audio = toRecord(rec.input_audio || rec.audio); if (typeof audio.data === "string" && audio.data) { - const format = typeof audio.format === "string" && audio.format ? audio.format : "wav"; - const mimeType = format === "mp3" ? "audio/mpeg" : `audio/${format}`; parts.push({ inlineData: { - mimeType, + mimeType: normalizeAudioMimeType(audio.format), data: audio.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""), }, }); diff --git a/tests/unit/gemini-helper-audio-input-912.test.ts b/tests/unit/gemini-helper-audio-input-912.test.ts index 79473f3e48..6ca2960110 100644 --- a/tests/unit/gemini-helper-audio-input-912.test.ts +++ b/tests/unit/gemini-helper-audio-input-912.test.ts @@ -23,7 +23,6 @@ test("convertOpenAIContentToParts maps input_audio (mp3) and strips a data: pref const parts = gemini.convertOpenAIContentToParts([ { type: "input_audio", input_audio: { data: "data:audio/mp3;base64,QUJDRA==", format: "mp3" } }, ]); - // mp3 normalizes to the canonical audio/mpeg (matches the #913 translator test). assert.deepEqual(parts, [{ inlineData: { mimeType: "audio/mpeg", data: "QUJDRA==" } }]); });