Multimodal: Video-Eingabe

Ein Echtzeit-Agent kann sehen. Neben dem Audio-Stream können Sie Bild-Frames von einer Kamera (oder einem Bildschirm) an das Modell senden, sodass der Benutzer dem Agenten etwas zeigen kann – ein beschädigtes Produkt für eine Rücksendung, einen Fehler auf einem Bildschirm, ein Dokument – anstatt es zu beschreiben.

Die API

Eine Methode auf dem Runner, die send_audio widerspiegelt:

runner.send_video_frame("image/jpeg", &base64_jpeg).await?;

Sie ist auch auf dem niedrigeren Level RealtimeRunner und auf RealtimeSession direkt verfügbar. Die Standard-Trait-Implementierung ist ein No-Op, sodass Anbieter/Modelle, die keine visuelle Eingabe akzeptieren, Frames einfach ignorieren.

Wie jeder Anbieter Frames verarbeitet

Die beiden Backends behandeln die Vision unterschiedlich, und das sollte beeinflussen, wie oft Sie Frames senden:

AnbieterMechanismusKadenz
Gemini LiveKontinuierliche realtimeInput Medien-ChunksStreamen Sie diese — ~1–2 fps ist natürlich
OpenAI RealtimeEin input_image Teil eines KonversationselementsSnapshots — auf ~1 alle paar Sekunden drosseln

Gemini ist für kontinuierliches Video ausgelegt: Frames fließen wie Audio und das Modell schließt über das sich bewegende Bild. OpenAIs Echtzeit-Vision ist Bild-im-Kontext: jeder Frame wird zu einem Konversationselement, sodass das Senden vieler pro Sekunde den Kontext überflutet und mehr kostet. Senden Sie OpenAI einen Frame, wenn es nützlich ist (z.B. wenn der Benutzer sagte "schau dir das an"), nicht bei jedem Tick.

Die Beispiel-UIs kodieren dies:

const intervalMs = provider === 'gemini' ? 700 : 2500;  // ~1.4 fps vs ~0.4 fps

Frames in einem Browser erfassen

Nimm die Kamera, zeichne den <video> auf eine Leinwand und sende JPEG-Frames über dein WebSocket (die server-seitige Brücke leitet sie an send_video_frame weiter):

const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } });
video.srcObject = stream;

const canvas = document.createElement('canvas');
setInterval(() => {
  if (ws.readyState !== WebSocket.OPEN) return;
  canvas.width = 640; canvas.height = 480;
  canvas.getContext('2d').drawImage(video, 0, 0, 640, 480);
  const data = canvas.toDataURL('image/jpeg', 0.6).split(',')[1];  // strip data: prefix
  ws.send(JSON.stringify({ type: 'video_frame', mime: 'image/jpeg', data }));
}, intervalMs);

Auf dem Server an das Modell weiterleiten:

ClientMsg::VideoFrame { mime, data } => {
    let _ = runner.send_video_frame(&mime, &data).await;  // non-fatal on error
}

Halte Frames bescheiden (640×480, JPEG-Qualität ~0.6) — für die Bilderkennung ist keine volle Auflösung erforderlich, und kleinere Frames bedeuten geringere Latenz und Kosten.

Prompts für die Bilderkennung

Sag dem Agenten, dass er sehen kann, damit er die Kamera natürlich nutzt:

You can hear the customer and SEE what they show their camera. When they show
you an item (e.g. a damaged product for a return), briefly describe what you see
and use it to help resolve the issue.

Ausprobieren

Das customer_service-Beispiel hat ein Kamera-Panel: starte die Kamera, halte ein Objekt hoch und sage "Ich möchte dies zurückgeben — kannst du es sehen?". Es funktioniert am besten mit Gemini (kontinuierliches Video); bei OpenAI argumentiert der Agent über die periodischen Schnappschüsse.

Weiter: Affektiver Dialog →