Live API

Live API memungkinkan interaksi suara dan video dua arah dengan latensi rendah dengan Gemini, sehingga Anda dapat berbicara dengan Gemini secara live sekaligus melakukan streaming input video atau berbagi layar. Dengan menggunakan Live API, Anda dapat memberikan pengalaman percakapan suara alami layaknya manusia kepada pengguna akhir.

Anda dapat mencoba Live API di Google AI Studio. Untuk menggunakan Live API di Google AI Studio, pilih Stream.

Cara kerja Live API

Streaming

Live API menggunakan model streaming melalui koneksi WebSocket. Saat Anda berinteraksi dengan API, koneksi persisten akan dibuat. Input Anda (audio, video, atau teks) di-streaming secara terus-menerus ke model, dan respons model (teks atau audio) di-streaming kembali secara real-time melalui koneksi yang sama.

Streaming dua arah ini memastikan latensi rendah dan mendukung fitur seperti deteksi aktivitas suara, penggunaan alat, dan pembuatan ucapan.

Ringkasan Live API

Untuk informasi selengkapnya tentang WebSockets API yang mendasarinya, lihat Referensi WebSockets API.

Pembuatan output

Live API memproses input multimodal (teks, audio, video) untuk menghasilkan teks atau audio secara real-time. Model ini dilengkapi dengan mekanisme bawaan untuk membuat audio dan bergantung pada versi model yang Anda gunakan, model ini menggunakan salah satu dari dua metode pembuatan audio:

  • Half cascade: Model menerima input audio native dan menggunakan cascade model khusus dari model yang berbeda untuk memproses input dan menghasilkan output audio.
  • Native: Gemini 2.5 memperkenalkan pembuatan audio native, yang langsung menghasilkan output audio, memberikan audio yang terdengar lebih alami, suara yang lebih ekspresif, lebih banyak kesadaran terhadap konteks tambahan, misalnya, nada, dan respons yang lebih proaktif.

Membangun dengan Live API

Sebelum Anda mulai mem-build dengan Live API, pilih pendekatan pembuatan audio yang paling sesuai dengan kebutuhan Anda.

Membuat koneksi

Contoh berikut menunjukkan cara membuat koneksi dengan kunci API:

import asyncio
from google import genai

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

model = "gemini-2.0-flash-live-001"
config = {"response_modalities": ["TEXT"]}

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

if __name__ == "__main__":
    asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';
const config = { responseModalities: [Modality.TEXT] };

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,
    });

    // Send content...

    session.close();
}

main();

Mengirim dan menerima teks

Berikut cara mengirim dan menerima teks:

import asyncio
from google import genai

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

config = {"response_modalities": ["TEXT"]}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        message = "Hello, how are you?"
        await session.send_client_content(
            turns={"role": "user", "parts": [{"text": message}]}, turn_complete=True
        )

        async for response in session.receive():
            if response.text is not None:
                print(response.text, end="")

if __name__ == "__main__":
    asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';
const config = { responseModalities: [Modality.TEXT] };

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.text) {
            console.debug('Received text: %s\n', turn.text);
        }
        else if (turn.data) {
            console.debug('Received inline data: %s\n', turn.data);
        }
    }

    session.close();
}

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

main();

Mengirim dan menerima audio

Anda dapat mengirim audio dengan mengonversinya ke format PCM 16-bit, 16 kHz, mono. Contoh ini membaca file WAV dan mengirimkannya dalam format yang benar:

# 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
from google import genai
from google.genai import types
import soundfile as sf
import librosa

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

config = {"response_modalities": ["TEXT"]}

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")
        )

        async for response in session.receive():
            if response.text is not None:
                print(response.text)

if __name__ == "__main__":
    asyncio.run(main())
// Test file: https://storage.googleapis.com/generativeai-downloads/data/16000.wav
// Install helpers for converting files: npm install wavefile
import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';
const { WaveFile } = pkg;

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';
const config = { responseModalities: [Modality.TEXT] };

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();
    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);
        }
    }

    session.close();
}

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

main();

Anda dapat menerima audio dengan menetapkan AUDIO sebagai modalitas respons. Contoh ini menyimpan data yang diterima sebagai file WAV:

