mirror of
https://github.com/sune-org/us.proxy.sune.chat.git
synced 2026-10-18 14:07:54 +00:00
Send videos to Gemini at 3 fps and allow larger WebSocket payloads
Map video_url parts to inline data for Google and attach videoMetadata.fps = 3 to every video part (media resolution stays at the default). Raise the WebSocket maxPayloadLength from Bun's 16 MB default to 100 MB so threads with several base64 videos still fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,8 @@ Bun.serve({
|
|||||||
},
|
},
|
||||||
|
|
||||||
websocket: {
|
websocket: {
|
||||||
|
// Videos ride along as base64 in every request; Bun's 16 MB default fits only a handful
|
||||||
|
maxPayloadLength: 100 * 1024 * 1024,
|
||||||
open(ws) {
|
open(ws) {
|
||||||
const { uid } = ws.data
|
const { uid } = ws.data
|
||||||
addSocket(uid, ws)
|
addSocket(uid, ws)
|
||||||
|
|||||||
+7
-1
@@ -57,6 +57,10 @@ const inlineFromDataUrl = u => {
|
|||||||
return m ? { inlineData: { mimeType: m[1], data: m[2] } } : null
|
return m ? { inlineData: { mimeType: m[1], data: m[2] } } : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gemini samples video at 1 fps by default; media resolution stays at the default (70 tokens/frame)
|
||||||
|
const VIDEO_FPS = 3
|
||||||
|
const withVideoFps = p => p?.inlineData?.mimeType?.startsWith('video/') ? { ...p, videoMetadata: { fps: VIDEO_FPS } } : p
|
||||||
|
|
||||||
function mapPartToGoogle(p) {
|
function mapPartToGoogle(p) {
|
||||||
if (!p) return null
|
if (!p) return null
|
||||||
if (typeof p === 'string') return p.trim() ? { text: p } : null
|
if (typeof p === 'string') return p.trim() ? { text: p } : null
|
||||||
@@ -65,6 +69,8 @@ function mapPartToGoogle(p) {
|
|||||||
return p.text?.trim() ? { text: p.text } : null
|
return p.text?.trim() ? { text: p.text } : null
|
||||||
case 'image_url':
|
case 'image_url':
|
||||||
return inlineFromDataUrl(p.image_url?.url || p.image_url)
|
return inlineFromDataUrl(p.image_url?.url || p.image_url)
|
||||||
|
case 'video_url':
|
||||||
|
return inlineFromDataUrl(p.video_url?.url || p.video_url)
|
||||||
case 'input_audio':
|
case 'input_audio':
|
||||||
return p.input_audio?.data
|
return p.input_audio?.data
|
||||||
? { inlineData: { mimeType: p.input_audio.format === 'mp3' ? 'audio/mp3' : 'audio/wav', data: p.input_audio.data } }
|
? { inlineData: { mimeType: p.input_audio.format === 'mp3' ? 'audio/mp3' : 'audio/wav', data: p.input_audio.data } }
|
||||||
@@ -87,7 +93,7 @@ function mapToGoogleContents(messages) {
|
|||||||
if (!m || m.role === 'system') continue
|
if (!m || m.role === 'system') continue
|
||||||
const role = m.role === 'assistant' ? 'model' : 'user'
|
const role = m.role === 'assistant' ? 'model' : 'user'
|
||||||
const src = Array.isArray(m.content) ? m.content : [{ type: 'text', text: String(m.content ?? '') }]
|
const src = Array.isArray(m.content) ? m.content : [{ type: 'text', text: String(m.content ?? '') }]
|
||||||
const parts = src.map(mapPartToGoogle).filter(Boolean)
|
const parts = src.map(mapPartToGoogle).filter(Boolean).map(withVideoFps)
|
||||||
for (const img of m.images || []) {
|
for (const img of m.images || []) {
|
||||||
const ip = inlineFromDataUrl(img?.image_url?.url || img?.image_url)
|
const ip = inlineFromDataUrl(img?.image_url?.url || img?.image_url)
|
||||||
if (ip) parts.push(ip)
|
if (ip) parts.push(ip)
|
||||||
|
|||||||
Reference in New Issue
Block a user