Live API 기능 가이드
Live API 기능 가이드
이것은 Live API에서 사용할 수 있는 기능과 구성을 다루는 종합 가이드예요.
개요와 일반 사용 사례의 샘플 코드는 Live API 시작하기 페이지를 참조하세요.
출처: 원문
본문
시작하기 전에
- 핵심 개념 숙지: 아직 읽지 않았다면 먼저 Live API 시작하기 페이지를 읽으세요. Live API의 기본 원리, 작동 방식, 다양한 구현 접근 방식을 소개할 거예요.
- AI Studio에서 Live API 시도: 구축을 시작하기 전에 Google AI Studio에서 Live API를 시도해 보는 것이 유용할 수 있어요. Google AI Studio에서 Live API를 사용하려면 Stream을 선택하세요.
모델 비교
다음 표는 Gemini 3.8 Live, Gemini 3.8 Live Extended Thinking, Gemini 3.1 Flash Live Preview 모델 간의 주요 차이점을 요약해요.
| 기능 | Gemini 3.8 Live | Gemini 3.8 Live Extended Thinking | Gemini 3.1 Flash Live Preview |
|---|---|---|---|
| 권장 용도 | 대부분의 저지연 음성 에이전트 경험의 기본 옵션 | 더 높은 백그라운드 추론이 필요할 때 권장 | 레거시 미리보기 모델. Gemini 3.8 Live로 업데이트 권장 |
| Thinking | 지원(교차 추론). thinkingLevel은 미지원(설정에서 생략) | 지원. 구성 가능한 백그라운드 추론(thinkingLevel: low, medium, high; minimal은 미지원) | thinkingLevel로 thinking 깊이 제어(minimal, low, medium, high 설정). 최저 지연 시간을 위해 기본값 minimal 사용. Live API의 Thinking 참조 |
| 응답 수신 | 단일 서버 이벤트가 여러 콘텐츠 파트를 동시에 포함할 수 있음 | 단일 서버 이벤트가 여러 콘텐츠 파트를 동시에 포함할 수 있음. 비동기 추론이 활성화되면 turnComplete: true가 유휴 세션을 나타내지 않음; interaction_status(IN_PROGRESS 대 IDLE) 사용 | 단일 서버 이벤트가 여러 콘텐츠 파트를 동시에 포함할 수 있음(예: inlineData 및 transcript). 콘텐츠를 놓치지 않도록 각 이벤트의 모든 파트를 처리하는지 확인 |
| 클라이언트 콘텐츠 | 세션 전체 수명 주기에서 명시적 역할(user 또는 model)로 send_client_content 지원. turn_complete=true는 무조건 생성 중단 | 세션 전체 수명 주기에서 명시적 역할(user 또는 model)로 send_client_content 지원. turn_complete=true는 무조건 생성 중단 | 세션 전체 수명 주기에서 명시적 역할(user 또는 model)로 send_client_content 지원. turn_complete=true는 무조건 생성 중단 |
| 비동기 함수 호출(behavior: NON_BLOCKING) | 지원(기본값). behavior: NON_BLOCKING 설정 또는 behavior: BLOCKING으로 하위 호환 차단 모드. 함수 스케줄링(SILENT, WHEN_IDLE, INTERRUPTED) 지원 | 지원(Async 전용). NON_BLOCKING 실행만 지원. 차단 모드와 함수 스케줄링 미지원 | 미지원. 함수 호출은 순차 전용. 도구 응답을 보내기 전까지 모델이 응답을 시작하지 않음 |
Gemini 3.8 Live로 마이그레이션하려면 마이그레이션 가이드를 참조하세요.
Thinking에 대해 더 알아보려면 Thinking 가이드와 업그레이드 가이드를 참조하세요.
연결 수립
다음 예시는 API 키로 연결을 만드는 방법을 보여줘요.
import asyncio
from google import genai
client = genai.Client()
model = "gemini-3.8-live"
config = {"response_modalities": ["AUDIO"]}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
print("Session started")
# Send content...
if __name__ == "__main__":
asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';
const ai = new GoogleGenAI({});
const model = 'gemini-3.8-live';
const config = { responseModalities: [Modality.AUDIO] };
async function main() {
const session = await ai.live.connect({
model: model,
callbacks: {
onopen: function () {
console.debug('Opened');
},
onmessage: function (message) {
console.debug(message);
},
onerror: function (e) {
console.debug('Error:', e.message);
},
onclose: function (e) {
console.debug('Close:', e.reason);
},
},
config: config,
});
console.debug("Session started");
// Send content...
session.close();
}
main();
상호작용 모달리티
다음 섹션은 Live API에서 사용 가능한 다양한 입력·출력 모달리티에 대한 예시와 지원 컨텍스트를 제공해요.
오디오 보내기
오디오는 원시 PCM 데이터(원시 16비트 PCM 오디오, 16kHz, 리틀 엔디언)로 보내야 해요.
# Assuming 'chunk' is your raw PCM audio bytes
await session.send_realtime_input(
audio=types.Blob(
data=chunk,
mime_type="audio/pcm;rate=16000"
)
)
// Assuming 'chunk' is a Buffer of raw PCM audio
session.sendRealtimeInput({
audio: {
data: chunk.toString('base64'),
mimeType: 'audio/pcm;rate=16000'
}
});
오디오 형식
Live API의 오디오 데이터는 항상 원시, 리틀 엔디언, 16비트 PCM이에요. 오디오 출력은 항상 24kHz 샘플 레이트를 사용해요. 입력 오디오는 기본적으로 16kHz이지만, Live API는 필요시 재샘플링하므로 어떤 샘플 레이트든 보낼 수 있어요. 입력 오디오의 샘플 레이트를 전달하려면 오디오를 포함하는 각 Blob의 MIME 유형을 audio/pcm;rate=16000 같은 값으로 설정하세요.
오디오 수신
모델의 오디오 응답은 데이터 청크로 수신돼요.
async for response in session.receive():
if response.server_content and response.server_content.model_turn:
for part in response.server_content.model_turn.parts:
if part.inline_data:
audio_data = part.inline_data.data
# Process or play the audio data
// Inside the onmessage callback
const content = response.serverContent;
if (content?.modelTurn?.parts) {
for (const part of content.modelTurn.parts) {
if (part.inlineData) {
const audioData = part.inlineData.data;
// Process or play audioData (base64 encoded string)
}
}
}
텍스트 보내기
텍스트는 send_realtime_input(Python) 또는 sendRealtimeInput(JavaScript)로 보낼 수 있어요.
await session.send_realtime_input(text="Hello, how are you?")
session.sendRealtimeInput({
text: 'Hello, how are you?'
});
비디오 보내기
비디오 프레임은 특정 프레임 레이트(초당 최대 1프레임)로 개별 이미지(예: JPEG 또는 PNG)로 보내져요.
# Assuming 'frame' is your JPEG-encoded image bytes
await session.send_realtime_input(
video=types.Blob(
data=frame,
mime_type="image/jpeg"
)
)
// Assuming 'frame' is a Buffer of JPEG-encoded image data
session.sendRealtimeInput({
video: {
data: frame.toString('base64'),
mimeType: 'image/jpeg'
}
});
증분 콘텐츠 업데이트
증분 업데이트를 사용해 텍스트 입력을 보내거나, 세션 컨텍스트를 설정하거나, 세션 컨텍스트를 복원할 수 있어요. 짧은 컨텍스트의 경우 턴별 상호작용을 보내 정확한 이벤트 시퀀스를 나타낼 수 있어요.
turns = [
{"role": "user", "parts": [{"text": "What is the capital of France?"}]},
{"role": "model", "parts": [{"text": "Paris"}]},
]
await session.send_client_content(turns=turns, turn_complete=False)
turns = [{"role": "user", "parts": [{"text": "What is the capital of Germany?"}]}]
await session.send_client_content(turns=turns, turn_complete=True)
let inputTurns = [
{ "role": "user", "parts": [{ "text": "What is the capital of France?" }] },
{ "role": "model", "parts": [{ "text": "Paris" }] },
]
session.sendClientContent({ turns: inputTurns, turnComplete: false })
inputTurns = [{ "role": "user", "parts": [{ "text": "What is the capital of Germany?" }] }]
session.sendClientContent({ turns: inputTurns, turnComplete: true })
더 긴 컨텍스트의 경우 후속 상호작용을 위한 컨텍스트 창을 확보하기 위해 단일 메시지 요약을 제공하는 것이 좋아요. 세션 컨텍스트 로딩의 또 다른 방법은 세션 재개를 참조하세요.
오디오 전사
모델 응답 외에도 오디오 출력과 오디오 입력 모두의 전사를 받을 수 있어요.
모델의 오디오 출력 전사를 활성화하려면 설정 구성에서 output_audio_transcription을 보내세요. 전사 언어는 모델의 응답에서 추론돼요.
import asyncio
from google import genai
from google.genai import types
client = genai.Client()
model = "gemini-3.8-live"
config = {
"response_modalities": ["AUDIO"],
"output_audio_transcription": {}
}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
message = "Hello? Gemini are you there?"
await session.send_client_content(
turns={"role": "user", "parts": [{"text": message}]}, turn_complete=True
)
async for response in session.receive():
if response.server_content.model_turn:
print("Model turn:", response.server_content.model_turn)
if response.server_content.output_transcription:
print("Transcript:", response.server_content.output_transcription.text)
if __name__ == "__main__":
asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';
const ai = new GoogleGenAI({});
const model = 'gemini-3.8-live';
const config = {
responseModalities: [Modality.AUDIO],
outputAudioTranscription: {}
};
async function live() {
const responseQueue = [];
async function waitMessage() {
let done = false;
let message = undefined;
while (!done) {
message = responseQueue.shift();
if (message) {
done = true;
} else {
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
return message;
}
async function handleTurn() {
const turns = [];
let done = false;
while (!done) {
const message = await waitMessage();
turns.push(message);
if (message.serverContent && message.serverContent.turnComplete) {
done = true;
}
}
return turns;
}
const session = await ai.live.connect({
model: model,
callbacks: {
onopen: function () {
console.debug('Opened');
},
onmessage: function (message) {
responseQueue.push(message);
},
onerror: function (e) {
console.debug('Error:', e.message);
},
onclose: function (e) {
console.debug('Close:', e.reason);
},
},
config: config,
});
const inputTurns = 'Hello how are you?';
session.sendClientContent({ turns: inputTurns });
const turns = await handleTurn();
for (const turn of turns) {
if (turn.serverContent && turn.serverContent.outputTranscription) {
console.debug('Received output transcription: %s\n', turn.serverContent.outputTranscription.text);
}
}
session.close();
}
async function main() {
await live().catch((e) => console.error('got error', e));
}
main();
모델의 오디오 입력 전사를 활성화하려면 설정 구성에서 input_audio_transcription을 보내세요.
import asyncio
from pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
model = "gemini-3.8-live"
config = {
"response_modalities": ["AUDIO"],
"input_audio_transcription": {},
}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
audio_data = Path("16000.pcm").read_bytes()
await session.send_realtime_input(
audio=types.Blob(data=audio_data, mime_type='audio/pcm;rate=16000')
)
async for msg in session.receive():
if msg.server_content.input_transcription:
print('Transcript:', msg.server_content.input_transcription.text)
if __name__ == "__main__":
asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';
const { WaveFile } = pkg;
const ai = new GoogleGenAI({});
const model = 'gemini-3.8-live';
const config = {
responseModalities: [Modality.AUDIO],
inputAudioTranscription: {}
};
async function live() {
const responseQueue = [];
async function waitMessage() {
let done = false;
let message = undefined;
while (!done) {
message = responseQueue.shift();
if (message) {
done = true;
} else {
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
return message;
}
async function handleTurn() {
const turns = [];
let done = false;
while (!done) {
const message = await waitMessage();
turns.push(message);
if (message.serverContent && message.serverContent.turnComplete) {
done = true;
}
}
return turns;
}
const session = await ai.live.connect({
model: model,
callbacks: {
onopen: function () {
console.debug('Opened');
},
onmessage: function (message) {
responseQueue.push(message);
},
onerror: function (e) {
console.debug('Error:', e.message);
},
onclose: function (e) {
console.debug('Close:', e.reason);
},
},
config: config,
});
// Send Audio Chunk
const fileBuffer = fs.readFileSync("16000.wav");
// Ensure audio conforms to API requirements (16-bit PCM, 16kHz, mono)
const wav = new WaveFile();
wav.fromBuffer(fileBuffer);
wav.toSampleRate(16000);
wav.toBitDepth("16");
const base64Audio = wav.toBase64();
// If already in correct format, you can use this:
// const fileBuffer = fs.readFileSync("sample.pcm");
// const base64Audio = Buffer.from(fileBuffer).toString('base64');
session.sendRealtimeInput(
{
audio: {
data: base64Audio,
mimeType: "audio/pcm;rate=16000"
}
}
);
const turns = await handleTurn();
for (const turn of turns) {
if (turn.text) {
console.debug('Received text: %s\n', turn.text);
}
else if (turn.data) {
console.debug('Received inline data: %s\n', turn.data);
}
else if (turn.serverContent && turn.serverContent.inputTranscription) {
console.debug('Received input transcription: %s\n', turn.serverContent.inputTranscription.text);
}
}
session.close();
}
async function main() {
await live().catch((e) => console.error('got error', e));
}
main();
음성 및 언어 변경
네이티브 오디오 출력 모델은 텍스트 음성 변환(TTS) 모델에서 사용 가능한 음성 중 어떤 것이든 지원해요. AI Studio에서 모든 음성을 들어볼 수 있어요.
음성을 지정하려면 세션 구성의 일부로 speechConfig 객체 내에 음성 이름을 설정하세요.
config = {
"response_modalities": ["AUDIO"],
"speech_config": {
"voice_config": {"prebuilt_voice_config": {"voice_name": "Kore"}}
},
}
const config = {
responseModalities: [Modality.AUDIO],
speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: "Kore" } } }
};
Live API는 여러 언어를 지원해요. 네이티브 오디오 출력 모델은 적절한 언어를 자동으로 선택하며 언어 코드를 명시적으로 설정하는 것을 지원하지 않아요.
네이티브 오디오 기능
최신 모델은 자연스럽고 현실적인 음성과 개선된 다국어 성능을 제공하는 네이티브 오디오 출력을 갖추고 있어요.
Thinking
Gemini 3.8 Live Extended Thinking과 Gemini 3.1 모델은 thinkingLevel을 사용해 thinking 깊이를 제어해요. gemini-3.8-live의 경우 thinkingLevel은 지원되지 않으며 설정에서 생략해야 해요. Gemini 3.8 Live Extended Thinking은 low, medium, high를 지원해요(minimal은 미지원). Gemini 3.1 모델은 minimal, low, medium, high를 지원해요. 자세한 내용은 Live API의 Thinking을 참조하세요.
model = "gemini-3.8-live-extended-thinking"
config = types.LiveConnectConfig(
response_modalities=["AUDIO"]
thinking_config=types.ThinkingConfig(
thinking_level="low",
)
)
async with client.aio.live.connect(model=model, config=config) as session:
# Send audio input and receive audio
const model = 'gemini-3.8-live-extended-thinking';
const config = {
responseModalities: [Modality.AUDIO],
thinkingConfig: {
thinkingLevel: 'low',
},
};
async function main() {
const session = await ai.live.connect({
model: model,
config: config,
callbacks: ...,
});
// Send audio input and receive audio
session.close();
}
main();
또한 구성에서 includeThoughts를 true로 설정해 thought 요약을 활성화할 수 있어요. 자세한 내용은 thought 요약을 참조하세요.
model = "gemini-3.8-live-extended-thinking"
config = types.LiveConnectConfig(
response_modalities=["AUDIO"]
thinking_config=types.ThinkingConfig(
thinking_level="low",
include_thoughts=True
)
)
const model = 'gemini-3.8-live-extended-thinking';
const config = {
responseModalities: [Modality.AUDIO],
thinkingConfig: {
thinkingLevel: 'low',
includeThoughts: true,
},
};
정서 대화(Affective dialog)
이 기능은 Gemini가 입력 표현과 어조에 맞게 응답 스타일을 적응시키게 해요.
정서 대화를 사용하려면 api 버전을 v1beta로 설정하고 setup 메시지에서 enable_affective_dialog를 true로 설정하세요.
client = genai.Client(http_options={"api_version": "v1beta"})
config = types.LiveConnectConfig(
response_modalities=["AUDIO"],
enable_affective_dialog=True
)
const ai = new GoogleGenAI({ httpOptions: {"apiVersion": "v1beta"} });
const config = {
responseModalities: [Modality.AUDIO],
enableAffectiveDialog: true
};
능동 오디오(Proactive audio)
이 기능이 활성화되면 Gemini는 콘텐츠가 관련이 없는 경우 응답하지 않기로 능동적으로 결정할 수 있어요.
이를 사용하려면 api 버전을 v1beta로 설정하고 setup 메시지에서 proactivity 필드를 구성하며 proactive_audio를 true로 설정하세요.
client = genai.Client(http_options={"api_version": "v1beta"})
config = types.LiveConnectConfig(
response_modalities=["AUDIO"],
proactivity={'proactive_audio': True}
)
const ai = new GoogleGenAI({ httpOptions: {"apiVersion": "v1beta"} });
const config = {
responseModalities: [Modality.AUDIO],
proactivity: { proactiveAudio: true }
}
실시간 번역
Live API는 구어 대화의 실시간 저지연 번역을 지원해요. 이 기능으로 실시간 음성-음성 번역 애플리케이션을 구축할 수 있어요.
자세한 내용과 예시는 Live 번역 가이드를 참조하세요.
음성 활동 감지(VAD)
음성 활동 감지(VAD)는 모델이 사람이 말하는 시점을 인식할 수 있게 해줘요. 이는 사용자가 언제든 모델을 방해할 수 있도록 해 자연스러운 대화를 만드는 데 필수적이에요.
VAD가 방해를 감지하면 진행 중인 생성이 취소되고 폐기돼요. 이미 클라이언트로 보낸 정보만 세션 히스토리에 유지돼요. 그런 다음 서버가 BidiGenerateContentServerContent 메시지를 보내 방해를 보고해요. Gemini 서버는 보류 중인 함수 호출을 폐기하고 취소된 호출의 ID로 BidiGenerateContentServerContent 메시지를 보내요.
async for response in session.receive():
if response.server_content.interrupted is True:
# The generation was interrupted
# If realtime playback is implemented in your application,
# you should stop playing audio and clear queued playback here.
const turns = await handleTurn();
for (const turn of turns) {
if (turn.serverContent && turn.serverContent.interrupted) {
// The generation was interrupted
// If realtime playback is implemented in your application,
// you should stop playing audio and clear queued playback here.
}
}
자동 VAD
기본적으로 모델은 연속 오디오 입력 스트림에서 자동으로 VAD를 수행해요. VAD는 setup 구성의 realtimeInputConfig.automaticActivityDetection 필드로 구성할 수 있어요. 오디오 스트림이 1초 이상 일시 중지되면(예: 사용자가 마이크를 껐을 때) 캐시된 오디오를 플러시하기 위해 audioStreamEnd 이벤트를 보내야 해요. 클라이언트는 언제든 오디오 데이터 전송을 재개할 수 있어요.
# example audio file to try:
# URL = "https://storage.googleapis.com/generativeai-downloads/data/hello_are_you_there.pcm"
# !wget -q $URL -O sample.pcm
import asyncio
from pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
model = "gemini-3.8-live"
config = {"response_modalities": ["AUDIO"]}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
audio_bytes = Path("sample.pcm").read_bytes()
await session.send_realtime_input(
audio=types.Blob(data=audio_bytes, mime_type="audio/pcm;rate=16000")
)
# if stream gets paused, send:
# await session.send_realtime_input(audio_stream_end=True)
async for response in session.receive():
if response.text is not None:
print(response.text)
if __name__ == "__main__":
asyncio.run(main())
send_realtime_input을 사용하면 API가 VAD에 따라 오디오에 자동으로 응답해요. send_client_content가 모델 컨텍스트에 메시지를 순서대로 추가하는 반면, send_realtime_input은 결정적 순서를 희생해 응답성에 최적화되어 있어요.
자동 VAD 구성
VAD 활동에 대한 더 많은 제어를 위해 다음 매개변수를 구성할 수 있어요. 자세한 내용은 API 참조를 참조하세요.
from google.genai import types
config = {
"response_modalities": ["AUDIO"],
"realtime_input_config": {
"automatic_activity_detection": {
"disabled": False, # default
"start_of_speech_sensitivity": types.StartSensitivity.START_SENSITIVITY_LOW,
"end_of_speech_sensitivity": types.EndSensitivity.END_SENSITIVITY_LOW,
"prefix_padding_ms": 20,
"silence_duration_ms": 100,
}
}
}
import { GoogleGenAI, Modality, StartSensitivity, EndSensitivity } from '@google/genai';
const config = {
responseModalities: [Modality.AUDIO],
realtimeInputConfig: {
automaticActivityDetection: {
disabled: false, // default
startOfSpeechSensitivity: StartSensitivity.START_SENSITIVITY_LOW,
endOfSpeechSensitivity: EndSensitivity.END_SENSITIVITY_LOW,
prefixPaddingMs: 20,
silenceDurationMs: 100,
}
}
};
하이브리드 VAD
하이브리드 VAD는 자동 VAD(견고한 음성 시작 감지)와 수동 VAD(저지연 응답 마무리)의 이점을 결합해요. 이 구성에서:
- 자동 VAD는 서버에서 계속 활성화돼요. 서버가 사용자 음성 시작을 자동 감지하고, 발화 시작 부분이 잘리지 않도록 접두사 패딩을 사용해요.
- 클라이언트는 클라이언트 측 VAD를 사용해 사용자가 말을 멈춘 시점을 감지해요.
- 클라이언트 측 VAD가 발화 종료를 감지하면 서버에 audio_stream_end 신호를 보내요.
- 서버는
audio_stream_end신호를 즉시 마무리 프롬프트로 취급해 기본 서버 측 침묵 감지 지연을 건너뛰고 최소 지연 시간으로 트랜스크립트와 모델 응답을 반환해요. - 클라이언트 측 VAD가 트리거되지 않으면 서버 측 VAD가 발화 종료 감지의 폴백으로 작동해요.
클라이언트 측 VAD 임계값을 너무 공격적으로 설정하면 음성 잘림이 발생할 수 있음에 유의하세요. 그러나 이 접근 방식은 수동 VAD에서 발생할 수 있는 앞부분 잘림 문제를 방지해요.
# Set up with automatic VAD enabled (default)
config = {
"response_modalities": ["AUDIO"],
}
async with client.aio.live.connect(model=model, config=config) as session:
# Send audio data normally
await session.send_realtime_input(
audio=types.Blob(data=audio_bytes, mime_type="audio/pcm;rate=16000")
)
# When client-side VAD detects the end of speech, send:
await session.send_realtime_input(audio_stream_end=True)
// Set up with automatic VAD enabled (default)
const config = {
responseModalities: [Modality.AUDIO],
};
// Send audio data normally
session.sendRealtimeInput({
audio: {
data: base64Audio,
mimeType: "audio/pcm;rate=16000"
}
});
// When client-side VAD detects the end of speech, send:
session.sendRealtimeInput({ audioStreamEnd: true });
자동 VAD 비활성화
또는 setup 메시지에서 realtimeInputConfig.automaticActivityDetection.disabled를 true로 설정해 자동 VAD를 비활성화할 수 있어요. 이 구성에서는 클라이언트가 사용자 음성을 감지하고 적절한 시점에 activityStart와 activityEnd 메시지를 보낼 책임이 있어요. 이 구성에서는 audioStreamEnd가 보내지지 않아요. 대신 스트림의 모든 중단은 activityEnd 메시지로 표시돼요.
config = {
"response_modalities": ["AUDIO"],
"realtime_input_config": {"automatic_activity_detection": {"disabled": True}},
}
async with client.aio.live.connect(model=model, config=config) as session:
# ...
await session.send_realtime_input(activity_start=types.ActivityStart())
await session.send_realtime_input(
audio=types.Blob(data=audio_bytes, mime_type="audio/pcm;rate=16000")
)
await session.send_realtime_input(activity_end=types.ActivityEnd())
# ...
const config = {
responseModalities: [Modality.AUDIO],
realtimeInputConfig: {
automaticActivityDetection: {
disabled: true,
}
}
};
session.sendRealtimeInput({ activityStart: {} })
session.sendRealtimeInput(
{
audio: {
data: base64Audio,
mimeType: "audio/pcm;rate=16000"
}
}
);
session.sendRealtimeInput({ activityEnd: {} })
VAD 매개변수와 품질에 대한 영향 이해
자동 VAD를 사용할 때 두 가지 핵심 매개변수는 모델에 보내기 전에 오디오가 음성 턴으로 분할되는 방식을 제어해요.
- prefixPaddingMs: 음성이 감지되기 전에 포함할 오디오 양. 이 "look-back"은 모델이 VAD가 트리거되기 전에 시작될 수 있는 첫 음절을 포함한 말의 전체 시작을 포착하도록 보장해요.
0값은 단어의 시작이 잘릴 수 있어요. - silenceDurationMs: 서버가 음성 턴을 끝내기 전에 침묵을 통해 기다리는 시간. 이는 시스템이 자연스러운 문장 중간 일시 정지(예: 생각, 호흡, 절 경계)에 얼마나 관대한지 결정해요.
silenceDurationMs가 오디오 품질에 미치는 영향
silenceDurationMs 값은 모델이 처리에 받는 오디오 청크의 크기와 완전성에 직접 영향을 줘요.
- 권장(500ms–800ms): 좋은 균형을 제공해요 — 모델은 지연 시간을 합리적으로 유지하면서 완전하고 컨텍스트가 풍부한 오디오 청크를 받아요. 서버의 내부 기본값은 약 800ms예요.
- 너무 낮음(예: 100ms–200ms): 시스템이 자연스러운 일시 정지 중에 음성 턴을 끝내 단일 발화를 여러 개의 작은 오디오 조각으로 나눠요. 모델은 이 조각들을 개별적으로 받아 조각 간 컨텍스트를 잃고 전사 및 응답 품질이 저하돼요.
- 너무 높음(예: 2000ms+): 시스템이 사용자가 말을 멈춘 후 오래 기다려 모델이 응답하기 전의 체감 지연 시간이 늘어나요.
수동(클라이언트 측) VAD 모범 사례
자동 VAD를 비활성화하고 자체 클라이언트 측 음성 감지에서 activityStart/activityEnd 신호를 관리할 때, 서버의 내장 오디오 버퍼링 메커니즘이 우회된다는 점에 유의하세요. 이는 다음을 의미해요.
- 말 전 버퍼 없음: 서버는 더 이상 감지된 음성 시작 전에 오디오를 추가하지 않아요. 클라이언트는
activityStart를 보내기 전에 충분한 오디오 컨텍스트를 포함해야 해요. - 침묵 허용 없음: 서버는 추가 대기 없이
activityEnd신호에 즉시 작동해요. 클라이언트 측 VAD가 공격적인 말 종료 임계값(예: 200ms 침묵)을 사용하면 자연스러운 일시 정지 중에 말이 문장 중간에서 잘릴 수 있어요.
수동 VAD로 오디오 품질을 유지하려면 클라이언트의 음성 활동 감지기에서 말 종료 침묵 임계값을 최소 500ms로 사용하세요. 이 값 미만의 임계값은 종종 전사 및 모델 응답 품질을 저하시키는 잘린 오디오를 유발해요.
토큰 수
반환된 서버 메시지의 usageMetadata 필드에서 소비된 총 토큰 수를 찾을 수 있어요.
async for message in session.receive():
# The server will periodically send messages that include UsageMetadata.
if message.usage_metadata:
usage = message.usage_metadata
print(
f"Used {usage.total_token_count} tokens in total. Response token breakdown:"
)
for detail in usage.response_tokens_details:
match detail:
case types.ModalityTokenCount(modality=modality, token_count=count):
print(f"{modality}: {count}")
const turns = await handleTurn();
for (const turn of turns) {
if (turn.usageMetadata) {
console.debug('Used %s tokens in total. Response token breakdown:\n', turn.usageMetadata.totalTokenCount);
for (const detail of turn.usageMetadata.responseTokensDetails) {
console.debug('%s\n', detail);
}
}
}
미디어 해상도
세션 구성의 일부로 mediaResolution 필드를 설정해 입력 미디어의 미디어 해상도를 지정할 수 있어요.
from google.genai import types
config = {
"response_modalities": ["AUDIO"],
"media_resolution": types.MediaResolution.MEDIA_RESOLUTION_LOW,
}
import { GoogleGenAI, Modality, MediaResolution } from '@google/genai';
const config = {
responseModalities: [Modality.AUDIO],
mediaResolution: MediaResolution.MEDIA_RESOLUTION_LOW,
};
오디오, 비디오 또는 이미지 입력을 포함하는 멀티모달 세션에 대해 mediaResolution을 구성할 수 있어요. mediaResolution은 시각 입력에 대한 프레임당 토큰 할당을 조정하지만, 오디오 스트림은 모든 해상도 설정에서 초당 고정 비율로 토큰화돼요. 자세한 내용은 미디어 해상도 가이드를 참조하세요.
제한 사항
프로젝트를 계획할 때 Live API의 다음 제한 사항을 고려하세요.
응답 모달리티
네이티브 오디오 모델은 AUDIO 응답 모달리티만 지원해요. 모델 응답을 텍스트로 필요하다면 출력 오디오 전사 기능을 사용하세요.
클라이언트 인증
Live API는 기본적으로 서버-서버 인증만 제공해요. 클라이언트-서버 접근 방식으로 Live API 애플리케이션을 구현하는 경우 임시 토큰을 사용해 보안 위험을 완화해야 해요.
세션 길이
오디오 전용 세션은 15분으로, 오디오+비디오 세션은 2분으로 제한돼요. 그러나 세션 길이를 무한 확장하는 다양한 세션 관리 기법을 구성할 수 있어요.
컨텍스트 창
세션의 컨텍스트 창 한도는 다음과 같아요.
- 네이티브 오디오 출력 모델의 경우 128k 토큰
- 다른 Live API 모델의 경우 32k 토큰
지원 언어
Live API는 다음 99개 언어를 지원해요.
| 언어 | BCP-47 코드 | 언어 | BCP-47 코드 |
|---|---|---|---|
| 아프리칸스어 | af | 라트비아어 | lv |
| 아칸어 | ak | 리투아니아어 | lt |
| 알바니아어 | sq | 마케도니아어 | mk |
| 암하라어 | am | 말레이어 | ms |
| 아랍어 | ar | 말라얄람어 | ml |
| 아르메니아어 | hy | 몰타어 | mt |
| 아삼어 | as | 마오리어 | mi |
| 아제르바이잔어 | az | 마라티어 | mr |
| 바스크어 | eu | 몽골어 | mn |
| 벨라루스어 | be | 네팔어 | ne |
| 벵골어 | bn | 노르웨이어 | no, nb |
| 보스니아어 | bs | 오디아어 | or |
| 불가리아어 | bg | 오로모어 | om |
| 버마어 | my | 파슈토어 | ps |
| 카탈루냐어 | ca | 페르시아어 | fa |
| 세부아노어 | ceb | 폴란드어 | pl |
| 중국어(간체) | zh-Hans | 포르투갈어(브라질) | pt-BR |
| 중국어(번체) | zh-Hant | 포르투갈어(포르투갈) | pt-PT |
| 크로아티아어 | hr | 펀자브어 | pa |
| 체코어 | cs | 케추아어 | qu |
| 덴마크어 | da | 루마니아어 | ro |
| 네덜란드어 | nl | 로만슈어 | rm |
| 영어 | en | 러시아어 | ru |
| 에스토니아어 | et | 세르비아어 | sr |
| 페로어 | fo | 신디어 | sd |
| 필리핀어 | fil | 신할라어 | si |
| 핀란드어 | fi | 슬로바키아어 | sk |
| 프랑스어 | fr | 슬로베니아어 | sl |
| 갈리시아어 | gl | 소말리어 | so |
| 조지아어 | ka | 남소토어 | st |
| 독일어 | de | 스페인어 | es |
| 그리스어 | el | 스와힐리어 | sw |
| 구자라트어 | gu | 스웨덴어 | sv |
| 하우사어 | ha | 타지크어 | tg |
| 히브리어 | he | 타밀어 | ta |
| 힌디어 | hi | 텔루구어 | te |
| 헝가리어 | hu | 태국어 | th |
| 아이슬란드어 | is | 츠와나어 | tn |
| 인도네시아어 | id | 터키어 | tr |
| 아일랜드어 | ga | 투르크멘어 | tk |
| 이탈리아어 | it | 우크라이나어 | uk |
| 일본어 | ja | 우르두어 | ur |
| 칸나다어 | kn | 우즈베크어 | uz |
| 카자흐어 | kk | 베트남어 | vi |
| 크메르어 | km | 웨일스어 | cy |
| 키냐르완다어 | rw | 서프리지아어 | fy |
| 한국어 | ko | 월로프어 | wo |
| 쿠르드어 | ku | 요루바어 | yo |
| 키르기스어 | ky | 줄루어 | zu |
| 라오어 | lo |
다음 단계
- Live API를 효과적으로 사용하기 위한 필수 정보는 도구 사용 및 세션 관리 가이드를 읽으세요.
- Google AI Studio에서 Live API를 시도하세요.
- Live API 모델에 대한 자세한 내용은 Gemini 3.8 Live 및 Gemini 3.8 Live Extended Thinking 모델 페이지를 참조하세요.
- Live API cookbook, Live API Tools cookbook, Live API Get Started script에서 더 많은 예시를 시도해 보세요.