import asyncio
import wave
from google import genai

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

config = {"response_modalities": ["AUDIO"]}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        wf = wave.open("audio.wav", "wb")
        wf.setnchannels(1)
        wf.setsampwidth(2)
        wf.setframerate(24000)

        message = "Hello how are you?"
        await session.send_client_content(
            turns={"role": "user", "parts": [{"text": message}]}, turn_complete=True
        )

        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())
import { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";
import pkg from 'wavefile';
const { WaveFile } = pkg;

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';
const config = { responseModalities: [Modality.AUDIO] };

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();

    // 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);
    fs.writeFileSync('output.wav', wf.toBuffer());

    session.close();
}

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

main();

Format audio

Data audio di Live API selalu berupa PCM 16-bit mentah, little-endian. Output audio selalu menggunakan frekuensi sampling 24 kHz. Audio input adalah 16 kHz secara native, tetapi Live API akan mengambil sampel ulang jika diperlukan sehingga frekuensi sampel apa pun dapat dikirim. Untuk menyampaikan frekuensi sampel audio input, tetapkan jenis MIME dari setiap Blob yang berisi audio ke nilai seperti audio/pcm;rate=16000.

Menerima transkripsi audio

Anda dapat mengaktifkan transkripsi output audio model dengan mengirim output_audio_transcription dalam konfigurasi penyiapan. Bahasa transkripsi diinferensi dari respons model.

import asyncio
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

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({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';

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();

Anda dapat mengaktifkan transkripsi input audio dengan mengirimkan input_audio_transcription dalam konfigurasi penyiapan.

import asyncio
from pathlib import Path
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

config = {
    "response_modalities": ["TEXT"],
    "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({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';

const config = {
    responseModalities: [Modality.TEXT],
    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.serverContent && turn.serverContent.outputTranscription) {
        console.log("Transcription")
        console.log(turn.serverContent.outputTranscription.text);
        }
    }
    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();

Streaming audio dan video

Petunjuk sistem

Petunjuk sistem memungkinkan Anda mengarahkan perilaku model berdasarkan kebutuhan dan kasus penggunaan tertentu. Petunjuk sistem dapat ditetapkan dalam konfigurasi penyiapan dan akan tetap berlaku selama seluruh sesi.

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

Update konten inkremental

Gunakan update inkremental untuk mengirim input teks, menetapkan konteks sesi, atau memulihkan konteks sesi. Untuk konteks singkat, Anda dapat mengirim interaksi per belokan untuk mewakili urutan peristiwa yang tepat:

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 })

Untuk konteks yang lebih panjang, sebaiknya berikan satu ringkasan pesan untuk mengosongkan jendela konteks untuk interaksi berikutnya.

Mengubah suara dan bahasa

Live API mendukung suara berikut: Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, dan Zephyr.

Untuk menentukan suara, tetapkan nama suara dalam objek speechConfig sebagai bagian dari konfigurasi sesi:

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 mendukung beberapa bahasa.

Untuk mengubah bahasa, tetapkan kode bahasa dalam objek speechConfig sebagai bagian dari konfigurasi sesi:

config = {
    "response_modalities": ["AUDIO"],
    "speech_config": {
        "language_code": "de-DE"
    }
}
const config = {
  responseModalities: [Modality.AUDIO],
  speechConfig: { languageCode: "de-DE" }
};

Output audio native

Melalui Live API, Anda juga dapat mengakses model yang memungkinkan output audio native selain input audio native. Hal ini memungkinkan output audio berkualitas lebih tinggi dengan kecepatan, kealamian suara, kepanjangan, dan suasana hati yang lebih baik.

Output audio native didukung oleh model audio native berikut:

  • gemini-2.5-flash-preview-native-audio-dialog
  • gemini-2.5-flash-exp-native-audio-thinking-dialog

Cara menggunakan output audio native

Untuk menggunakan output audio native, konfigurasikan salah satu model audio native dan tetapkan response_modalities ke AUDIO.

Lihat Mengirim dan menerima audio untuk contoh lengkap.

model = "gemini-2.5-flash-preview-native-audio-dialog"
config = types.LiveConnectConfig(response_modalities=["AUDIO"])

