feat(translator): add support for handling video URLs in Gemini requests

- Updated `ConvertOpenAIRequestToGemini` to process `video_url` message types, extracting and embedding video metadata (MIME type and base64 data) into Gemini request parts.
- Added corresponding unit tests to validate `video_url` handling, ensuring proper extraction and data preservation.

Closes: #3920
This commit is contained in:
Luis Pater
2026-06-20 14:46:39 +08:00
parent 09179a707f
commit 35c3d80ab9
2 changed files with 44 additions and 0 deletions
@@ -196,6 +196,18 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
p++
}
}
case "video_url":
videoURL := item.Get("video_url.url").String()
if len(videoURL) > 5 {
pieces := strings.SplitN(videoURL[5:], ";", 2)
if len(pieces) == 2 && len(pieces[1]) > 7 {
mime := pieces[0]
data := pieces[1][7:]
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".inlineData.mime_type", mime)
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".inlineData.data", data)
p++
}
}
case "file":
filename := item.Get("file.filename").String()
fileData := item.Get("file.file_data").String()
@@ -59,6 +59,38 @@ func TestConvertOpenAIRequestToGeminiPreservesInputAudio(t *testing.T) {
}
}
func TestConvertOpenAIRequestToGeminiPreservesVideoURL(t *testing.T) {
inputJSON := `{
"model": "gemini-3-flash",
"messages": [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "data:video/mp4;base64,AAAAIGZ0eXBtcDQy"}},
{"type": "text", "text": "Describe the video"}
]
}
]
}`
result := ConvertOpenAIRequestToGemini("gemini-3-flash", []byte(inputJSON), false)
resultJSON := gjson.ParseBytes(result)
parts := resultJSON.Get("contents.0.parts").Array()
if len(parts) != 2 {
t.Fatalf("parts length = %d, want 2. parts=%s", len(parts), resultJSON.Get("contents.0.parts").Raw)
}
if got := parts[0].Get("inlineData.mime_type").String(); got != "video/mp4" {
t.Fatalf("video mime_type = %q, want %q", got, "video/mp4")
}
if got := parts[0].Get("inlineData.data").String(); got != "AAAAIGZ0eXBtcDQy" {
t.Fatalf("video data = %q, want %q", got, "AAAAIGZ0eXBtcDQy")
}
if got := parts[1].Get("text").String(); got != "Describe the video" {
t.Fatalf("text part = %q, want prompt text", got)
}
}
func TestConvertOpenAIRequestToGeminiCleansToolSchemaRequiredFields(t *testing.T) {
inputJSON := `{
"model": "gemini-2.0-flash",