使用 Gemini Live API 進行即時轉錄

Gemini Live API 支援使用 gemini-3.5-transcribe-live 模型進行低延遲的即時語音轉文字轉錄。透過 WebSockets 連線至 Live API,或使用 Google Gen AI SDK,即可串流連續音訊輸入內容,並在語音出現時接收即時文字轉錄稿。

開發人員平台 (例如 AgoraFishjamLiveKitPipecatVercelVision Agents) 運用 Gemini Live API,可讓開發人員輕鬆建構及部署高效能的語音介面。這些平台會在幕後管理複雜的即時媒體串流基礎架構,讓開發人員專心打造使用者體驗。

真人服務專員與即時轉錄

兩者都使用 Live API 雙向串流連線,但即時轉錄功能是專用的低延遲語音辨識管道,而非對話式代理程式。

功能 線上服務專員 即時轉錄
主要作用 對話式助理會聆聽、推理並回覆。 即時語音轉文字管道,可轉錄輸入的音訊。
回覆方式 語音音訊和文字 (response_modalities=["AUDIO"])。 串流文字轉錄稿 (response_modalities=["TEXT"])。
互動風格 以輪流對話的形式進行,可偵測暫停和中斷。 在說話者說話時,持續處理串流。
支援的功能 函式呼叫、Google 搜尋、系統指令。 語音偏好設定 (custom_vocabulary)、語言偵測、手動和混合 VAD、智慧轉錄。
輸入串流 多模態:音訊、影片、圖像、文字。 音訊輸入 (原始 16 位元 PCM)。

開始使用

下列範例示範如何使用 gemini-3.5-transcribe-live 開啟雙向串流工作階段,並接收即時轉錄內容。

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

WebSocket

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

暫定和最終轉錄稿

音訊串流傳送至 Live API 時,伺服器會在 server_content 中發出兩個互補的轉錄欄位:

  • interim_input_transcription:低延遲,在說話者說話時更新推測的部分假設。這些部分更新會快速進行,延遲時間極短。使用 interim_input_transcription 轉譯即時 UI 字幕或預覽字幕。
  • input_transcription:說話者暫停、輪流說話完成或語音完成時,系統會發出最終轉錄稿。發出後,這段文字代表模型對該語音片段的權威轉錄內容。在智慧轉錄模式下,這會包括經過清理和格式化的回覆。

以下範例說明如何顯示串流中繼部分結果,以及提交最終轉錄稿:

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

WebSocket

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

正在傳送音訊

透過有效連線串流音訊區塊,以原始 16 位元 PCM 音訊格式傳輸。

  • 音訊格式:16 kHz 的原始 16 位元 PCM (單聲道,小端序)。
  • 分塊大小:以 100 毫秒 (1,024 到 2,048 個影格) 為單位傳送音訊。
  • MIME 類型: audio/pcm;rate=16000 (或相符的取樣率)。

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

WebSocket

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

轉錄功能

自動偵測語言

根據預設,省略 language_codes 或將 language_codes=[] 設為 language_codes=[],即可啟用自動語言辨識功能。模型會動態偵測語音中的語言,包括多語言對話和交替使用不同語言的情況。

Python

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

JavaScript

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

WebSocket

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

特定語言提示

提供明確的 BCP-47 語言代碼 (例如西班牙文為 ["es-ES"],法文為 ["fr-FR"]),將辨識結果偏向特定語言 (請參閱「支援的語言」)。

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'],
  },
};

WebSocket

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

自訂詞彙偏誤

提供最多 1,000 個詞組、專有名詞、品牌名稱或術語的清單,custom_vocabulary讓語音辨識器優先辨識特定術語 (通常最多 100 個字詞可達到最佳效果)。

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'],
  },
};

WebSocket

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

智慧轉錄

使用 input_audio_transcription 中的 mode 參數設定轉錄輸出格式:

  • VERBATIM (預設):逐字轉錄所有說出的內容,保留原始的贅字 (例如「嗯」、「呃」、「像」)、重複內容和錯誤開頭。
  • SMART (智慧轉錄):整理並編排轉錄稿,方便閱讀:

    • 移除口語障礙:移除贅字、口吃和錯誤開頭。
    • 即時自動修正:自然地解決口語修正問題。
    • 結構化格式:自動設定清單、項目符號、數字、日期和段落分隔符號的格式。
    • 文法和大小寫:自然地使用大寫字母,並潤飾標點符號。

Python

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

JavaScript

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

WebSocket

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

語音活動偵測 (VAD) 策略

自動 VAD (預設)

根據預設,伺服器端自動語音活動偵測功能會偵測說話者何時開始和停止說話。

混合 VAD

混合 VAD 結合伺服器端自動語音開始偵測和用戶端語音結束偵測,可零延遲完成回合:

  1. 伺服器端自動 VAD 仍會啟用,並使用前置音訊填補功能準確偵測語音開頭,避免截斷開頭的字詞。
  2. 用戶端 VAD 偵測到靜音:當本機裝置上的 VAD 偵測到說話者停止說話時,用戶端會立即傳送 audio_stream_end 訊號。
  3. 快速完成:伺服器會將 audio_stream_end 視為立即完成提示,略過預設的伺服器端靜音等待時間,並以最短延遲時間傳回最終轉錄稿。
  4. 備援:如果用戶端 VAD 無法觸發,伺服器端 VAD 會自動備援。

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

WebSocket

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 (按下開始交談)