async with client.aio.live.connect(model=model, config=config) as session:
    # Send audio input and receive audio
const model = 'gemini-2.5-flash-preview-native-audio-dialog';
const config = { responseModalities: [Modality.AUDIO] };

async function main() {

    const session = await ai.live.connect({
        model: model,
        config: config,
        callbacks: ...,
    });

    // Send audio input and receive audio

    session.close();
}

main();

Dialog afektif

Fitur ini memungkinkan Gemini menyesuaikan gaya responsnya dengan ekspresi dan nada input.

Untuk menggunakan dialog afektif, tetapkan versi API ke v1alpha dan tetapkan enable_affective_dialog ke true dalam pesan penyiapan:

client = genai.Client(api_key="GOOGLE_API_KEY", http_options={"api_version": "v1alpha"})

config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],
    enable_affective_dialog=True
)
const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY", httpOptions: {"apiVersion": "v1alpha"} });

const config = {
    responseModalities: [Modality.AUDIO],
    enableAffectiveDialog: true
};

Perhatikan bahwa dialog afektif saat ini hanya didukung oleh model output audio native.

Audio proaktif

Jika fitur ini diaktifkan, Gemini dapat secara proaktif memutuskan untuk tidak merespons jika konten tidak relevan.

Untuk menggunakannya, tetapkan versi API ke v1alpha dan konfigurasikan kolom proactivity dalam pesan penyiapan, lalu tetapkan proactive_audio ke true:

client = genai.Client(api_key="GOOGLE_API_KEY", http_options={"api_version": "v1alpha"})

config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],
    proactivity={'proactive_audio': True}
)
const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY", httpOptions: {"apiVersion": "v1alpha"} });

const config = {
    responseModalities: [Modality.AUDIO],
    proactivity: { proactiveAudio: true }
}

Perhatikan bahwa audio proaktif saat ini hanya didukung oleh model output audio native.

Output audio native dengan pemikiran

Output audio native mendukung kemampuan berpikir, yang tersedia melalui model terpisah gemini-2.5-flash-exp-native-audio-thinking-dialog.

Lihat Mengirim dan menerima audio untuk contoh lengkap.

model = "gemini-2.5-flash-exp-native-audio-thinking-dialog"
config = types.LiveConnectConfig(response_modalities=["AUDIO"])

async with client.aio.live.connect(model=model, config=config) as session:
    # Send audio input and receive audio
const model = 'gemini-2.5-flash-exp-native-audio-thinking-dialog';
const config = { responseModalities: [Modality.AUDIO] };

async function main() {

    const session = await ai.live.connect({
        model: model,
        config: config,
        callbacks: ...,
    });

    // Send audio input and receive audio

    session.close();
}

main();

Penggunaan alat dengan Live API

Anda dapat menentukan alat seperti Panggilan fungsi, Eksekusi kode, dan Google Penelusuran dengan Live API.

Ringkasan alat yang didukung

Berikut adalah ringkasan singkat tentang alat yang tersedia untuk setiap model:

Alat Model bersusun
gemini-2.0-flash-live-001
gemini-2.5-flash-preview-native-audio-dialog gemini-2.5-flash-exp-native-audio-thinking-dialog
Penelusuran Ya Ya Ya
Panggilan fungsi Ya Ya Tidak
Eksekusi kode Ya Tidak Tidak
Konteks URL Ya Tidak Tidak

Panggilan fungsi

Anda dapat menentukan deklarasi fungsi sebagai bagian dari konfigurasi sesi. Lihat Tutorial panggilan fungsi untuk mempelajari lebih lanjut.

Setelah menerima panggilan alat, klien harus merespons dengan daftar objek FunctionResponse menggunakan metode session.send_tool_response.

import asyncio
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

# Simple function definitions
turn_on_the_lights = {"name": "turn_on_the_lights"}
turn_off_the_lights = {"name": "turn_off_the_lights"}

