Transkripsi langsung dengan Gemini Live API

Gemini Live API mendukung transkripsi speech-to-text real-time dengan latensi rendah menggunakan model gemini-3.5-transcribe-live. Dengan terhubung ke Live API melalui WebSockets atau menggunakan Google Gen AI SDK, Anda dapat melakukan streaming input audio berkelanjutan dan menerima transkripsi teks inkremental secara real-time saat ucapan terjadi.

Dengan memanfaatkan Gemini Live API, platform developer seperti Agora, Fishjam, LiveKit, Pipecat, Vercel, dan Vision Agents memungkinkan developer membangun dan men-deploy antarmuka berbasis suara berperforma tinggi dengan mudah. Platform ini mengelola infrastruktur streaming media real-time yang kompleks di balik layar, sehingga developer dapat sepenuhnya berfokus pada pembuatan pengalaman pengguna.

Agen langsung versus Transkripsi langsung

Meskipun keduanya menggunakan koneksi streaming dua arah Live API, Transkripsi Instan beroperasi sebagai pipeline pengenalan ucapan khusus dengan latensi rendah, bukan sebagai agen percakapan.

Fitur Agen Langsung Transkripsi Langsung
Peran utama Asisten percakapan yang mendengarkan, memberikan alasan, dan berbicara kembali. Pipeline speech-to-text real-time yang mentranskripsikan audio masuk.
Modalitas respons Audio dan teks lisan (response_modalities=["AUDIO"]). Transkripsi teks streaming (response_modalities=["TEXT"]).
Gaya interaksi Dialog berbasis giliran dengan deteksi jeda dan interupsi. Pemrosesan streaming berkelanjutan saat penutur berbicara.
Fitur yang didukung Pemanggilan fungsi, Google Penelusuran, petunjuk sistem. Penyesuaian ucapan (custom_vocabulary), deteksi bahasa, VAD manual & hybrid, Transkripsi cerdas.
Input stream Multimodal: audio, video, gambar, teks. Input audio (PCM 16-bit mentah).

Mulai

Contoh berikut menunjukkan cara membuka sesi streaming dua arah dengan gemini-3.5-transcribe-live dan menerima transkripsi real-time.

Python

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

client = genai.Client()
model = "gemini-3.5-transcribe-live"

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],  # Automatic language detection
    ),
)

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

        # Receive transcription events
        async for response in session.receive():
            server_content = response.server_content
            if server_content and server_content.input_transcription:
                print("Transcript:", server_content.input_transcription.text)

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

JavaScript

import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({});
const model = 'gemini-3.5-transcribe-live';

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [], // Automatic language detection
  },
};

async function main() {
  const session = await ai.live.connect({
    model: model,
    config: config,
    callbacks: {
      onopen: () => console.log('Connected to Live Transcription'),
      onmessage: (message) => {
        const content = message.serverContent;
        if (content?.inputTranscription) {
          console.log('Transcript:', content.inputTranscription.text);
        }
      },
      onerror: (e) => console.error('Error:', e.message),
      onclose: (e) => console.log('Connection closed:', e.reason),
    },
  });
}

main();

WebSockets

const API_KEY = "YOUR_API_KEY";
const MODEL_NAME = "gemini-3.5-transcribe-live";
const WS_URL = `wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key=${API_KEY}`;

const websocket = new WebSocket(WS_URL);

websocket.onopen = () => {
  console.log('WebSocket connected');

  const setupMessage = {
    setup: {
      model: `models/${MODEL_NAME}`,
      generationConfig: {
        responseModalities: ['TEXT'],
      },
      inputAudioTranscription: {
        languageCodes: []
      }
    }
  };
  websocket.send(JSON.stringify(setupMessage));
};

websocket.onmessage = (event) => {
  const response = JSON.parse(event.data);
  const content = response.serverContent;
  if (content?.inputTranscription) {
    console.log('Transcript:', content.inputTranscription.text);
  }
};

Transkripsi sementara dan akhir

