跳到内容
  1. 洞察

Speech to Text API 集成:开发者指南

作者
Jack Limebear

收听收听本文

Speech to Text API 让开发者可以直接在应用中集成语音识别和转写功能。但在连接 STT API 前,需要先做一些架构决策。

你会选择哪种转写模式?如何处理较长的音频文件?如何确保产品名或专有名词拼写正确?提前规划有助于打造可扩展的 语音转文本 API 集成。

本指南涵盖了 ElevenLabs 语音转文本 API 集成所需的一切,包含可直接用于生产环境的清晰代码示例。建议同时打开 ElevenLabs Speech to Text 快速入门API 指南 以便参考。

摘要

  • ElevenLabs Speech to Text 提供两种模式:批量(适用于预录音频)和实时(通过 WebSocket 处理实时音频流)。
  • Scribe v2 支持 90 多种语言的批量转写,具备说话人分离、关键词提示、实体检测、逐词时间戳和多通道支持。
  • Scribe v2 实时版 支持实时流式转写,延迟约 150 毫秒,可在说话时返回部分转写,语音片段结束后返回最终转写。
  • 对于超过 8 分钟的文件,Scribe v2 会自动分段并并行转写。长时间任务建议使用 webhook,避免同步等待响应。
  • 关键词提示通过上下文让模型更倾向于识别特定词汇,比关键词列表更适合产品名、技术术语或特殊专有名词。

Speech to Text API 集成:批量与实时对比

每次 ElevenLabs STT API 集成都要先选架构模式:批量还是实时。两者都能为开发环境带来强大的 STT 模型,但选择会影响可用功能和端到端延迟。

两种模式对比如下:

  • 批量(Scribe v2):上传完整音频或视频文件,转写后一次性返回完整文本。支持最多 1,000 个关键词、32 个说话人分离、实体检测、多通道模式和 webhook 异步推送。标准模式下支持最大 3 GB、10 小时的文件。
  • 实时(Scribe v2 Realtime):通过 WebSocket 接收实时音频流,边接收边返回部分和最终转写,延迟约 150 毫秒。支持最多 50 个关键词和逐词时间戳,适合语音助手、实时字幕等需要即时响应的场景。

下面进一步拆解两者区别。

Feature
Batch (Scribe v2)
Realtime (Scribe v2 Realtime)
Input
Pre-recorded audio or video file
Live audio stream
Latency
File duration + processing time
~150ms
Keyterms
Up to 1,000 (50 chars each)
Up to 50 (20 chars each)
Speaker diarization
Up to 32 speakers
-
Entity detection
Entity detection, up to 56
-
Multichannel
Up to 5 channels
-
Languages
Accurate in 90+ languages
Accurate in 90+ languages
Async delivery
Webhooks
-
Best for
Transcription pipelines, meeting recordings, long-form audio
Voice agents, live captions, real-time assistants

简单来说:音频已录制完毕时用批量,边录边转写时用实时。

何时选择 Scribe v2 或 Scribe v2 Realtime

批量和实时适用于不同场景,选错模式后期容易返工。

具体匹配方式如下:

  • Scribe v2 适合音频已录制完毕再处理的场景,如会议录音、播客转写、媒体文件或离线处理。支持说话人分离、实体检测和最多 1,000 个关键词等全部功能。
  • Scribe v2 Realtime 专为实时音频设计。通过 WebSocket 流接收音频并实时返回转写,适合语音助手等需要在用户说话时即时响应的场景。

还需注意,不同语言的转写准确率不同。建议在确定语言组合前,先查看各语言的转写词错误率(WER)。Scribe v2 公布了 90 多种支持语言的 WER 分级。

极高准确率(≤5% WER)覆盖主要欧洲语言、日语、印尼语、越南语等。高准确率(5-10% WER)覆盖印地语、孟加拉语、普通话、韩语、格鲁吉亚语等。详细分类见 语言支持文档

ElevenLabs Speech to Text API 设置