tools = [{"function_declarations": [turn_on_the_lights, turn_off_the_lights]}]
config = {"response_modalities": ["TEXT"], "tools": tools}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        prompt = "Turn on the lights please"
        await session.send_client_content(turns={"parts": [{"text": prompt}]})

        async for chunk in session.receive():
            if chunk.server_content:
                if chunk.text is not None:
                    print(chunk.text)
            elif chunk.tool_call:
                function_responses = []
                for fc in tool_call.function_calls:
                    function_response = types.FunctionResponse(
                        id=fc.id,
                        name=fc.name,
                        response={ "result": "ok" } # simple, hard-coded function response
                    )
                    function_responses.append(function_response)

                await session.send_tool_response(function_responses=function_responses)


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

Dari satu perintah, model dapat menghasilkan beberapa panggilan fungsi dan kode yang diperlukan untuk merantai outputnya. Kode ini dieksekusi di lingkungan sandbox, yang menghasilkan pesan BidiGenerateContentToolCall berikutnya.

Panggilan fungsi asinkron

Secara default, eksekusi dijeda hingga hasil setiap panggilan fungsi tersedia, yang memastikan pemrosesan berurutan. Artinya, Anda tidak akan dapat terus berinteraksi dengan model saat fungsi dijalankan.

Jika tidak ingin memblokir percakapan, Anda dapat memberi tahu model untuk menjalankan fungsi secara asinkron.

Untuk melakukannya, Anda harus menambahkan behavior ke definisi fungsi terlebih dahulu:

  # Non-blocking function definitions
  turn_on_the_lights = {"name": "turn_on_the_lights", "behavior": "NON_BLOCKING"} # turn_on_the_lights will run asynchronously
  turn_off_the_lights = {"name": "turn_off_the_lights"} # turn_off_the_lights will still pause all interactions with the model

NON-BLOCKING akan memastikan fungsi berjalan secara asinkron saat Anda dapat terus berinteraksi dengan model.

Kemudian, Anda perlu memberi tahu model cara berperilaku saat menerima FunctionResponse menggunakan parameter scheduling. Hal ini dapat:

  • Mengganggu aktivitasnya dan langsung memberi tahu Anda tentang respons yang didapatnya (scheduling="INTERRUPT"),
  • Tunggu hingga selesai melakukan tindakan yang sedang dilakukan (scheduling="WHEN_IDLE"),
  • Atau tidak melakukan apa pun dan menggunakan pengetahuan tersebut nanti dalam diskusi (scheduling="SILENT")
# Non-blocking function definitions
  function_response = types.FunctionResponse(
      id=fc.id,
      name=fc.name,
      response={
          "result": "ok",
          "scheduling": "INTERRUPT" # Can also be WHEN_IDLE or SILENT
      }
  )

Eksekusi kode

Anda dapat menentukan eksekusi kode sebagai bagian dari konfigurasi sesi. Lihat Tutorial eksekusi kode untuk mempelajari lebih lanjut.

import asyncio
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

tools = [{'code_execution': {}}]
config = {"response_modalities": ["TEXT"], "tools": tools}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        prompt = "Compute the largest prime palindrome under 100000."
        await session.send_client_content(turns={"parts": [{"text": prompt}]})

        async for chunk in session.receive():
            if chunk.server_content:
                if chunk.text is not None:
                    print(chunk.text)
            
                model_turn = chunk.server_content.model_turn
                if model_turn:
                    for part in model_turn.parts:
                      if part.executable_code is not None:
                        print(part.executable_code.code)

                      if part.code_execution_result is not None:
                        print(part.code_execution_result.output)

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

Anda dapat mengaktifkan Grounding dengan Google Penelusuran sebagai bagian dari konfigurasi sesi. Lihat Tutorial pentanahan untuk mempelajari lebih lanjut.

import asyncio
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

tools = [{'google_search': {}}]
config = {"response_modalities": ["TEXT"], "tools": tools}

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        prompt = "When did the last Brazil vs. Argentina soccer match happen?"
        await session.send_client_content(turns={"parts": [{"text": prompt}]})

        async for chunk in session.receive():
            if chunk.server_content:
                if chunk.text is not None:
                    print(chunk.text)

                # The model might generate and execute Python code to use Search
                model_turn = chunk.server_content.model_turn
                if model_turn:
                    for part in model_turn.parts:
                      if part.executable_code is not None:
                        print(part.executable_code.code)

                      if part.code_execution_result is not None:
                        print(part.code_execution_result.output)

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