Saat audio di-streaming ke Live API, server akan memancarkan dua kolom transkripsi pelengkap dalam server_content:

  • interim_input_transcription: hipotesis parsial spekulatif latensi rendah diperbarui saat pembicara sedang aktif berbicara. Update parsial ini terjadi dengan cepat dan jeda minimal. Gunakan interim_input_transcription untuk merender subtitel UI live responsif atau pratinjau teks.
  • input_transcription: transkrip akhir yang dikeluarkan saat pembicara menjeda, giliran selesai, atau ucapan diselesaikan. Setelah dikeluarkan, teks ini merepresentasikan transkripsi resmi model dari segmen ucapan tersebut. Dalam mode transkripsi cerdas, hal ini akan mencakup respons yang sudah dibersihkan dan diformat.

Contoh berikut menunjukkan cara menampilkan parsial sementara streaming dan melakukan transkrip akhir:

Python

async def receive_transcripts(session):
    async for response in session.receive():
        server_content = response.server_content
        if not server_content:
            continue

        # Real-time interim hypothesis (updates dynamically as user speaks)
        if server_content.interim_input_transcription:
            interim_text = server_content.interim_input_transcription.text
            print(f"\r[Interim] {interim_text}", end="", flush=True)

        # Finalized transcript (emitted on speech completion)
        if server_content.input_transcription:
            final_text = server_content.input_transcription.text
            print(f"\n[Final] {final_text}")

JavaScript

onmessage: (message) => {
  const content = message.serverContent;
  if (!content) return;

  if (content.interimInputTranscription) {
    // Update live subtitle preview on screen
    renderInterimPreview(content.interimInputTranscription.text);
  }

  if (content.inputTranscription) {
    // Append final committed transcript to chat history
    commitFinalTranscript(content.inputTranscription.text);
  }
};

WebSockets

websocket.onmessage = (event) => {
  const response = JSON.parse(event.data);
  const content = response.serverContent;
  if (content?.interimInputTranscription) {
    console.log('[Interim]:', content.interimInputTranscription.text);
  }
  if (content?.inputTranscription) {
    console.log('[Final]:', content.inputTranscription.text);
  }
};

Mengirim audio

Streaming potongan audio melalui koneksi aktif sebagai audio PCM 16-bit mentah.

  • Format audio: PCM 16-bit mentah pada 16 kHz (mono, little-endian).
  • Ukuran chunk: Kirim audio dalam chunk 100 md (1.024 hingga 2.048 frame).
  • Jenis MIME: audio/pcm;rate=16000 (atau sample rate yang cocok).

Python

# Stream a raw PCM audio chunk
await session.send_realtime_input(
    audio=types.Blob(
        data=audio_chunk_bytes,
        mime_type="audio/pcm;rate=16000"
    )
)

# Signal the end of the audio stream when finished
await session.send_realtime_input(audio_stream_end=True)

JavaScript

// Send base64-encoded PCM audio chunk
session.sendRealtimeInput({
  audio: {
    data: audioChunkBase64,
    mimeType: 'audio/pcm;rate=16000'
  }
});

// Signal stream end
session.sendRealtimeInput({
  audioStreamEnd: true
});

WebSockets

// Send base64-encoded PCM audio chunk
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: {
      data: audioChunkBase64,
      mimeType: 'audio/pcm;rate=16000'
    }
  }
}));

// Signal stream end
websocket.send(JSON.stringify({
  realtimeInput: {
    audioStreamEnd: true
  }
}));

Fitur transkripsi

Deteksi bahasa otomatis

Secara default, tidak menyertakan language_codes atau menyetel language_codes=[] akan mengaktifkan identifikasi bahasa otomatis. Model ini secara dinamis mendeteksi bahasa yang diucapkan di seluruh ucapan, termasuk percakapan multibahasa dan peralihan kode.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [],
  },
};

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: [],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Petunjuk bahasa tertentu

Berikan kode bahasa BCP-47 eksplisit (misalnya, ["es-ES"] untuk bahasa Spanyol atau ["fr-FR"] untuk bahasa Prancis) untuk memengaruhi pengenalan ke bahasa tertentu (lihat Bahasa yang didukung).

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=["es-ES"],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: ['es-ES'],
  },
};

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: ['es-ES'],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Bias kosakata kustom

