Get started with Live API

Live API を使用すると、Gemini との低レイテンシのリアルタイム音声と動画によるやり取りが可能になります。音声、動画、テキストの連続ストリーミングを処理して、人間のような即時音声レスポンスを提供することで、ユーザーに自然な会話エクスペリエンスを提供します。

Live API の概要

Live API には、音声アクティビティ検出ツールの使用と関数呼び出しセッション管理(長時間の会話を管理するため)、エフェメラル トークン(安全なクライアントサイド認証用)など、包括的な機能セットが用意されています。

このページでは、サンプルと基本的なコードサンプルを使用して、すぐに使い始める方法について説明します。

アプリケーションの例

エンドツーエンドのユースケースで Live API を使用する方法を示す次のサンプル アプリケーションをご覧ください。

パートナーとの統合

よりシンプルな開発プロセスを希望する場合は、Daily または LiveKit を使用できます。これらは、WebRTC プロトコル経由で Gemini Live API をすでに統合しており、リアルタイムの音声と動画のアプリケーションの開発を効率化しているサードパーティ パートナー プラットフォームです。

ビルドを開始する前に

Live API を使用してビルドを開始する前に、モデルの選択と実装アプローチの選択という 2 つの重要な決定を行う必要があります。

モデルを選択する

音声ベースのユースケースを構築する場合、選択したモデルによって、音声レスポンスを作成するために使用される音声生成アーキテクチャが決まります。

  • Gemini 2.5 Flash によるネイティブ音声: このオプションを使用すると、最も自然でリアルな音声を実現し、マルチリンガル パフォーマンスが向上します。また、感情(感情認識)に基づく会話プロアクティブな音声(モデルが特定の入力を無視するか、応答するかを決定できる)、「思考」などの高度な機能を実現します。ネイティブ音声は、次のネイティブ音声モデルでサポートされています。
    • gemini-2.5-flash-preview-native-audio-dialog
    • gemini-2.5-flash-exp-native-audio-thinking-dialog
  • Gemini 2.0 Flash を使用したハーフ カスケード音声: このオプションは gemini-2.0-flash-live-001 モデルで使用でき、カスケード モデル アーキテクチャ(ネイティブ音声入力とテキスト読み上げ出力)を使用します。本番環境では、特にツールの使用でパフォーマンスと信頼性が向上します。

実装方法を選択する

Live API と統合する場合は、次のいずれかの実装方法を選択する必要があります。

  • サーバー間: バックエンドは WebSockets を使用して Live API に接続します。通常、クライアントはストリーミング データ(音声、動画、テキスト)をサーバーに送信し、サーバーがそれを Live API に転送します。
  • クライアントからサーバー: フロントエンド コードは、WebSockets を使用して Live API に直接接続し、バックエンドをバイパスしてデータをストリーミングします。

始める

この例では、WAV ファイルを読み取り、適切な形式で送信し、受信したデータを WAV ファイルとして保存します。

音声を 16 ビット PCM、16 kHz、モノラル形式に変換して送信できます。音声を受信するには、AUDIO をレスポンス モダリティとして設定します。出力では 24 kHz のサンプリング レートが使用されます。

Python

# Test file: https://storage.googleapis.com/generativeai-downloads/data/16000.wav
# Install helpers for converting files: pip install librosa soundfile
import asyncio
import io
from pathlib import Path
import wave
from google import genai
from google.genai import types
import soundfile as sf
import librosa

client = genai.Client(api_key="GEMINI_API_KEY")

# Half cascade model:
# model = "gemini-2.0-flash-live-001"

# Native audio output model:
model = "gemini-2.5-flash-preview-native-audio-dialog"

config = {
  "response_modalities": ["AUDIO"],
  "system_instruction": "You are a helpful assistant and answer in a friendly tone.",
}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:

        buffer = io.BytesIO()
        y, sr = librosa.load("sample.wav", sr=16000)
        sf.write(buffer, y, sr, format='RAW', subtype='PCM_16')
        buffer.seek(0)
        audio_bytes = buffer.read()

        # If already in correct format, you can use this:
        # audio_bytes = Path("sample.pcm").read_bytes()

        await session.send_realtime_input(
            audio=types.Blob(data=audio_bytes, mime_type="audio/pcm;rate=16000")
        )

        wf = wave.open("audio.wav", "wb")
        wf.setnchannels(1)
        wf.setsampwidth(2)
        wf.setframerate(24000)  # Output is 24kHz

        async for response in session.receive():
            if response.data is not None:
                wf.writeframes(response.data)

            # Un-comment this code to print audio data info
            # if response.server_content.model_turn is not None:
            #      print(response.server_content.model_turn.parts[0].inline_data.mime_type)

        wf.close()

if __name__ == "__main__":
    asyncio.run(main())

JavaScript

// Test file: https://storage.googleapis.com/generativeai-downloads/data/16000.wav
import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';  // npm install wavefile
const { WaveFile } = pkg;

const ai = new GoogleGenAI({ apiKey: "GEMINI_API_KEY" });
// WARNING: Do not use API keys in client-side (browser based) applications
// Consider using Ephemeral Tokens instead
// More information at: https://ai.google.dev/gemini-api/docs/ephemeral-tokens

// Half cascade model:
// const model = "gemini-2.0-flash-live-001"

// Native audio output model:
const model = "gemini-2.5-flash-preview-native-audio-dialog"

const config = {
  responseModalities: [Modality.AUDIO], 
  systemInstruction: "You are a helpful assistant and answer in a friendly tone."
};

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("sample.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();

    // Combine audio data strings and save as wave file
    const combinedAudio = turns.reduce((acc, turn) => {
        if (turn.data) {
            const buffer = Buffer.from(turn.data, 'base64');
            const intArray = new Int16Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Int16Array.BYTES_PER_ELEMENT);
            return acc.concat(Array.from(intArray));
        }
        return acc;
    }, []);

    const audioBuffer = new Int16Array(combinedAudio);

    const wf = new WaveFile();
    wf.fromScratch(1, 24000, '16', audioBuffer);  // output is 24kHz
    fs.writeFileSync('audio.wav', wf.toBuffer());

    session.close();
}

async function main() {
    await live().catch((e) => console.error('got error', e));
}

main();

次のステップ