Gradio Agents & MCP 黑客马拉松

获奖者
Gradio logo
  1. 流媒体
  2. 实时语音识别

实时语音识别

简介

自动语音识别(ASR),即将口语转换为文本,是机器学习领域一个非常重要且蓬勃发展的方向。ASR 算法在几乎每部智能手机上都在运行,并且越来越多地嵌入到专业工作流程中,例如用于护士和医生的数字助理。由于 ASR 算法旨在供客户和最终用户直接使用,因此在面对各种语音模式(不同口音、音高和背景音频条件)时,验证它们是否按预期运行非常重要。

使用 gradio,你可以轻松构建 ASR 模型的演示,并与测试团队共享,或通过设备上的麦克风自行测试。

本教程将展示如何获取预训练的语音转文本模型并将其部署到 Gradio 界面。我们将从一个**全上下文**模型开始,用户在运行预测之前说完整个音频。然后,我们将修改演示,使其变为**流式传输**,这意味着音频模型将在你说话时实时转换语音。

先决条件

请确保你已安装 gradio Python 包。你还需要一个预训练的语音识别模型。在本教程中,我们将使用来自 whisper 模型的预训练 ASR 模型。

  • Transformers (为此,请 pip install torch transformers torchaudio)

请确保你至少安装了其中一个,以便能跟着教程进行操作。如果你尚未安装,还需要在系统上安装 ffmpeg,以便处理麦克风文件。

以下是构建实时语音识别(ASR)应用的方法:

  1. 设置 Transformers ASR 模型
  2. 使用 Transformers 创建全上下文 ASR 演示
  3. 使用 Transformers 创建流式 ASR 演示

1. 设置 Transformers ASR 模型

首先,你需要一个你自己训练过的 ASR 模型,或者你需要下载一个预训练模型。在本教程中,我们将从使用 whisper 模型的预训练 ASR 模型开始。

这是从 Hugging Face transformers 加载 whisper 的代码。

from transformers import pipeline

p = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")

就这样!

2. 使用 Transformers 创建全上下文 ASR 演示

我们将从创建一个**全上下文** ASR 演示开始,用户在运行 ASR 模型进行推理之前,会说完完整的音频。这在 Gradio 中非常容易——我们只需在上面创建的 pipeline 对象周围创建一个函数。

我们将使用 gradio 内置的 Audio 组件,它被配置为从用户麦克风获取输入并返回录制音频的文件路径。输出组件将是一个普通的 Textbox

import gradio as gr
from transformers import pipeline
import numpy as np

transcriber = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")

def transcribe(audio):
    sr, y = audio
    
    # Convert to mono if stereo
    if y.ndim > 1:
        y = y.mean(axis=1)
        
    y = y.astype(np.float32)
    y /= np.max(np.abs(y))

    return transcriber({"sampling_rate": sr, "raw": y})["text"]  

demo = gr.Interface(
    transcribe,
    gr.Audio(sources="microphone"),
    "text",
)

demo.launch()

transcribe 函数接受一个参数 audio,它是一个用户录制的音频的 numpy 数组。pipeline 对象期望这是 float32 格式,所以我们首先将其转换为 float32,然后提取转录文本。

3. 使用 Transformers 创建流式 ASR 演示

为了将其制作成流式演示,我们需要进行以下更改:

  1. Audio 组件中设置 streaming=True
  2. Interface 中设置 live=True
  3. 为界面添加一个 state 以存储用户录制的音频

    提示: 你还可以在界面中设置 `time_limit` 和 `stream_every` 参数。`time_limit` 限制了每个用户流可以持续的时间,默认为 30 秒,因此用户无法流式传输超过 30 秒的音频。`stream_every` 参数控制数据发送到你的函数的频率,默认为 0.5 秒。

请看下方。

import gradio as gr
from transformers import pipeline
import numpy as np

transcriber = pipeline("automatic-speech-recognition", model="openai/whisper-base.en")

def transcribe(stream, new_chunk):
    sr, y = new_chunk
    
    # Convert to mono if stereo
    if y.ndim > 1:
        y = y.mean(axis=1)
        
    y = y.astype(np.float32)
    y /= np.max(np.abs(y))

    if stream is not None:
        stream = np.concatenate([stream, y])
    else:
        stream = y
    return stream, transcriber({"sampling_rate": sr, "raw": stream})["text"]  

demo = gr.Interface(
    transcribe,
    ["state", gr.Audio(sources=["microphone"], streaming=True)],
    ["state", "text"],
    live=True,
)

demo.launch()

请注意,我们现在有一个状态变量,因为我们需要跟踪所有音频历史记录。transcribe 在有新的小音频块时会被调用,但我们也需要跟踪到目前为止所有已说出的音频状态。当界面运行时,transcribe 函数会被调用,其中包含 stream 中所有以前说过的音频记录和 new_chunk 中的新音频片段。我们将新的完整音频返回以存储回其当前状态,并且我们还返回转录文本。在这里,我们简单地将音频拼接在一起,并在整个音频上调用 transcriber 对象。你可以想象更有效率的处理方式,例如每当收到新的音频片段时,只重新处理最后 5 秒的音频。

现在 ASR 模型将在你说话时运行推理!