Menggabungkan beberapa alat

Anda dapat menggabungkan beberapa alat dalam Live API:

prompt = """
Hey, I need you to do three things for me.

1. Compute the largest prime palindrome under 100000.
2. Then use Google Search to look up information about the largest earthquake in California the week of Dec 5 2024?
3. Turn on the lights

Thanks!
"""

tools = [
    {"google_search": {}},
    {"code_execution": {}},
    {"function_declarations": [turn_on_the_lights, turn_off_the_lights]},
]

config = {"response_modalities": ["TEXT"], "tools": tools}

Menangani gangguan

Pengguna dapat mengganggu output model kapan saja. Saat Deteksi aktivitas suara (VAD) mendeteksi gangguan, pembuatan yang sedang berlangsung akan dibatalkan dan dihapus. Hanya informasi yang telah dikirim ke klien yang dipertahankan dalam histori sesi. Server kemudian mengirimkan pesan BidiGenerateContentServerContent untuk melaporkan gangguan.

Selain itu, server Gemini akan menghapus panggilan fungsi yang tertunda dan mengirim pesan BidiGenerateContentServerContent dengan ID panggilan yang dibatalkan.

async for response in session.receive():
    if response.server_content.interrupted is True:
        # The generation was interrupted
const turns = await handleTurn();

for (const turn of turns) {
  if (turn.serverContent && turn.serverContent.interrupted) {
    // The generation was interrupted
  }
}

Deteksi aktivitas suara (VAD)

Anda dapat mengonfigurasi atau menonaktifkan deteksi aktivitas suara (VAD).

Menggunakan VAD otomatis

Secara default, model akan otomatis melakukan VAD pada streaming input audio yang berkelanjutan. VAD dapat dikonfigurasi dengan kolom realtimeInputConfig.automaticActivityDetection dari konfigurasi penyiapan.

Saat streaming audio dijeda selama lebih dari satu detik (misalnya, karena pengguna menonaktifkan mikrofon), peristiwa audioStreamEnd harus dikirim untuk menghapus audio yang di-cache. Klien dapat melanjutkan pengiriman data audio kapan saja.

# 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(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

config = {"response_modalities": ["TEXT"]}

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())
// 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 { GoogleGenAI, Modality } from '@google/genai';
import * as fs from "node:fs";

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';
const config = { responseModalities: [Modality.TEXT] };

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.pcm");
  const base64Audio = Buffer.from(fileBuffer).toString('base64');

  session.sendRealtimeInput(
    {
      audio: {
        data: base64Audio,
        mimeType: "audio/pcm;rate=16000"
      }
    }

  );

  // if stream gets paused, send:
  // session.sendRealtimeInput({ audioStreamEnd: true })

  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);
    }
  }

  session.close();
}

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

main();

Dengan send_realtime_input, API akan merespons audio secara otomatis berdasarkan VAD. Meskipun send_client_content menambahkan pesan ke konteks model secara berurutan, send_realtime_input dioptimalkan untuk responsivitas dengan mengorbankan urutan deterministik.

Mengonfigurasi VAD otomatis

Untuk kontrol yang lebih besar atas aktivitas VAD, Anda dapat mengonfigurasi parameter berikut. Lihat referensi API untuk mengetahui info selengkapnya.

from google.genai import types

config = {
    "response_modalities": ["TEXT"],
    "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.TEXT],
  realtimeInputConfig: {
    automaticActivityDetection: {
      disabled: false, // default
      startOfSpeechSensitivity: StartSensitivity.START_SENSITIVITY_LOW,
      endOfSpeechSensitivity: EndSensitivity.END_SENSITIVITY_LOW,
      prefixPaddingMs: 20,
      silenceDurationMs: 100,
    }
  }
};

Menonaktifkan VAD otomatis

