1. 流式传输
  2. 实时语音识别

实时语音识别

简介

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

使用 gradio,您可以轻松构建 ASR 模型的演示,并将其分享给测试团队,或者通过设备上的麦克风自行测试。

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

先决条件

确保您已经[安装](/getting_started)了 gradio Python 包。您还需要一个预训练的语音识别模型。在本教程中,我们将使用 2 个 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",
    api_name="predict",
)

demo.launch()

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

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

要使其成为*流式*演示,我们需要进行以下更改:

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

    您还可以在界面中设置 time_limitstream_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,
    api_name="predict"
)

demo.launch()

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

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

gradio