Berikan daftar hingga 1.000 frasa, kata benda khusus, nama merek, atau istilah teknis dalam custom_vocabulary untuk memengaruhi pengenalan ucapan agar menggunakan terminologi tertentu (hasil terbaik biasanya dicapai dengan hingga 100 istilah).

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],
        custom_vocabulary=["Gemini", "Kubernetes", "BigQuery"],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [],
    customVocabulary: ['Gemini', 'Kubernetes', 'BigQuery'],
  },
};

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: [],
      customVocabulary: ['Gemini', 'Kubernetes', 'BigQuery'],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Transkripsi pintar

Konfigurasi pemformatan output transkripsi menggunakan parameter mode di input_audio_transcription:

  • VERBATIM (default): Menghasilkan transkrip literal yang persis dari semua yang diucapkan, dengan mempertahankan kata pengisi mentah ("um", "eh", "kayak"), pengulangan, dan permulaan yang salah.
  • SMART (Transkripsi cerdas): Membersihkan dan menyusun transkrip agar mudah dibaca:

    • Penghapusan gangguan kelancaran: Menghapus kata pengisi, gagap, dan kesalahan memulai kalimat.
    • Koreksi mandiri inline: Menyelesaikan koreksi lisan secara alami.
    • Pemformatan terstruktur: Secara otomatis memformat daftar, poin-poin, angka, tanggal, dan jeda paragraf.
    • Tata bahasa & kapitalisasi: Menerapkan kapitalisasi alami dan polesan tanda baca.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        mode="SMART",
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    mode: 'SMART',
  },
};

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      mode: 'SMART',
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Strategi Deteksi Aktivitas Suara (VAD)

VAD Otomatis (Default)

Secara default, Deteksi Aktivitas Suara otomatis sisi server mendeteksi kapan pembicara mulai dan berhenti berbicara.

VAD Hybrid

VAD Hybrid menggabungkan deteksi awal ucapan otomatis sisi server dengan deteksi akhir ucapan sisi klien untuk penyelesaian giliran dengan latensi nol:

  1. VAD otomatis sisi server tetap diaktifkan untuk mendeteksi awal ucapan secara akurat dengan padding audio awalan, sehingga mencegah pemotongan kata depan.
  2. VAD sisi klien mendeteksi keheningan: Saat VAD di perangkat lokal mendeteksi bahwa pembicara telah berhenti berbicara, klien akan segera mengirimkan sinyal audio_stream_end.
  3. Finalisasi cepat: Server memperlakukan audio_stream_end sebagai perintah finalisasi langsung, melewati waktu tunggu tanpa suara sisi server default dan menampilkan transkrip yang difinalisasi dengan latensi minimal.
  4. Penggantian: Jika VAD klien gagal dipicu, VAD sisi server akan bertindak sebagai penggantian otomatis.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(),
)

async with client.aio.live.connect(model=model, config=config) as session:
    # Stream audio chunks...
    await session.send_realtime_input(
        audio=types.Blob(data=chunk, mime_type="audio/pcm;rate=16000")
    )

    # When client-side VAD detects end of speech, send audio_stream_end:
    await session.send_realtime_input(audio_stream_end=True)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {},
};

// Stream audio...
session.sendRealtimeInput({
  audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' }
});

// When client VAD detects end of speech, send audioStreamEnd:
session.sendRealtimeInput({
  audioStreamEnd: true
});

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {},
  },
};
websocket.send(JSON.stringify(setupMessage));

// Stream audio...
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' }
  }
}));

// When client VAD detects end of speech, send audioStreamEnd:
websocket.send(JSON.stringify({
  realtimeInput: {
    audioStreamEnd: true
  }
}));

VAD Manual (Push-to-Talk)