只需两步即可获得可用客户端。第一步,安装 SDK。第二步,安全存储凭证。

在首次转写请求前,按以下步骤操作。

安装 SDK,并用 .env 文件或平台密钥管理器安全存储 API 密钥。切勿将 API 密钥硬编码进应用。

Python

pip install elevenlabs
pip install python-dotenv

TypeScript

npm install @elevenlabs/elevenlabs-js

创建 .env 文件:

ELEVENLABS_API_KEY=<your_api_key_here>

初始化客户端:

Python

import os
from dotenv import load_dotenv
from elevenlabs.client import ElevenLabs

load_dotenv()

elevenlabs = ElevenLabs(
    api_key=os.getenv("ELEVENLABS_API_KEY"),
)

TypeScript

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({
  apiKey: process.env.ELEVENLABS_API_KEY,
});

使用 ElevenLabs STT API 进行首次批量转写

客户端初始化后,即可发送首个文件。

批量 API 接收文件,转写后同步返回完整结果。下方示例转写远程音频文件,并启用说话人分离和音频事件标记。

Python

# example.py
import os
from dotenv import load_dotenv
from io import BytesIO
import requests
from elevenlabs.client import ElevenLabs

load_dotenv()

elevenlabs = ElevenLabs(
    api_key=os.getenv("ELEVENLABS_API_KEY"),
)

audio_url = (
    "https://storage.googleapis.com/eleven-public-cdn/audio/marketing/nicole.mp3"
)
response = requests.get(audio_url)
audio_data = BytesIO(response.content)

transcription = elevenlabs.speech_to_text.convert(
    file=audio_data,
    model_id="scribe_v2",          # Model to use
    tag_audio_events=True,          # Tag audio events like laughter, applause, etc.
    language_code="eng",            # Language of the audio file. If set to None, the model will detect the language automatically.
    diarize=True,                   # Whether to annotate who is speaking
)

print(transcription)

运行:

python example.py

响应对象包含完整转写文本、带时间戳和说话人 ID 的逐词条目,以及检测到的音频事件。

每个词条包含一个 type 字段,取值如下:

  • word:音频中转写出的词。
  • spacing:词间空格(适用于有空格的语言)。日语、粤语、缅甸语等语言不适用此类型。
  • audio_event:非语音声音标签,如笑声或咳嗽。

响应结构如下:

{
  "language_code": "en",
  "language_probability": 1,
  "text": "With a soft and whispery American accent, I'm the ideal choice for creating ASMR content, meditative guides, or adding an intimate feel to your narrative projects.",
  "words": [
    {
      "text": "With",
      "start": 0.119,
      "end": 0.259,
      "type": "word",
      "speaker_id": "speaker_0"
    },
    {
      "text": " ",
      "start": 0.239,
      "end": 0.299,
      "type": "spacing",
      "speaker_id": "speaker_0"
    },
    {
      "text": "a",
      "start": 0.279,
      "end": 0.359,
      "type": "word",
      "speaker_id": "speaker_0"
    }
  ]
}

language_probability 字段表示模型对语言检测的置信度,范围 0.00-1.00。

STT API 实时集成

实时 STT API 集成流程略有不同。不是一次请求一次响应,而是建立 WebSocket 连接,实时接收转写结果。

实时 API 通过 WebSocket 接收实时音频流,并在音频到达时返回转写。包含两种转写类型:

  • 部分转写:模型处理音频时的中间结果,内容可能会变化。
  • 最终转写:语音片段结束后的最终结果,不会再更改。如设置 "include timestamps" 为 true,还会包含逐词时间戳。

客户端实现时,使用一次性 token 替代 API 密钥。该 token 由服务端生成,有效期 15 分钟,避免 API 密钥暴露在浏览器端。

步骤 1:生成一次性 token(服务端)

// Node.js server
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({
  apiKey: process.env.ELEVENLABS_API_KEY,
});

