用 GPT‑Live‑1 构建可打断、可定制、可接电话的实时语音应用

2026-09-10 31 预计阅读时间: 1 分钟
来源: openai.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

GPT‑Live‑1 将自然的全双工语音对话带入 API。相比“录音、上传、等待、播放”这类轮流工作的语音链路,全双工意味着用户说话、模型理解和语音输出可以并行发生。再结合更强的指令遵循、自定义声音与电话系统支持,语音应用可以从带语音按钮的聊天框,进一步变成能够实时响应、允许插话并保持角色一致的交互界面。

全双工改变的不只是延迟

传统语音助手通常按顺序执行:语音活动检测、语音转文字、模型推理、文字转语音。任何一段耗时都会累积,而且系统播放回答时往往无法处理用户的新输入。

全双工连接则需要同时维护两条数据流:

  • 上行流持续发送用户音频。
  • 下行流持续接收模型音频和状态事件。
  • 用户插话时,客户端立即停止当前播放,并通知服务端取消未完成的回答。
  • 会话指令、工具结果和音频事件共享同一条有状态连接。

因此,实现质量不只取决于模型,也取决于客户端是否正确处理并发、背压、中断和音频缓冲。一个常见错误是把发送和接收写在同一个循环中:播放一次较长的响应就会阻塞麦克风上传,所谓实时对话仍会退化成轮流说话。

一个可改造的双向音频客户端

下面是一个最小 Python 骨架,展示如何并行采集、发送和播放 PCM 音频。由于摘要没有给出正式端点、鉴权头和事件结构,示例中的 URL 与事件名是明确的占位约定;接入时应按照当前 GPT‑Live‑1 API 文档替换它们。

安装依赖:

python -m pip install websockets sounddevice
export OPENAI_API_KEY="your-api-key"
export GPT_LIVE_URL="wss://YOUR_REALTIME_ENDPOINT"
python live_voice.py

创建 live_voice.py

import asyncio
import base64
import json
import os

import sounddevice as sd
import websockets

RATE = 24000
CHANNELS = 1
BLOCK = 960


async def microphone_sender(ws, queue):
    loop = asyncio.get_running_loop()

    def on_audio(indata, frames, time, status):
        if status:
            print(f"microphone: {status}")
        pcm = bytes(indata)
        loop.call_soon_threadsafe(queue.put_nowait, pcm)

    with sd.RawInputStream(
        samplerate=RATE,
        channels=CHANNELS,
        dtype="int16",
        blocksize=BLOCK,
        callback=on_audio,
    ):
        while True:
            pcm = await queue.get()
            await ws.send(json.dumps({
                "type": "input_audio.append",  # Replace with the real event name.
                "audio": base64.b64encode(pcm).decode("ascii"),
            }))


async def response_receiver(ws):
    with sd.RawOutputStream(
        samplerate=RATE,
        channels=CHANNELS,
        dtype="int16",
        blocksize=BLOCK,
    ) as speaker:
        async for raw_message in ws:
            event = json.loads(raw_message)

            if event.get("type") == "output_audio.delta":
                speaker.write(base64.b64decode(event["audio"]))
            elif event.get("type") == "error":
                raise RuntimeError(event)


async def main():
    api_key = os.environ["OPENAI_API_KEY"]
    url = os.environ["GPT_LIVE_URL"]
    queue = asyncio.Queue(maxsize=50)

    async with websockets.connect(
        url,
        additional_headers={"Authorization": f"Bearer {api_key}"},
        max_size=None,
    ) as ws:
        # Replace fields and model identifier with the current API schema.
        await ws.send(json.dumps({
            "type": "session.configure",
            "model": "gpt-live-1",
            "instructions": (
                "你是技术支持坐席。使用简短中文回答;先确认问题,"
                "再给出一个可以立即执行的操作。不要猜测账户数据。"
            ),
            "audio": {
                "input_format": "pcm16",
                "output_format": "pcm16",
                "sample_rate": RATE,
                "voice": "YOUR_CONFIGURED_VOICE"
            }
        }))

        await asyncio.gather(
            microphone_sender(ws, queue),
            response_receiver(ws),
        )


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        pass

运行前需要确认实际 API 使用的采样率、编码格式、模型标识、事件名称和鉴权方式。生产环境还应给队列增加丢帧策略:当网络速度赶不上麦克风输入时,继续积压旧音频会制造越来越高的延迟,此时通常应丢弃过期帧并记录指标。

指令、声音和插话要作为一个整体设计

更强的指令遵循适合把业务约束直接放入会话配置,但指令应当可执行,而不是只描述性格。比如客服场景可以明确规定回答长度、身份验证边界、何时调用工具,以及哪些数据不得推测。

声音也不只是一个展示选项。使用自定义声音时,需要同时管理声音资产授权、适用地区、品牌一致性和滥用风险。不要仅靠声音模仿身份;涉及付款、账户修改或敏感信息时,仍应使用独立的身份验证步骤。

插话处理则需要客户端与服务端协作。可以这样实践:

  1. 本地或服务端检测到用户重新开口。
  2. 立刻清空尚未播放的扬声器缓冲区。
  3. 向实时会话发送取消当前响应的事件。
  4. 保存已经播放到用户耳中的位置,避免会话历史误以为整段回答都已被听到。
  5. 继续上传新音频,而不是重新建立连接。

取消事件及播放进度事件的具体名称应以实际 API 为准。这里最重要的工程原则是:中断属于会话状态的一部分,不能只在前端静音。

接入电话系统时增加一层媒体网关

电话网络通常使用与浏览器或桌面麦克风不同的音频编码和采样率。接入 GPT‑Live‑1 时,可以在电话供应商与模型 API 之间部署媒体网关,负责:

  • 将电话音频解码并转换成模型接受的输入格式。
  • 将模型输出重新采样、编码后发送到通话线路。
  • 映射开始、停止、静音、挂机和双音多频信号等事件。
  • 在用户插话时同时停止电话侧播放和模型侧生成。
  • 隔离 API 密钥,避免把长期凭据暴露给浏览器或电话供应商。

网关还应记录阶段性延迟,而不只是总耗时。至少区分首个输入音频到达、语音结束判定、首个输出音频产生和首包播放四个时间点,这样才能判断延迟来自网络、编解码、轮次检测还是模型生成。

上线前检查清单

适合优先采用 GPT‑Live‑1 的场景,是交互节奏本身具有价值的任务,例如电话客服、语言练习、无障碍界面和免手持操作。对于不需要打断、响应也不频繁的流程,普通的转写加文本模型链路可能更简单、更容易审计。

上线前应重点验证:

  • 弱网、丢包和网络切换时是否会无限积压音频。
  • 用户插话后,旧回答是否能在可接受时间内真正停止。
  • 自定义声音是否具备明确授权,并有版本和访问控制。
  • 工具调用和高风险操作是否经过服务端校验。
  • 电话场景是否满足录音告知、隐私和数据保留要求。
  • 日志是否避免保存不必要的原始音频和敏感转写。
  • 断线重连是否会重复执行工具或业务操作。

GPT‑Live‑1 提供了更自然的语音交互基础,但自然感最终来自完整链路:并发音频流、及时中断、清晰指令、合规的声音资产,以及能够量化的延迟与失败处理。


相关推荐