카메라 에이전트
카메라 에이전트 (Camera Agent)
이 카메라 에이전트는 마이크 오디오와 초당 하나의 카메라 프레임을 realtime 세션으로 스트리밍한 다음, 음성 응답을 재생하고 자막을 붙여요. 물체에 대해 묻고 싶을 때 물체를 가리키거나, Watch 모드를 켜서 능동 나레이션을 받거나, 스케치를 보여줘 다시 그리게 할 수 있어요.
이 예시가 보여주는 것:
- 프로필에서 파생된 PCM 샘플 레이트를 사용하는 공급자-불가지론 realtime 세션
BinaryContent를 사용한 이미지 입력turn_coverage='all_input'와 Watch 토글을 사용한 라이브 비전- 다이어그램 렌더링을 두 번째
Agent에게 위임하는 일반 함수 도구 WebSearch와 클릭 가능한 인용을 사용한 웹 검색- 모델 선택기와 공급자 인식 음성, 양식(modality), VAD, Gemini 설정
예시 실행하기
리포지토리 루트의 .env에 선택기 모델에 대한 자격 증명을 추가하세요. 예:
GOOGLE_API_KEY=your-google-api-key
스케치 다시 그리기 도구는 별도의 드로잉 에이전트(google:gemini-3.5-flash가 기본)에게 위임하며, 이 에이전트는 같은 GOOGLE_API_KEY를 재사용해요. CAMERA_DRAW_MODEL을 자격 증명이 커버하는 다른 provider:model로 설정하거나, CAMERA_DRAW=false로 드로잉을 끌 수 있어요. 어시스턴트의 나머지 부분은 어느 쪽이든 작동해요.
의존성 설치와 환경 변수 설정이 끝나면 로컬 서버를 시작하세요:
터미널
python -m pydantic_ai_examples.realtime_camera.app
터미널
uv run -m pydantic_ai_examples.realtime_camera.app
http://localhost:8000을 열고 Start를 선택한 다음 카메라와 마이크 접근을 허용하세요.
모델 기본값은 google:gemini-3.1-flash-live-preview이며, CAMERA_REALTIME_MODEL로 바꾸거나 선택기로 세션별로 Google, OpenAI, Azure OpenAI provider:model로 전환할 수 있어요 (xAI realtime은 카메라 이미지 입력을 지원하지 않아요). 선택된 모델의 realtime 프로필이 브라우저의 PCM 입력·출력 샘플 레이트를 제공해요: Gemini 입력은 16kHz를, OpenAI와 Azure 입력은 24kHz를 사용해요.
예시를 로컬에 유지하세요
WebSocket은 서버의 공급자 자격 증명을 사용하며 사용자 인증이 없어요. 예시는 브라우저의 origin이 서빙되는 호스트와 일치하는지 확인하지만, 이는 운영 환경 access control이 아니라 개발용 방어 장치예요.
Cloudflare quick tunnel, ngrok, 공용 리버스 프록시로 서버를 노출하지 마세요. 다른 기기의 경우 인증과 TLS 뒤에서 통제하는 네트워크에 배포하고, 환경에 맞는 사용자 수준 할당량과 요율 제한을 적용하세요.
Watch 모드
카메라 프레임은 시각적 맥락을 추가하지만 모델 턴을 시작하지 않아요. _Watch_는 모델이 유휴 상태일 때 주기적으로 짧은 텍스트 턴을 보내 이미 진행 중인 음성을 방해하지 않으면서 시각적 변화를 보고하도록 유도해요. CAMERA_WATCH_PROMPT로 그 지시를 커스터마이즈할 수 있어요.
Gemini 네이티브 오디오 모델은 말할 것이 없다고 판단할 수 있어요:
export CAMERA_PROACTIVE=true
export CAMERA_AFFECTIVE=true
CAMERA_TURN_COVERAGE는 기본값이 all_input이며, Gemini Developer API와 Vertex AI 모두에서 작동해요. Watch 모드는 켜져 있는 동안 토큰을 소비해요.
검색과 인용
CAMERA_WEB_SEARCH=true(기본값)이면, 선택된 모델 프로필이 네이티브 검색을 지원할 때 예시가 WebSearch를 추가해요. 네이티브 도구 반환 이벤트는 인용 칩으로 변환되며, 브라우저는 HTTP(S) 소스 URL만 허용해요.
다이어그램 다시 그리기
CAMERA_DRAW=true(기본값)이면 realtime 에이전트가 redraw_diagram을 호출할 수 있어요. 보이는 스케치의 자세한 텍스트 설명을 별도의 Agent에 전달하면, 그 에이전트가 자체 포함된 HTML을 만들어요. 브라우저는 그 HTML을 스크립트와 네트워크 접근을 차단하는 불투명 origin iframe에 표시하고, PNG 내보내기 동작을 유지해요.
기본값은 사용자가 라이브 통화를 기다리고 있기 때문에 빠른 소형 모델이에요: redraw의 지연은 HTML 출력 토큰이 지배하므로, 더 큰 모델은 주로 생각 시간만 늘리고 품질은 늘리지 않아요. 드로잉 모델을 독립적으로 구성하세요:
export CAMERA_DRAW_MODEL=anthropic:claude-haiku-4-5
선택된 realtime 모델이 둘 다 지원할 때 드로잉과 웹 검색은 함께 켜진 채 유지돼요. 도구는 동시에 실행되므로 드로잉이 음성 대화를 대체하지 않아요.
Vertex AI
조직이 Gemini API 키를 허용하지 않을 때 Application Default Credentials를 사용하세요:
gcloud auth application-default login
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=your-project
export GOOGLE_CLOUD_LOCATION=us-central1
브리지 작동 방식
브라우저와 공급자는 _run_session의 두 개의 작은 동시 펌프로 연결돼요:
browser ── PCM16 + JPEG/text ──▶ FastAPI /ws ──▶ RealtimeSession
browser ◀── PCM16 + JSON events ──────────────── RealtimeSession
마이크 캡처가 시작되기 전에 서버는 프로필 파생 오디오 레이트와 함께 JSON 채널로 session_config를 보내요. 그다음 인바운드 펌프가 PCM, 이미지, 텍스트, Watch 메시지를 전달해요. 이벤트 펌프는 오디오, 트랜스크립트, barge-in 알림, 근거 인용, 드로잉 업데이트, 턴 완료를 반환해요. 어느 쪽이든 종료되면 다른 펌프가 취소되고 세션이 깨끗하게 닫혀요.
예제 코드
서버에는 realtime 브리지와 하위 Watch, 근거, 드로잉 헬퍼가 들어 있어요:
app.py
from __future__ import annotations
import base64
import json
import os
import re
from collections.abc import Awaitable, Callable, Mapping
from contextlib import suppress
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path
from typing import cast
from urllib.parse import urlsplit
import anyio
import logfire
from dotenv import load_dotenv
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from pydantic_ai import (
Agent,
BinaryContent,
PartDeltaEvent,
PartEndEvent,
RunContext,
SpeechPartDelta,
)
from pydantic_ai.capabilities import WebSearch
from pydantic_ai.exceptions import ModelAPIError, UserError
from pydantic_ai.messages import NativeToolReturnPart, TextPartDelta
from pydantic_ai.native_tools import WebSearchTool
from pydantic_ai.realtime import (
RealtimeError,
RealtimeEvent,
RealtimeInputSpeechStartEvent,
RealtimeModel,
RealtimeModelSettings,
RealtimeResponseInterruptedEvent,
RealtimeSession,
RealtimeTurnCompleteEvent,
ReconnectPolicy,
TurnDetection,
infer_realtime_model,
)
from pydantic_ai.realtime.google import (
AutomaticVAD,
GoogleRealtimeModel,
GoogleRealtimeModelSettings,
)
from pydantic_ai.realtime.openai import (
OpenAIRealtimeModel,
OpenAIRealtimeModelSettings,
)
load_dotenv()
(전체 예제 코드는 카메라 브리지의 환경 변수 설정, _same_origin origin 검사, redraw_diagram 도구, _web_search_supported/_build_agent 헬퍼, app.py의 FastAPI WebSocket 엔드포인트, 그리고 index.html 프런트엔드(마이크 캡처, PCM 재생, 프레임 캡처, Watch, 자막, 드로잉 보드)로 구성돼요. 전체 소스는 위의 "브리지 작동 방식" 설명과 함께 원문 문서와 GitHub 예시 리포지토리에서 확인할 수 있어요.)
출처: 문서