Atau, VAD otomatis dapat dinonaktifkan dengan menetapkan realtimeInputConfig.automaticActivityDetection.disabled ke true dalam pesan penyiapan. Dalam konfigurasi ini, klien bertanggung jawab untuk mendeteksi ucapan pengguna dan mengirim pesan activityStart dan activityEnd pada waktu yang tepat. audioStreamEnd tidak dikirim dalam konfigurasi ini. Sebagai gantinya, gangguan streaming apa pun ditandai dengan pesan activityEnd.

config = {
    "response_modalities": ["TEXT"],
    "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.TEXT],
  realtimeInputConfig: {
    automaticActivityDetection: {
      disabled: true,
    }
  }
};

session.sendRealtimeInput({ activityStart: {} })

session.sendRealtimeInput(
  {
    audio: {
      data: base64Audio,
      mimeType: "audio/pcm;rate=16000"
    }
  }

);

session.sendRealtimeInput({ activityEnd: {} })

Jumlah token

Anda dapat menemukan jumlah total token yang digunakan di kolom usageMetadata dari pesan server yang ditampilkan.

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);
    }
  }
}

Memperpanjang durasi sesi

Durasi sesi maksimum dapat diperpanjang menjadi tanpa batas dengan dua mekanisme:

Selain itu, Anda akan menerima pesan GoAway sebelum sesi berakhir, sehingga Anda dapat mengambil tindakan lebih lanjut.

Kompresi jendela konteks

Untuk mengaktifkan sesi yang lebih lama, dan menghindari penghentian koneksi secara tiba-tiba, Anda dapat mengaktifkan kompresi jendela konteks dengan menetapkan kolom contextWindowCompression sebagai bagian dari konfigurasi sesi.

Di ContextWindowCompressionConfig, Anda dapat mengonfigurasi mekanisme jendela geser dan jumlah token yang memicu kompresi.

from google.genai import types

config = {
    "response_modalities": ["AUDIO"],
    "context_window_compression": (
        # Configures compression with default parameters.
        types.ContextWindowCompressionConfig(
            sliding_window=types.SlidingWindow(),
        )
    ),
}
const config = {
  responseModalities: [Modality.AUDIO],
  contextWindowCompression: { slidingWindow: {} }
};

Melanjutkan sesi

Untuk mencegah penghentian sesi saat server mereset koneksi WebSocket secara berkala, konfigurasikan kolom sessionResumption dalam konfigurasi penyiapan.

Meneruskan konfigurasi ini akan menyebabkan server mengirim pesan SessionResumptionUpdate, yang dapat digunakan untuk melanjutkan sesi dengan meneruskan token lanjutan terakhir sebagai SessionResumptionConfig.handle koneksi berikutnya.

import asyncio
from google import genai
from google.genai import types

client = genai.Client(api_key="GEMINI_API_KEY")
model = "gemini-2.0-flash-live-001"

async def main():
    print(f"Connecting to the service with handle {previous_session_handle}...")
    async with client.aio.live.connect(
        model=model,
        config=types.LiveConnectConfig(
            response_modalities=["AUDIO"],
            session_resumption=types.SessionResumptionConfig(
                # The handle of the session to resume is passed here,
                # or else None to start a new session.
                handle=previous_session_handle
            ),
        ),
    ) as session:
        while True:
            await session.send_client_content(
                turns=types.Content(
                    role="user", parts=[types.Part(text="Hello world!")]
                )
            )
            async for message in session.receive():
                if message.session_resumption_update:
                    update = message.session_resumption_update
                    if update.resumable and update.new_handle:
                        newHandle = update.new_handle
                        # TODO: store newHandle and start new session with this handle
                        # ...

if __name__ == "__main__":
    asyncio.run(main())
import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({ apiKey: "GOOGLE_API_KEY" });
const model = 'gemini-2.0-flash-live-001';

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;
    }

    console.debug('Connecting to the service with handle %s...', previousSessionHandle)
    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: { 
          responseModalities: [Modality.TEXT],
          sessionResumption: { handle: previousSessionHandle }
          // The handle of the session to resume is passed here, or else null to start a new session.
        }
    });

    const inputTurns = 'Hello how are you?';
    session.sendClientContent({ turns: inputTurns });

    const turns = await handleTurn();
    for (const turn of turns) {
        if (turn.sessionResumptionUpdate) {
            if (turn.sessionResumptionUpdate.resumable && turn.sessionResumptionUpdate.newHandle) {
              let newHandle = turn.sessionResumptionUpdate.newHandle
              // TODO: store newHandle and start new session with this handle
              // ...
            }
        }
    }

    session.close();
}

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