app.get("/scribe-token", yourAuthMiddleware, async (req, res) => {
  const token = await elevenlabs.tokens.singleUse.create("realtime_scribe");

  res.json(token);
});

步骤 2:连接并转写(客户端,React)

import { useScribe } from "@elevenlabs/react";

function MyComponent() {
  const scribe = useScribe({
    modelId: "scribe_v2_realtime",
    onPartialTranscript: (data) => {
      console.log("Partial:", data.text);
    },
    onCommittedTranscript: (data) => {
      console.log("Committed:", data.text);
    },
    onCommittedTranscriptWithTimestamps: (data) => {
      console.log("Committed with timestamps:", data.text);
      console.log("Timestamps:", data.words);
    },
  });

  const handleStart = async () => {
    // Fetch a single use token from the server
    const token = await fetchTokenFromServer();

    await scribe.connect({
      token,
      microphone: {
        echoCancellation: true,
        noiseSuppression: true,
      },
    });
  };

  return (
    <div>
      <button onClick={handleStart} disabled={scribe.isConnected}>
        Start Recording
      </button>
      <button onClick={scribe.disconnect} disabled={!scribe.isConnected}>
        Stop
      </button>

      {scribe.partialTranscript && <p>Live: {scribe.partialTranscript}</p>}

      <div>
        {scribe.committedTranscripts.map((t) => (
          <p key={t.id}>{t.text}</p>
        ))}
      </div>
    </div>
  );
}

useScribe hook 管理 WebSocket 连接、麦克风权限和转写状态。partialTranscript 保存当前转写文本,committedTranscripts 存储已完成片段。

如需服务端流式转写(如从 URL 或文件流转写音频),请参考 服务端流式转写指南.

并发与长文件扩展

长文件需要不同于常规 API 的扩展方式,建议提前了解。

批量转写的并发机制不同于大多数 API。Scribe v2 会自动将长文件内部并行处理,而不是限制并发请求数。

超过 8 分钟的文件会被自动分段并同时转写。并发段数计算方式如下:

Concurrency = min(4, round_up(audio_duration_secs / 480))

具体示例:

  • 15 分钟文件并发数为 2
  • 120 分钟文件并发数为 4(最大值)

标准模式下支持最长 10 小时、3 GB 的文件。注意:多通道模式下时长限制更低,详见下文多通道转写部分。

支持的格式方面,STT API 可接收常见音频和视频格式:

  • 音频:AAC、AIFF、OGG、MP3、OPUS、WAV、FLAC、M4A、WebM。
  • 视频:MP4、AVI、MKV、MOV、WMV、FLV、WebM、MPEG、3GPP。

可直接上传视频文件,自动提取音轨并转写,无需预处理。

关键词提示

通用模型容易误转品牌名和技术术语,关键词提示可解决此问题。

关键词提示让模型在转写时更倾向于识别指定词语,适用于包含产品名、技术词汇或特殊专有名词的音频。

关键词提示的优势在于利用上下文,比简单关键词列表更可靠。例如,将 "ElevenLabs" 作为关键词,模型在听到公司名时会正确转写,否则可能出现 "I've worked at eleven labs for a year" 被误转写的情况。

未使用关键词提示:

I work at eleven labs.

使用 keyterms=["ElevenLabs"]:

I work at ElevenLabs.

批量模式支持最多 1,000 个关键词(每个 50 字符),实时模式支持最多 50 个关键词(每个 20 字符)。

批量转写关键词用法

Python

import os
from dotenv import load_dotenv
from io import BytesIO
import requests
from elevenlabs.client import ElevenLabs

load_dotenv()

elevenlabs = ElevenLabs(
    api_key=os.getenv("ELEVENLABS_API_KEY"),
)

audio_url = (
    "https://storage.googleapis.com/eleven-public-cdn/documentation_assets/audio/stt-keyterm-prompting.mp3"
)
response = requests.get(audio_url)
audio_data = BytesIO(response.content)