Untuk antarmuka walkie-talkie atau tombol tekan untuk bicara, nonaktifkan VAD otomatis sepenuhnya dan kontrol batas pergantian secara eksplisit menggunakan activity_start dan activity_end:

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    realtime_input_config=types.RealtimeInputConfig(
        automatic_activity_detection=types.AutomaticActivityDetection(
            disabled=True
        )
    ),
    input_audio_transcription=types.AudioTranscriptionConfig(),
)

async with client.aio.live.connect(model=model, config=config) as session:
    # Button pressed: signal speech start
    await session.send_realtime_input(activity_start=types.ActivityStart())

    # Stream audio chunks...
    await session.send_realtime_input(audio=types.Blob(data=chunk, mime_type="audio/pcm;rate=16000"))

    # Button released: signal speech end
    await session.send_realtime_input(activity_end=types.ActivityEnd())

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  realtimeInputConfig: {
    automaticActivityDetection: {
      disabled: true,
    },
  },
  inputAudioTranscription: {},
};

// Signal speech start
session.sendRealtimeInput({ activityStart: {} });

// Stream audio...

// Signal speech end
session.sendRealtimeInput({ activityEnd: {} });

WebSockets

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    realtimeInputConfig: {
      automaticActivityDetection: {
        disabled: true,
      },
    },
    inputAudioTranscription: {},
  },
};
websocket.send(JSON.stringify(setupMessage));

// Button pressed: signal speech start
websocket.send(JSON.stringify({
  realtimeInput: {
    activityStart: {},
  },
}));

// Stream audio...
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' },
  },
}));

// Button released: signal speech end
websocket.send(JSON.stringify({
  realtimeInput: {
    activityEnd: {},
  },
}));

Token sementara di aplikasi klien

Untuk aplikasi klien ke server (seperti aplikasi seluler atau web yang melakukan streaming langsung dari mikrofon), gunakan token sementara untuk menghindari pemaparan kunci API Anda dalam kode klien.

Buat token sementara yang dibatasi di server Anda sebelum memulai koneksi klien:

Python

import datetime
from google import genai

client = genai.Client()
expire_time = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(minutes=30)

token = client.auth_tokens.create(
    config={
        "uses": 1,
        "expire_time": expire_time,
        "live_connect_constraints": {
            "model": "gemini-3.5-transcribe-live",
            "config": {
                "response_modalities": ["TEXT"],
                "input_audio_transcription": {
                    "language_codes": [],
                },
            },
        },
    }
)

JavaScript

import { GoogleGenAI } from '@google/genai';

const client = new GoogleGenAI({});
const expireTime = new Date(Date.now() + 30 * 60 * 1000).toISOString();

const token = await client.authTokens.create({
  config: {
    uses: 1,
    expireTime: expireTime,
    liveConnectConstraints: {
      model: 'gemini-3.5-transcribe-live',
      config: {
        responseModalities: ['TEXT'],
        inputAudioTranscription: {
          languageCodes: [],
        },
      },
    },
  },
});

REST

curl -X POST "https://generativelanguage.googleapis.com/v1beta/auth_tokens" \
  -H "x-goog-api-key: ${GEMINI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "uses": 1,
    "expireTime": "YYYY-MM-DDTHH:MM:SSZ",
    "liveConnectConstraints": {
      "model": "models/gemini-3.5-transcribe-live",
      "config": {
        "responseModalities": ["TEXT"],
        "inputAudioTranscription": {
          "languageCodes": []
        }
      }
    }
  }'

Bahasa yang didukung

Bahasa dan kode bahasa BCP-47 berikut didukung untuk Transcribe Live Gemini 3.5:

Language Kode BCP-47 Language Kode BCP-47
Afrika af-ZA Jepang ja-JP
Amharik am-ET Jawa jv-ID
Arab (Mesir) ar-EG Kabuverdianu kea-CV
Armenia hy-AM Kannada kn-IN
Assam as-IN Kazak kk-KZ
Azerbaijan az-AZ Korea ko-KR
Belarusia be-BY Kirgiz ky-KG
Bengali (Bangladesh) bn-BD Latvia lv-LV
Bengali (India) bn-IN Lingala ln-CD
Bosnia bs-BA Lituania lt-LT
Bulgaria bg-BG Makedonia mk-MK
Bulgaria (Aromania) rup-BG Melayu ms-MY
Burma my-MM Malayalam ml-IN
Kanton (Tradisional) yue-Hant-HK Malta mt-MT
Katalan ca-ES China Mandarin (Aksara Sederhana) cmn-Hans-CN
Cebuano ceb Marathi mr-IN
Khmer Tengah km-KH Mongolia mn-MN
Kroasia hr-HR Nepal ne-NP
Ceko cs-CZ Norwegia nb-NO
Denmark da-DK Oriya or-IN
Belanda nl-NL Polandia pl-PL
Inggris (Britania Raya) en-GB Portugis (Brasil) pt-BR
Inggris (India) en-IN Portugis (Portugal) pt-PT
Inggris (Amerika Serikat) en-US Punjabi pa-IN
Estonia et-EE Punjabi (skrip Gurmukhi) pa-Guru-IN
Persia fa-IR Rumania ro-RO
Filipino fil-PH Rusia ru-RU
Finlandia fi-FI Serbia sr-RS
Prancis fr-FR Sindhi (skrip Arab) sd-Arab-IN
Galisia gl-ES Slovakia sk-SK
Georgia ka-GE Slovenia sl-SI
Jerman de-DE Spanyol (Amerika Latin) es-419
Yunani el-GR Spanyol (Amerika Serikat) es-US
Gujarati gu-IN Swahili (Kenya) sw-KE
Hausa ha-NG Swedia sv-SE
Ibrani he-IL Tajik tg-TJ
Hindi hi-IN Telugu te-IN
Hungaria hu-HU Thai th-TH
Islandia is-IS Turki tr-TR
Inggris - India en-IN Ukraina uk-UA
Indonesia id-ID Uzbek uz-UZ
Italia it-IT Vietnam vi-VN

Referensi parameter

Konfigurasi transkripsi instan menggunakan kolom di input_audio_transcription dan realtime_input_config:

Parameter Jenis Deskripsi
language_codes Array string Kode bahasa BCP-47 (misalnya, ["en-US"]). Jika tidak ada atau kosong ([]), model akan otomatis mendeteksi bahasa dan menangani ucapan multibahasa.
custom_vocabulary Array string Hingga 1.000 istilah kustom, akronim, nama merek, atau kata benda khusus untuk memengaruhi pengenalan ucapan.
mode String Mode transkripsi: "VERBATIM" (default) atau "SMART" (Transkripsi smart). Jika disetel ke "SMART", model akan menghapus kata pengisi, memformat daftar, dan mengoreksi ketidaklancaran.
automatic_activity_detection.disabled Boolean Setel ke true untuk menonaktifkan deteksi aktivitas suara otomatis dan mengirim sinyal activityStart dan activityEnd secara manual.

Kolom respons server

Kolom Deskripsi
server_content.interim_input_transcription Hipotesis transkripsi parsial sementara dengan latensi rendah yang dipancarkan secara berkelanjutan saat pengguna sedang berbicara.
server_content.input_transcription Transkrip input resmi yang telah diselesaikan dikeluarkan saat giliran ucapan selesai.

Batasan

  • Durasi sesi: Sesi transkripsi langsung mendukung streaming berkelanjutan hingga 10 menit.
  • Diarisasi pembicara: Diarisasi pembicara tidak didukung dalam sesi live streaming. Untuk diarisasi pembicara, gunakan endpoint Transkripsi audio non-streaming.
  • Stempel waktu tingkat kata: Stempel waktu tingkat kata tidak didukung melalui Live API. Live API memancarkan stempel waktu tingkat ucapan (interim_input_transcription dan input_transcription).
  • Kosakata kustom: Anda dapat memberikan hingga 1.000 istilah dalam custom_vocabulary, tetapi hasil terbaik biasanya dicapai dengan hingga 100 istilah.
  • Kompatibilitas mode: Transkripsi smart ("mode": "SMART") menghapus kata pengisi dan memformat teks yang memahami maksud, tetapi tidak dapat digabungkan dengan anotasi kata.

Langkah berikutnya