如果是對講機介面或一按即說按鈕,請完全停用自動 VAD,並使用 activity_startactivity_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: {} });

WebSocket

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

用戶端應用程式中的臨時權杖

如果是用戶端對伺服器的應用程式 (例如直接從麥克風串流的行動或網路應用程式),請使用臨時權杖,避免在用戶端程式碼中公開 API 金鑰。

在伺服器上建立受限的臨時權杖,然後再啟動用戶端連線:

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": []
        }
      }
    }
  }'

支援的語言

Gemini 3.5 Transcribe Live 支援下列語言和 BCP-47 語言代碼:

語言 BCP-47 代碼 語言 BCP-47 代碼
南非荷蘭文 af-ZA 日文 ja-JP
阿姆哈拉文 am-ET 爪哇語 jv-ID
阿拉伯文 (埃及) ar-EG Kabuverdianu kea-CV
亞美尼亞文 hy-AM 卡納達文 kn-IN
阿薩姆文 as-IN 哈薩克文 kk-KZ
亞塞拜然文 az-AZ 韓文 ko-KR
白俄羅斯語 be-BY 吉爾吉斯文 ky-KG
孟加拉文 (孟加拉) bn-BD 拉脫維亞文 lv-LV
孟加拉文 (印度) bn-IN 林格拉文 ln-CD
波士尼亞文 bs-BA 立陶宛文 lt-LT
保加利亞文 bg-BG 馬其頓文 mk-MK
保加利亞文 (阿羅馬尼亞文) rup-BG 馬來文 ms-MY
緬甸文 my-MM 馬拉雅拉姆文 ml-IN
粵語 (繁體) yue-Hant-HK 馬爾他文 mt-MT
加泰隆尼亞文 ca-ES 中文 (簡體) cmn-Hans-CN
宿霧文 ceb 馬拉地文 mr-IN
中部高棉文 km-KH 蒙古文 mn-MN
克羅埃西亞文 hr-HR 尼泊爾文 ne-NP
捷克文 cs-CZ 挪威文 nb-NO
丹麥文 da-DK 奧里雅文 or-IN
荷蘭文 nl-NL 波蘭文 pl-PL
英文 (英國) en-GB 葡萄牙文 (巴西) pt-BR
英文 (印度) en-IN 葡萄牙文 (葡萄牙) pt-PT
英文 (美國) en-US 旁遮普文 pa-IN
愛沙尼亞文 et-EE 旁遮普文 (古爾穆基字母) pa-Guru-IN
波斯文 fa-IR 羅馬尼亞文 ro-RO
菲律賓文 fil-PH 俄文 ru-RU
芬蘭文 fi-FI 塞爾維亞文 sr-RS
法文 fr-FR 信德文 (阿拉伯字母) sd-Arab-IN
加里西亞文 gl-ES 斯洛伐克文 sk-SK
喬治亞文 ka-GE 斯洛維尼亞文 sl-SI
德文 de-DE 西班牙文 (拉丁美洲) es-419
希臘文 el-GR 西班牙文 (美國) es-US
古吉拉特文 gu-IN 斯瓦希里文 (肯亞) sw-KE
豪薩文 ha-NG 瑞典文 sv-SE
希伯來文 he-IL 塔吉克文 tg-TJ
北印度文 hi-IN 泰盧固文 te-IN
匈牙利文 hu-HU 泰文 th-TH
冰島文 is-IS 土耳其文 tr-TR
印度英語 en-IN 烏克蘭文 uk-UA
印尼文 id-ID 烏茲別克文 uz-UZ
義大利文 it-IT 越南文 vi-VN

參數參照

使用 input_audio_transcriptionrealtime_input_config 中的欄位設定即時轉錄:

參數 類型 說明
language_codes 字串陣列 BCP-47 語言代碼 (例如 ["en-US"])。如果省略或空白 ([]),模型會自動偵測語言並處理多語言語音。
custom_vocabulary 字串陣列 最多可提供 1,000 個自訂字詞、縮寫、品牌名稱或專有名詞,以調整語音辨識結果。
mode 字串 轉錄模式:"VERBATIM" (預設) 或 "SMART" (智慧轉錄)。如果設為 "SMART",模型會移除贅字、編排清單格式,並修正語句不流暢之處。
automatic_activity_detection.disabled 布林值 設為 true 可停用自動語音活動偵測功能,並手動傳送 activityStartactivityEnd 信號。

伺服器回應欄位

欄位 說明
server_content.interim_input_transcription 使用者說話時,系統會持續發出低延遲的暫時性部分轉錄假設。
server_content.input_transcription 語音輪流說話結束時發出的最終權威輸入轉錄稿。

限制

  • 工作階段持續時間:即時轉錄工作階段最多可連續串流 10 分鐘。
  • 說話者區分:直播工作階段不支援說話者區分功能。如要進行說話者區分,請使用非串流的 音訊轉錄端點。
  • 字詞層級時間戳記:Live API 不支援字詞層級時間戳記。Live API 會發出語句層級的時間戳記 (interim_input_transcriptioninput_transcription)。
  • 自訂詞彙:您最多可以在 custom_vocabulary 中提供 1,000 個字詞,但通常最多 100 個字詞就能獲得最佳結果。
  • 模式相容性:智慧轉錄 ("mode": "SMART") 會移除贅字並格式化意圖感知文字,但無法與字詞註解搭配使用。

後續步驟