transcription = elevenlabs.speech_to_text.convert(
    file=audio_data,
    model_id="scribe_v2",
    # Keyterms to prompt the model with.
    # Up to 1,000 keyterms can be provided, with a maximum length of 50 characters each
    keyterms=["ElevenLabs"],
)

print(transcription)

实时流式关键词用法

连接实时 WebSocket 时传递关键词:

Python

connection = await elevenlabs.speech_to_text.realtime.connect(RealtimeUrlOptions(
    model_id="scribe_v2_realtime",
    keyterms=["ElevenLabs"],
))

或直接作为查询参数传递到 WebSocket URL:

wss://api.elevenlabs.io/v1/speech-to-text/realtime?model_id=scribe_v2_realtime&keyterms=ElevenLabs&keyterms=AnotherTerm

关键词提示功能需额外付费,详情见 API 价格页面

高级功能

上述流程涵盖了 STT API 的核心转写,但还有多项功能可丰富最终输出。以下是 Speech to Text API 可用的高级功能:

  • 说话人分离,识别发言人
  • 非逐字模式,清理转写内容
  • 实体检测,标记敏感数据
  • 多通道转写,分离音频通道

下面逐一介绍。

说话人分离

批量请求中设置 diarize=True,可标注发言人。Scribe v2 支持最多 32 个说话人。响应中每个词包含 speaker_id 字段(如 speaker_0、speaker_1),可按说话人分割转写片段。

说话人分离适用于会议转写、访谈处理或多说话人录音等需区分发言人的场景。

非逐字模式

设置 no_verbatim=True 时,模型会自动去除转写中的语气词、重复、口吃等杂音。例如 "Erm, M-maybe we should, uh, go with option A" 会变成 "Maybe we should go with option A."

适合字幕、摘要或更注重可读性的场景。批量(scribe_v2)和实时(scribe_v2_realtime)均支持。

实体检测与脱敏

Scribe v2 可检测并标注转写中的实体,并给出精确时间戳。类别包括 PII(姓名、信用卡号、社保号)、PHI(健康信息)、PCI(支付卡信息)等。完整实体类型列表见 实体检测文档.

此功能适用于合规场景,可在存储或展示前自动识别并脱敏敏感信息。

实体检测功能需额外 $0.070/小时,详情见 API 价格页面

多通道转写

设置 use_multi_channel=True 时,每个音频通道独立转写,并按通道号分配说话人 ID。最多支持 5 个通道,多通道模式下单文件最长 1 小时。

多通道模式适用于每位说话人单独音轨的录音,如电话录音。比混音文件的说话人分离更准确。

Webhook 异步推送

低量级时轮询结果尚可,但处理长文件或高并发时无法扩展。Webhook 可主动推送结果,解决此问题。

长文件或高并发转写时,同步等待响应不现实。Webhook 支持提交请求后,处理完成自动推送结果到指定端点,无需轮询。

Webhook 设置

在 ElevenLabs 控制台,进入 开发者 > Webhooks,点击 创建 webhook,并配置:

  • 名称:填写易记且有描述性的名称。
  • 回调 URL:添加可公开访问的 HTTPS 端点。
  • Webhook 认证方式:选择 HMAC 或 OAuth(二选一,强烈推荐用于安全)。
  • 事件:选择“转写完成”事件。

Webhook 推送转写请求

Python

from dotenv import load_dotenv
from elevenlabs.client import ElevenLabs

load_dotenv()

elevenlabs = ElevenLabs(
    api_key=os.getenv("ELEVENLABS_API_KEY"),
)

def transcribe_with_webhook(audio_file):
    try:
        result = elevenlabs.speech_to_text.convert(
            file=audio_file,
            model_id="scribe_v2",
            webhook=True,
        )
        print(f"Transcription started: {result.request_id}")
        return result
    except Exception as e:
        print(f"Error starting transcription: {e}")
        raise e

设置 webhook=True 后,请求会提前返回,转写完成后以 POST 方式推送到你的端点。

