Gemini Live API는 세션이라고 하는 연속적인 오디오 또는 텍스트 스트림을 처리하여 지연 시간이 짧은 음성 및 텍스트 상호작용을 지원하고, 즉각적이고 사람과 유사한 음성 대답을 제공합니다. 초기 핸드셰이크부터 정상 종료까지의 세션 수명 주기 관리는 개발자가 제어합니다.
이 페이지에서는 Gemini Live API를 사용하여 Gemini 모델로 대화 세션을 시작하는 방법을 보여줍니다. Vertex AI Studio, Google 생성형 AI SDK 또는 WebSocket을 사용하여 세션을 시작할 수 있습니다.
이 페이지에서는 다음을 수행하는 방법도 보여줍니다.
- 기본 시간 제한을 초과하여 세션 연장
- 이전 세션 재개하기
- 세션 중에 시스템 요청 사항 업데이트
- Gemini 3.8 Live를 사용한 세션 중에 시스템 요청 사항 및 도구 업데이트
- 세션의 컨텍스트 윈도우 구성
- 세션의 스크립트 작성 사용 설정
- 고객 관리 암호화 키 (CMEK)로 세션 데이터 암호화
세션 수명
컨텍스트 윈도우 압축이 없으면 토큰 제한으로 인해 오디오 전용 세션은 15분으로 제한되고 오디오-동영상 세션은 2분으로 제한됩니다. 이 한도를 초과하면 세션이 종료되지만 컨텍스트 윈도우 압축을 사용하여 세션을 무제한으로 연장할 수 있습니다.
WebSocket 연결 제약조건으로 인해 연결 수명은 약 10분으로 제한됩니다. 연결이 종료되면 세션도 종료됩니다. 이 경우 세션 재개를 사용하여 여러 연결에서 단일 세션이 활성 상태를 유지하도록 구성할 수 있습니다. 또한 연결이 종료되기 전에 GoAway 메시지가 표시되므로 추가 조치를 취할 수 있습니다.
최대 동시 실행 세션
동시 세션 할당량은 세션이 시작될 때 확인되며 사용한 만큼만 지불하는 표준(표준 PayGo) 또는 프로비저닝된 처리량 사용 여부에 관계없이 적용됩니다.
gemini-3.8-live의 경우 동시 세션 할당량은 Gemini Live API 세션과 라이브 아바타 세션 모두에 적용됩니다. 프로젝트의 특정 한도를 보려면Google Cloud 콘솔의 할당량 및 시스템 한도 페이지로 이동하여gemini-3.8-live를 필터링합니다. 자세한 내용은 Gemini 3.8 Live 동시 세션 할당량을 참조하세요.gemini-live-2.5-flash-native-audio의 경우 기본적으로 프로젝트당 최대 1,000개의 동시 세션을 사용할 수 있습니다.
세션 시작
다음 탭에서는 Vertex AI Studio, Google 생성형 AI SDK 또는 WebSocket을 사용하여 실시간 대화 세션을 시작하는 방법을 보여줍니다.
콘솔
- Vertex AI Studio > 실시간 스트리밍을 엽니다.
- 세션 시작을 클릭하여 대화를 시작합니다.
세션을 종료하려면 세션 중지를 클릭합니다.
Python
시작하기 전에 API 키 또는 애플리케이션 기본 사용자 인증 정보 (ADC)를 사용해 Gemini Enterprise Agent Platform에 인증해야 합니다.
gcloud auth application-default login
인증 설정에 대한 자세한 내용은 빠른 시작을 참조하세요.
import asyncio from google import genai # Replace the PROJECT_ID and LOCATION with your Project ID and location. client = genai.Client(vertexai=True, project="PROJECT_ID", location="LOCATION") # Configuration MODEL = "gemini-3.8-live" config = { "response_modalities": ["audio"], } async def main(): # Establish WebSocket session async with client.aio.live.connect(model=MODEL, config=config) as session: print("Session established. Sending audio...") if __name__ == "__main__": asyncio.run(main())
Python
WebSockets를 사용하는 경우 표준 WebSocket 핸드셰이크로 연결이 설정됩니다. 엔드포인트는 리전별이며 인증에 OAuth 2.0 Bearer 토큰을 사용합니다. 이 시나리오에서는 인증 토큰이 일반적으로 WebSocket 헤더(예: Authorization: Bearer [TOKEN])에 전달됩니다.
import asyncio import websockets # Replace the PROJECT_ID and LOCATION with your Project ID and location. PROJECT_ID = "PROJECT_ID" LOCATION = "LOCATION" # Authentication token_list = !gcloud auth application-default print-access-token ACCESS_TOKEN = token_list[0] # Configuration MODEL_ID = "gemini-3.8-live" MODEL = f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/{MODEL_ID}" config = { "response_modalities": ["audio"], } # Construct the WSS URL HOST = f"{LOCATION}-aiplatform.googleapis.com" URI = f"wss://{HOST}/ws/google.cloud.aiplatform.v1.LlmBidiService/BidiGenerateContent" async def main(): headers = {"Authorization": f"Bearer {ACCESS_TOKEN}"} async with websockets.connect(URI, additional_headers=headers) as ws: print("Session established.") # Send Setup (Handshake) await ws.send(json.dumps({ "setup": { "model": MODEL, "generation_config": config } })) # Send audio/video ... if __name__ == "__main__": asyncio.run(main())
세션 연장하기
대화 세션의 최대 길이 기본값은 10분이며 goAway 알림을 사용하여 연장할 수 있습니다. 세션이 종료되기 60초 전에 goAway 알림(BidiGenerateContentServerMessage.goAway)이 클라이언트에 전송됩니다.
10분 연결 한도를 초과하여 세션을 연장하려면 세션 재개를 사용하여 다시 연결해야 합니다. goAway 알림을 받거나 다른 이유로 연결이 종료되면 세션 중에 가져온 세션 핸들을 사용하여 새 연결을 시작할 수 있습니다. 이렇게 하면 새 연결에서 컨텍스트가 그대로 유지된 상태로 세션이 재개됩니다. 이 작업은 횟수 제한 없이
수행할 수 있습니다 세션 재개 예시는 이전 세션 재개를 참조하세요.
다음 예시에서는 goAway 알림을 리슨하여 임박한 세션 종료를 감지하는 방법을 보여줍니다.
Python
async for response in session.receive(): if response.go_away is not None: # The connection will soon be terminated print(response.go_away.time_left)
이전 세션 재개하기
Gemini Live API는 사용자가 일시적인 연결 해제(예: Wi-Fi에서 5G로 전환) 중에 대화 컨텍스트를 잃지 않도록 세션 재개를 지원합니다. 24시간 이내에 이전 세션을 재개할 수 있습니다. 세션 재개는 텍스트, 동영상, 오디오 프롬프트, 모델 출력을 포함한 캐시된 데이터를 저장하여 수행됩니다. 캐시된 데이터에는 프로젝트 수준의 개인 정보 보호가 적용됩니다.
기본적으로 세션 재개는 중지되어 있습니다. 세션 재개를 사용 설정하려면 BidiGenerateContentSetup 메시지의 sessionResumption 필드를 설정합니다. 사용 설정하면 서버는 session_id 및 재개 토큰이 포함된 SessionResumptionUpdate 메시지를 주기적으로 전송합니다. WebSocket 연결이 끊어지면 클라이언트가 다시 연결하고 새 설정 메시지에 이러한 사용자 인증 정보를 포함할 수 있습니다. 그러면 서버가 이전 컨텍스트를 복원하여 대화를 원활하게 계속할 수 있습니다.
재개 기간은 유한합니다(일반적으로 약 10분). 클라이언트가 이 기간 내에 다시 연결하지 않으면 서버 리소스를 확보하기 위해 세션 상태가 삭제됩니다.
다음 예시에서는 서비스에 연결하고, 세션 재개 핸들을 가져오고, 연결 해제를 시뮬레이션한 다음, 핸들을 사용하여 다시 연결하여 세션을 재개합니다.
Python
import asyncio from google import genai from google.genai import types import websockets # Replace the PROJECT_ID and LOCATION with your Project ID and location. client = genai.Client(vertexai=True, project="PROJECT_ID", location="LOCATION") # Configuration MODEL = "gemini-3.8-live" async def resumable_session_example(): """Demonstrates session resumption by connecting, disconnecting, and reconnecting.""" session_handle = None print("Starting a new session...") try: async with client.aio.live.connect( model=MODEL, config=types.LiveConnectConfig( response_modalities=["audio"], session_resumption=types.SessionResumptionConfig(handle=None), ), ) as session: await session.send_content( content=types.Content(role="user", parts=[types.Part(text="Hello!")]) ) async for message in session.receive(): if message.session_resumption_update: update = message.session_resumption_update if update.resumable and update.new_handle: session_handle = update.new_handle print(f"Received session handle: {session_handle}") # For demonstration, we break to simulate a disconnect # after receiving a handle. break if message.server_content and message.server_content.turn_complete: break except websockets.exceptions.WebSocketException as e: print(f"Initial connection failed: {e}") return if not session_handle: print("Did not receive a session handle. Cannot demonstrate resumption.") return print(f"\nSimulating disconnect and reconnecting with handle {session_handle}...") try: async with client.aio.live.connect( model=MODEL, config=types.LiveConnectConfig( response_modalities=["audio"], session_resumption=types.SessionResumptionConfig(handle=session_handle), ), ) as session: print("Successfully resumed session.") await session.send_content( content=types.Content(role="user", parts=[types.Part(text="I am back!")]) ) async for message in session.receive(): if message.session_resumption_update: update = message.session_resumption_update if update.resumable and update.new_handle: session_handle = update.new_handle print(f"Received updated session handle: {session_handle}") if message.server_content: print(f"Received server content: {message.server_content}") if message.server_content.turn_complete: break print("Resumed session finished.") except websockets.exceptions.WebSocketException as e: print(f"Failed to resume session: {e}") if __name__ == "__main__": asyncio.run(resumable_session_example())
주변 소리 모드로 원활한 세션 재개 사용 설정
세션 재개를 사용 설정하면 투명 모드를 사용 설정하여 사용자가 재개 프로세스를 더 원활하게 진행할 수 있습니다. 투명 모드가 사용 설정되면 컨텍스트 스냅샷에 해당하는 클라이언트 메시지의 색인이 명시적으로 반환됩니다. 이렇게 하면 재개 핸들에서 세션을 재개할 때 다시 전송해야 하는 클라이언트 메시지를 식별하는 데 도움이 됩니다.
주변 소리 모드를 사용 설정하려면 다음 안내를 따르세요.
Python
config = { "response_modalities": ["audio"], "session_resumption_config": { "transparent": True, } }
CMEK로 세션 데이터 암호화
세션 재개는 저장된 캐시된 세션 데이터를 최대 24시간 동안 저장합니다.Google-owned and Google-managed encryption key대신 자체 키로 데이터를 보호하려면 서빙 프로필을 사용합니다. 서빙 프로필은 Cloud Key Management Service 키를 프로젝트, 위치, API 범위에 연결합니다. 서빙 프로필이 있는 동안 Agent Platform은 데이터를 자동으로 암호화합니다. 세션 구성과 요청 형식은 변경되지 않습니다.
Gemini Live API의 서빙 프로필 CMEK는 us 및 eu 멀티 리전에서 지원됩니다. 전역 리전은 지원되지 않습니다.
Gemini Live API에 CMEK를 설정하려면 다음을 수행합니다.
- 프로젝트에서 Cloud KMS API와 Agent Platform API를 사용 설정합니다. 시작하기 전에를 참조하세요.
us또는eu멀티 리전에서 Cloud KMS 키를 만듭니다. 키링 및 키 만들기를 참조하세요.- Gemini Enterprise Agent Platform 서비스 에이전트에 키에 대한
roles/cloudkms.cryptoKeyEncrypterDecrypter역할을 부여합니다. Agent Platform 권한 부여를 참조하세요. scope를GEMINI_LIVE로 설정하고cmekConfig.encryptionSpec.kmsKeyName를 키로 설정하는 서빙 프로필을 만듭니다. 서빙 프로필 만들기를 참조하세요.
세션 중에 시스템 요청 사항 업데이트
Gemini Live API를 사용하면 활성 세션 중에 시스템 요청 사항을 업데이트할 수 있습니다. 이를 사용하여 대답 언어를 변경하거나 어조를 수정하는 등 모델의 대답을 조정합니다.
다음 메서드는 Gemini 2.5 Flash Live API 네이티브 오디오에 적용됩니다. Gemini 3.8 Live의 경우 Gemini 3.8 Live로 시스템 요청 사항 및 도구 업데이트를 참조하세요.
세션 중에 시스템 요청 사항을 업데이트하려면 system 역할로 텍스트 콘텐츠를 전송하면 됩니다. 업데이트된 시스템 요청 사항이 남은 세션 동안 적용됩니다.
Python
session.send_client_content( content=types.Content( role="system", parts=[types.Part(text="new system instruction")] ), turn_complete=False )
Gemini 3.8 Live로 시스템 안내 및 도구 업데이트하기
Gemini 3.8 Live를 사용하면 BidiGenerateContentContextUpdate 메시지를 전송하여 활성 세션의 시스템 요청 사항과 도구를 업데이트할 수 있습니다. 예를 들어 대화가 새 작업으로 이동할 때 대답 언어나 어조를 변경하거나 모델에 다른 함수 집합을 제공할 수 있습니다.
Google 생성형 AI SDK를 사용하여 send_context_update를 호출합니다. WebSocket을 사용하여 클라이언트 메시지의 context_update 필드를 설정합니다. system 역할이 있는 클라이언트 콘텐츠를 Gemini 3.8 Live로 전송하지 마세요.
변경하려는 필드를 설정합니다.
system_instruction: 세션의 나머지 부분에 대해 설정 메시지의 시스템 요청 사항을 대체합니다.tools: 세션의 전체 도구 목록을 대체합니다. 모델이 계속 사용할 수 있어야 하는 모든 도구를 포함합니다. 모든 도구를 삭제하려면 빈 목록을 전송합니다.
설정하지 않은 필드는 현재 값을 유지합니다. 업데이트는 세션의 나머지 입력과 함께 순서대로 처리됩니다.
Python
from google.genai import types # Replace the system instruction. await session.send_context_update( system_instruction="Respond only in Spanish." ) # Replace the tool list. get_current_weather = types.FunctionDeclaration( name="get_current_weather", description="Get the current weather in a given location", parameters=types.Schema( type=types.Type.OBJECT, properties={"location": types.Schema(type=types.Type.STRING)}, ), ) await session.send_context_update( tools=[types.Tool(function_declarations=[get_current_weather])] ) # Remove all tools. await session.send_context_update(tools=[])
서버 측 도구는 세션이 시작될 때 설정되므로 도구 업데이트에 서버 측 도구가 포함된 경우 다음 제한사항이 적용됩니다. 함수 선언은 영향을 받지 않으며 도구 업데이트에 추가할 수 있습니다.
- 도구 업데이트 후 Google 검색을 사용한 그라운딩을 사용하려면 설정 메시지에서
google_search도 선언해야 합니다. - Enterprise용 웹 그라운딩, Agent Search, RAG Engine 도구는 설정 메시지에서만 선언할 수 있습니다. 이러한 문자가 포함된
context_update는INVALID_ARGUMENT오류를 반환합니다.
세션의 컨텍스트 윈도우 구성
Gemini Live API 컨텍스트 윈도우는 실시간 스트리밍 데이터(오디오의 경우 초당 토큰(TPS) 25개, 동영상의 경우 TPS 258개)와 텍스트 입력, 모델 출력 등 기타 콘텐츠를 저장하는 데 사용됩니다. 모든 Gemini Live API 모델의 컨텍스트 윈도우 한도는 128,000개 토큰입니다.
장기 실행 세션에서는 대화가 진행됨에 따라 오디오 및 텍스트 토큰의 기록이 누적됩니다. 이 기록이 모델의 한도를 초과하면 모델이 할루시네이션을 일으키거나 속도가 느려지거나 세션이 강제로 종료될 수 있습니다. 더 긴 세션을 사용 설정하려면 세션 구성의 일부로 contextWindowCompression 필드를 설정하여 컨텍스트 윈도우 압축을 사용 설정하면 됩니다.
컨텍스트 윈도우 압축은 사용 설정된 경우 서버 측 슬라이딩 윈도우를 사용하여 가장 오래된 차례를 자릅니다. 누적된 토큰이 정의된 최대 길이(Vertex AI Studio의 최대 콘텐츠 크기 슬라이더 또는 API의 trigger_tokens를 사용하여 설정)를 초과하면, 서버는 한도 내에서 컨텍스트를 유지하기 위해 가장 오래된 턴을 자동으로 삭제하거나 요약합니다. ContextWindowCompressionConfig에서 슬라이딩 윈도우 메커니즘과 압축을 트리거하는 target_tokens 파라미터에 정의된 토큰 수를 구성할 수 있습니다.
이렇게 하면 '메모리'가 지속적으로 관리되므로 사용자 관점에서 이론적으로 무한한 세션 시간이 가능합니다. 압축이 없으면 오디오 전용 세션이 엄격한 제한에 도달하기 전에 약 15분으로 제한될 수 있습니다.
컨텍스트 길이와 대상 크기의 최소 및 최대 길이는 다음과 같습니다.
| 설정(API 플래그) | 최솟값 | 최댓값 |
|---|---|---|
최대 컨텍스트 길이(trigger_tokens) |
5,000 | 128,000 |
대상 컨텍스트 크기(target_tokens) |
0 | 128,000 |
컨텍스트 윈도우를 설정하려면 다음 단계를 따르세요.
콘솔
- Vertex AI Studio > 실시간 스트리밍을 엽니다.
- 클릭하여 고급 메뉴를 엽니다.
- 세션 컨텍스트 섹션에서 최대 컨텍스트 크기 슬라이더를 사용하여 컨텍스트 크기를 5,000~128,000 사이의 값으로 설정합니다.
- (선택사항) 동일한 섹션에서 대상 컨텍스트 크기 슬라이더를 사용하여 대상 크기를 0~128,000 사이의 값으로 설정합니다.
Python
설정 메시지에서 context_window_compression.trigger_tokens 및 context_window_compression.sliding_window.target_tokens 필드를 설정합니다.
config = { "response_modalities": ["audio"], # Configures compression "context_window_compression" : { "trigger_tokens": 10000, "sliding_window": {"target_tokens" : 512} } }
세션의 오디오 스크립트 작성 사용 설정
입력 및 출력 오디오 모두에 대해 스크립트 작성을 사용 설정할 수 있습니다.
스크립트 작성을 받으려면 세션 구성을 업데이트해야 합니다. input_audio_transcription 및 output_audio_transcription 객체를 추가하고 text가 response_modalities에 포함되어 있는지 확인해야 합니다.
다국어 자동 음성 인식(ASR)의 스크립트 작성 품질을 개선하려면 input_audio_transcription 또는 output_audio_transcription 내에서 language_codes 필드를 사용하여 언어 힌트를 제공하면 됩니다. 힌트를 제공하면 잘못된 언어 감지 위험이 줄어들므로 스크립트 작성 품질을 개선하는 데 도움이 됩니다. 특히 짧은 프롬프트의 경우 더욱 그렇습니다. language_codes 필드는 BCP-47 언어 코드 목록을 허용합니다(예: 'en-US', 'es-US').
config = {
"response_modalities": ["audio", "text"],
"input_audio_transcription": {
"language_codes": ["en-US"]
},
"output_audio_transcription": {},
}
응답 처리
다음 코드 샘플은 구성된 세션을 사용하여 연결하고 오디오 데이터와 함께 텍스트 부분(스크립트)을 추출하는 방법을 보여줍니다.
# Receive Output Loop
async for message in session.receive():
server_content = message.server_content
if server_content:
# Handle Model Turns (Audio + Text)
model_turn = server_content.model_turn
if model_turn and model_turn.parts:
for part in model_turn.parts:
# Handle Text (Transcriptions)
if part.text:
print(f"Transcription: {part.text}")
# Handle Audio
if part.inline_data:
audio_data = part.inline_data.data
# Process audio bytes...
pass
# Check for turn completion
if server_content.turn_complete:
print("Turn complete.")