main();

Menerima pesan sebelum sesi terputus

Server mengirim pesan GoAway yang menandakan bahwa koneksi saat ini akan segera dihentikan. Pesan ini menyertakan timeLeft, yang menunjukkan waktu yang tersisa dan memungkinkan Anda mengambil tindakan lebih lanjut sebelum koneksi dihentikan sebagai ABORTED.

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)
const turns = await handleTurn();

for (const turn of turns) {
  if (turn.goAway) {
    console.debug('Time left: %s\n', turn.goAway.timeLeft);
  }
}

Menerima pesan saat pembuatan selesai

Server mengirimkan pesan generationComplete yang menandakan bahwa model telah selesai membuat respons.

async for response in session.receive():
    if response.server_content.generation_complete is True:
        # The generation is complete
const turns = await handleTurn();

for (const turn of turns) {
  if (turn.serverContent && turn.serverContent.generationComplete) {
    // The generation is complete
  }
}

Resolusi media

Anda dapat menentukan resolusi media untuk media input dengan menetapkan kolom mediaResolution sebagai bagian dari konfigurasi sesi:

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.TEXT],
    mediaResolution: MediaResolution.MEDIA_RESOLUTION_LOW,
};

Batasan

Pertimbangkan batasan Live API berikut saat Anda merencanakan project.

Modalitas respons

Anda hanya dapat menetapkan satu modalitas respons (TEXT atau AUDIO) per sesi dalam konfigurasi sesi. Menetapkan keduanya akan menghasilkan pesan error konfigurasi. Artinya, Anda dapat mengonfigurasi model untuk merespons dengan teks atau audio, tetapi tidak keduanya dalam sesi yang sama.

Autentikasi klien

Live API hanya menyediakan autentikasi server ke server dan tidak direkomendasikan untuk penggunaan klien langsung. Input klien harus dirutekan melalui server aplikasi perantara untuk autentikasi aman dengan Live API.

Durasi sesi

Durasi sesi dapat diperpanjang menjadi tidak terbatas dengan mengaktifkan kompresi sesi. Tanpa kompresi, sesi audio saja dibatasi hingga 15 menit, dan sesi audio plus video dibatasi hingga 2 menit. Jika batas ini terlampaui tanpa kompresi, koneksi akan dihentikan.

Selain itu, Anda dapat mengonfigurasi lanjutan sesi untuk memungkinkan klien melanjutkan sesi yang dihentikan.

Jendela konteks

Sesi memiliki batas periode konteks sebesar:

Bahasa yang didukung

Live API mendukung bahasa berikut.

Language Kode BCP-47
Jerman (Jerman) de-DE
Inggris (Australia) en-AU
Inggris (Inggris Raya) en-GB
Inggris (India) en-IN
Inggris (AS) en-US
Spanyol (Amerika Serikat) es-US
Prancis (Prancis) fr-FR
Hindi (India) hi-IN
Portugis (Brasil) pt-BR
Arab (Umum) ar-XA
Spanyol (Spanyol) es-ES
Prancis (Kanada) fr-CA
Indonesia (Indonesia) id-ID
Italia (Italia) it-IT
Jepang (Jepang) ja-JP
Turki (Turki) tr-TR
Vietnam (Vietnam) vi-VN
Bengali (India) bn-IN
Gujarati (India) gu-IN
Kannada (India) kn-IN
Malayalam (India) ml-IN
Marathi (India) mr-IN
Tamil (India) ta-IN
Telugu (India) te-IN
Belanda (Belanda) nl-NL
Korea (Korea Selatan) ko-KR
Mandarin (China) cmn-CN
Polandia (Polandia) pl-PL
Rusia (Rusia) ru-RU
Thai (Thailand) th-TH

Integrasi pihak ketiga

Untuk deployment aplikasi web dan seluler, Anda dapat menjelajahi opsi dari:

Langkah berikutnya