Webhook 端点实现

import { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';
import 'dotenv/config';
import express from 'express';

const elevenlabs = new ElevenLabsClient();
const app = express();
app.use(express.json());

const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

app.post('/webhook/speech-to-text', (req, res) => {
  try {
    const signature = req.headers['elevenlabs-signature'];
    const payload = JSON.stringify(req.body);
    let event;

    try {
      // Verify the webhook signature.
      event = await elevenlabs.webhooks.constructEvent(payload, signature, WEBHOOK_SECRET);
    } catch (error) {
      return res.status(401).json({ error: 'Invalid signature' });
    }

    if (event.type === 'speech_to_text.completed') {
      const { requestId, status, text, language_code } = event.data;

      console.log(`Transcription ${requestId} completed`);
      console.log(`Language: ${language_code}`);
      console.log(`Text: ${text}`);

      processTranscription(requestId, text, language_code);
    } else if (status === 'failed') {
      console.error(`Transcription ${requestId} failed`);
      handleTranscriptionError(requestId);
    }

    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => {
  console.log('Webhook server listening on port 3000');
});

Webhook 数据结构

端点会收到如下结构的 POST 请求:

{
  "type": "speech_to_text_transcription",
  "data": {
    "request_id": "some-request-id-123",
    "webhook_metadata": {},
    "transcription": {
      "language_code": "en",
      "language_probability": 0.98,
      "text": "Hello world!",
      "words": [
        {
          "text": "Hello",
          "start": 0.0,
          "end": 0.5,
          "type": "word",
          "speaker_id": "speaker_1"
        }
      ]
    }
  }
}

Webhook 安全最佳实践

使用 webhook 时,可采取以下安全措施确保事件正确推送和处理。

  • 验证 webhook 签名:始终用 elevenlabs.webhooks.constructEvent() 验证 webhook 签名,确保来源于 ElevenLabs。
  • 使用 HTTPS 端点:Webhook URL 必须为 HTTPS,保障传输数据安全。
  • 返回正确的 HTTP 状态码:处理成功返回 200-299,客户端错误返回 400-499(不会重试),服务端错误返回 500-599(会重试)。
  • 本地开发用隧道工具:本地开发时,可用 ngrok 等隧道工具将本地服务暴露为公网 HTTPS URL。

采用以上策略,可放心使用 webhook。

Speech to Text API 集成要点总结

生产级 Speech to Text API 集成主要取决于几个关键决策。

选对这些,后续流程都顺畅:

  • 按场景选择模式:音频已录制完毕用批量(scribe_v2),需边录边转写用实时(scribe_v2_realtime),如 智能体、语音助手或实时字幕。
  • 用关键词提升特定词汇准确率:将产品名、技术词或特殊专有名词作为关键词传递,模型会结合上下文准确应用,避免误触发。
  • 长文件交给 API 自动处理:超过 8 分钟的文件会自动并行处理,无需手动分段。标准模式下支持最长 10 小时、3 GB 文件。
  • 异步流程用 webhook:长任务或高并发处理时,webhook=True 可提交后直接继续其他操作。每次接收 webhook 时都要验证签名。
  • 开启非逐字模式获得更清晰输出:如用于字幕、摘要或下游 NLP,no_verbatim=True 可自动去除杂音和口吃。
  • 多通道模式适合分轨录音:如每位说话人单独通道(呼叫中心 录音、访谈等),多通道转写比混音文件的说话人分离更准确。注意此模式下单文件最长 1 小时。

如需更多信息,可参考 完整 API 参考文档

用 ElevenAPI 构建 Speech to Text 集成

看完本指南,你已掌握生产级 Speech to Text API 集成的全部模式。无论批量还是实时转写,包含关键词提示、异步推送等高级功能,都能让你的应用快速接入 STT。

建议先了解 语音转文本 API,或 注册账号,立即用 ElevenAPI 发起首次调用。

STT API 集成常见问题

用高质量 AI 音频创作