体验 Whisper ,本地离线部署自己的 ASR 语音识别服务

需求背景

最近看视频,过几天后经常忘记内容,所以有了把重点内容总结提炼到自己知识库的需求,这涉及到了提取视频中的音频数据、离线语音识别等功能。

提取视频中的音频数据,可以使用格式工厂或 FFmpeg 等工具, FFmpeg 可以使用命令 ffmpeg -i test.mp4 -f mp3 -vn test.mp3 将视频文件转换为 MP3 格式的音频文件,其中,-i test.mp4-i 参数指定输入文件,这里的输入文件是 test.mp4-f mp3-f 参数用于指定输出文件的格式,这里指定为 mp3 格式。-vn:这个参数告诉 FFmpeg 在处理文件时忽略视频流,即不处理视频数据,只处理音频数据。test.mp3:指定了输出文件的名称,即转换后的音频文件将被保存为当前目录下的 test.mp3

Whisper 是由 OpenAI 创建的开源通用语音识别项目,是一个经过大量的音频数据训练出来的支持多任务处理的语言识别模型。项目的 GitHub 仓库地址是 OpenAI Whisper ,在仓库介绍的 Show and tell 中发现这个项目 whisper-asr-webservice ,它在 whisper 基础上提供了 web 界面,并且可以用 docker 部署。

下面基于开源项目,体验了本地离线部署自己的 ASR 语音识别服务的过程。

镜像构建

克隆 whisper-asr-webservice 仓库到本地,切换到稳定版本,

git clone https://github.com/ahmetoner/whisper-asr-webservice.git
cd whisper-asr-webservice
git checkout v1.3.0

进入仓库目录,分析 Dockerfile.gpu 文件内容,这个 Dockerfile 使用了多阶段构建,

# 第一阶段:构建 FFmpeg
# 使用 Debian bookworm slim 版本作为基础镜像来构建 FFmpeg
FROM debian:bookworm-slim AS ffmpeg
# 安装 FFmpeg 编译所需的依赖包
RUN export DEBIAN_FRONTEND=noninteractive \
    && apt-get -qq update \
    && apt-get -qq install --no-install-recommends \
    build-essential \
    git \
    pkg-config \
    yasm \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*
# 从 GitHub 克隆特定版本的 FFmpeg 源码
RUN git clone https://github.com/FFmpeg/FFmpeg.git --depth 1 --branch n6.1.1 --single-branch /FFmpeg-6.1.1
# 设置工作目录为 FFmpeg 源代码目录
WORKDIR /FFmpeg-6.1.1
# 配置 FFmpeg 编译选项,禁用不需要的功能,以优化最终构建
RUN PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \
      --prefix="$HOME/ffmpeg_build" \
      --pkg-config-flags="--static" \
      --extra-cflags="-I$HOME/ffmpeg_build/include" \
      --extra-ldflags="-L$HOME/ffmpeg_build/lib" \
      --extra-libs="-lpthread -lm" \
      --ld="g++" \
      --bindir="$HOME/bin" \
      --disable-doc \
      --disable-htmlpages \
      --disable-podpages \
      --disable-txtpages \
      --disable-network \
      --disable-autodetect \
      --disable-hwaccels \
      --disable-ffprobe \
      --disable-ffplay \
      --enable-filter=copy \
      --enable-protocol=file \
      --enable-small && \
    PATH="$HOME/bin:$PATH" make -j$(nproc) && \
    make install && \
    hash -r

# 第二阶段:准备 Swagger UI
# 使用 swagger-ui 镜像作为基础来提供 API 文档界面
FROM swaggerapi/swagger-ui:v5.9.1 AS swagger-ui

# 第三阶段:应用程序与 FFmpeg 集成
# 使用 NVIDIA CUDA 基础镜像,准备 Python 环境
FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04
# 设置 Python 版本和 poetry 虚拟环境路径
ENV PYTHON_VERSION=3.10
ENV POETRY_VENV=/app/.venv
# 安装 Python 和 pip
RUN export DEBIAN_FRONTEND=noninteractive \
    && apt-get -qq update \
    && apt-get -qq install --no-install-recommends \
    python${PYTHON_VERSION} \
    python${PYTHON_VERSION}-venv \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*
# 创建软链接以确保 python 和 pip 命令指向正确的版本
RUN ln -s -f /usr/bin/python${PYTHON_VERSION} /usr/bin/python3 && \
    ln -s -f /usr/bin/python${PYTHON_VERSION} /usr/bin/python && \
    ln -s -f /usr/bin/pip3 /usr/bin/pip
# 创建并配置 Python 虚拟环境
RUN python3 -m venv $POETRY_VENV \
    && $POETRY_VENV/bin/pip install -U pip setuptools \
    && $POETRY_VENV/bin/pip install poetry==1.6.1
# 添加 poetry 虚拟环境到 PATH
ENV PATH="${PATH}:${POETRY_VENV}/bin"
# 设置工作目录并复制项目依赖文件
WORKDIR /app

COPY poetry.lock pyproject.toml ./
# 配置 poetry 并安装项目依赖
RUN poetry config virtualenvs.in-project true
RUN poetry install --no-root
# 复制项目文件和依赖
COPY . .
COPY --from=ffmpeg /FFmpeg-6.1.1 /FFmpeg-6.1.1
COPY --from=ffmpeg /root/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=swagger-ui /usr/share/nginx/html/swagger-ui.css swagger-ui-assets/swagger-ui.css
COPY --from=swagger-ui /usr/share/nginx/html/swagger-ui-bundle.js swagger-ui-assets/swagger-ui-bundle.js
# 再次运行 poetry 安装以确保所有依赖都已安装
RUN poetry install
# 安装 PyTorch
RUN $POETRY_VENV/bin/pip install torch==1.13.0+cu117 -f https://download.pytorch.org/whl/torch
# 暴露服务端口
EXPOSE 9000
# 定义容器启动时执行的命令
CMD gunicorn --bind 0.0.0.0:9000 --workers 1 --timeout 0 app.webservice:app -k uvicorn.workers.UvicornWorker

第一阶段:构建 FFmpeg

  1. FROM debian:bookworm-slim AS ffmpeg:使用 debian:bookworm-slim 作为基础镜像开始第一个构建阶段,并命名这个阶段为 ffmpeg

  2. 安装构建依赖:

    • RUN export DEBIAN_FRONTEND=noninteractive:设置环境变量,使 apt-get 在非交互模式下运行,避免安装过程中的提示。
    • apt-get -qq update:更新包列表,-qq 选项让更新过程尽可能静默。
    • apt-get -qq install --no-install-recommends:安装必要的包,不安装推荐的依赖包以减少镜像大小。
    • 包括 build-essentialgitpkg-configyasmca-certificates:这些都是编译 FFmpeg 所需的工具和库。
    • rm -rf /var/lib/apt/lists/*:清理 apt 缓存以减小镜像大小。
  3. RUN git clone https://github.com/FFmpeg/FFmpeg.git --depth 1 --branch n6.1.1 --single-branch /FFmpeg-6.1.1:从 GitHub 克隆 FFmpeg 仓库的特定分支(n6.1.1),使用 --depth 1 进行浅克隆以减少下载的数据量。

  4. WORKDIR /FFmpeg-6.1.1:将工作目录切换到 FFmpeg 源码目录。

  5. 编译安装 FFmpeg:

    • 设置编译配置,禁用了一些不需要的功能以缩小最终安装的大小,并优化为静态链接。
    • 使用 make -j$(nproc) 并行编译 FFmpeg,以加速编译过程。
    • make install 将编译好的程序安装到指定目录。
    • hash -r 刷新 shell 的命令缓存。

第二阶段:准备 Swagger UI

  1. FROM swaggerapi/swagger-ui:v5.9.1 AS swagger-ui:这是一个新的阶段,使用 Swagger UI 的官方镜像作为基础,用于提供 API 文档界面。

第三阶段:应用程序与 FFmpeg 集成

  1. FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04:这是最终构建阶段的基础镜像,使用 NVIDIA CUDA 的镜像来支持 GPU 加速。这意味着基础镜像是 nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04,而不是 debian:bookworm-slim

  2. 安装 Python 环境和依赖:

    • 类似于第一阶段,设置非交互模式,更新包列表,并安装 Python 以及相关工具。
    • 创建和配置 Python 虚拟环境,安装 Poetry 作为依赖管理工具。
  3. 配置工作目录 /app 并安装 Python 依赖。

  4. 从之前的阶段复制必要的文件和目录到当前镜像中,包括 FFmpeg 可执行文件和 Swagger UI 静态文件。

  5. 安装额外的 Python 依赖,包括 PyTorch。

  6. 配置容器启动时运行的命令,使用 gunicorn 启动 Web 服务。

修改 Dockerfile

针对本地机器环境,修改 Dockerfile 文件内容,
- 本地机器环境,输入命令 nvidia-smi 查询显卡驱动信息,当前 Nvidia 驱动版本为 515.48.07 ,CUDA 版本最高可以支持到 11.7 ,whisper-asr-webservice 仓库 v1.3.0 版本原来的 Dockerfile 文件使用的基础镜像为 nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04 ,修改为 nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu22.04
- 在构建的镜像中包含 net-toolscurlwgetvimiputils-ping 等工具,方便容器启动后的开发调试。

修改后的例子如下,

# 修改的部分
FROM nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu22.04

# 未修改的部分
ENV PYTHON_VERSION=3.10
ENV POETRY_VENV=/app/.venv

# 修改的部分
RUN export DEBIAN_FRONTEND=noninteractive \
    && apt-get -qq update \
    && apt-get -qq install --no-install-recommends \
    python${PYTHON_VERSION} \
    python${PYTHON_VERSION}-venv \
    python3-pip \
    # ----- add software begin -----
    curl \
    wget \
    vim \
    net-tools \
    iputils-ping \
    # ----- add software end -----
    && rm -rf /var/lib/apt/lists/*

# 剩下的部分保持不变
# ...

修改 Dockerfile 后,需要重新构建镜像。

docker build -f Dockerfile.gpu -t whisper-asr-webservice-gpu:v1.3.0 .

镜像部署

docker save -o whisper_asr_webservice_gpu_v1.3.0.tar whisper-asr-webservice-gpu:v1.3.0
docker load --input whisper_asr_webservice_gpu_v1.3.0.tar
docker tag <IMAGE ID> whisper_asr_webservice_gpu:v1.3.0
docker run -d --gpus '"device=0"' -p 9000:9000 -e ASR_MODEL=base -e ASR_ENGINE=openai_whisper -e ASR_MODEL_PATH=/data/whisper -v /data/whisper:/data/whisper whisper_asr_webservice_gpu:v1.3.0

观察容器日志,

[2024-04-06 06:38:59 +0000] [27] [INFO] Starting gunicorn 21.2.0
[2024-04-06 06:38:59 +0000] [27] [INFO] Listening at: http://127.0.0.1:9000 (27)
[2024-04-06 06:38:59 +0000] [27] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2024-04-06 06:38:59 +0000] [28] [INFO] Booting worker with pid: 28
OpenBLAS blas_thread_init: pthread_create failed for thread 1 of 64: Operation not permitted
OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max
[2024-04-06 06:38:59 +0000] [27] [ERROR] Worker (pid:28) was sent SIGINT!
[2024-04-06 06:38:59 +0000] [29] [INFO] Booting worker with pid: 29
OpenBLAS blas_thread_init: pthread_create failed for thread 1 of 64: Operation not permitted
OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max
[2024-04-06 06:38:59 +0000] [27] [ERROR] Worker (pid:29) was sent SIGINT!

结合 GPT 给出的排查步骤逐步验证,发现容器中的进程(例如 OpenBLAS 创建的线程)可能因为 Docker 的安全性配置(特别是 seccomp 默认策略)而受到限制,导致操作被禁止。尝试使用更宽松的安全选项启动容器,例如 --security-opt seccomp=unconfined--privileged。这些选项会降低容器的安全性,因此最好分析和定制 Seccomp 策略。

再次观察容器日志,成功启动了容器服务。

[2024-04-06 06:50:26 +0000] [27] [INFO] Starting gunicorn 21.2.0
[2024-04-06 06:50:26 +0000] [27] [INFO] Listening at: http://127.0.0.1:9000 (27)
[2024-04-06 06:50:26 +0000] [27] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2024-04-06 06:50:26 +0000] [28] [INFO] Booting worker with pid: 28
[2024-04-06 06:50:30 +0000] [28] [INFO] Started server process [28]
[2024-04-06 06:50:30 +0000] [28] [INFO] Waiting for application startup.
[2024-04-06 06:50:30 +0000] [28] [INFO] Application startup complete.

验证使用

这个项目提供了 2 个接口:

  • /asr ,自动语音识别,上传语音或视频文件,输出文本。
  • /detect-language ,检测语言,检测上传文件中使用的语言。仅处理前 30 秒。

自动语音识别服务 /asr

  • encode: 识别之前通过 FFmpeg 编码音视频文件。
  • task: transcribe ,(默认)任务,转写上传的文件,中文语音识别为中文文字,英文语音识别为英文文字;translate ,无论源文件中是什么语言,识别后翻译为英文再输出。
  • language: 告诉接口源文件是什么语言,可不指定,可以自动识别出来,如果指定错了,输出的结果是不对的。
  • initial_prompt: prompt 工程可以提高语音识别结果的准确性。
  • word_timestamps: 单词级别的时间戳,在输出为 json 时起作用,可输出每个单词的开始时间、结束时间、识别正确的可能性。
  • output: 输出格式。
  • 可以启用语音活动检测(VAD),通过参数 vad_filter 过滤掉没有语音的音频部分(目前仅支持 Faster Whisper)。

请求 URL 查询参数如下:

NameValues
audio_fileFile
encodetrue (default)
tasktranscribe, translate
languageen (default is auto recognition)
initial_promptprompt
word_timestampsfalse (default)
outputtext (default), json, vtt, srtt, tsv

使用 curl 的示例请求,

curl -X POST -H "content-type: multipart/form-data" -F "audio_file=@test.mp3" http://127.0.0.1:9000/asr?output=json

响应(JSON),

  • text :包含完整的文字记录
  • segments :每个分段包含一个条目。每个条目提供 timestampstranscripttoken idsword leveltimestamps、其他元数据
  • language :检测到或提供的语言(as a language code)

语言检测服务 /detect-language

检测上传文件中使用的语言,仅处理前 30 秒。返回包含以下字段的 json:

  • detected_language: “english”
  • language_code: “en”

使用 curl 的示例请求,

curl -X POST -H "content-type: multipart/form-data" -F "audio_file=@test.mp3" http://127.0.0.1:9000/detect-language
{"detected_language":"chinese","language_code":"zh"}

针对标点符号,和中英文混杂的情况,可以加入 prompt 提升识别的准确率:‘这是一段中文、英文混合的录音,输出请记得加标点符号。’

curl -X POST -H "content-type: multipart/form-data" -F "initial_prompt="这是一段中文、英文混合的录音,输出请记得加标点符号。"" -F "audio_file=@test.mp3" http://127.0.0.9:9000/asr > test.txt

base 模型对短音频的识别效果不错,一般模型越大,识别效果越好。

在看解决方案的过程中,我还发现一个好玩的语音日记应用 Alog ,只需要在想说话的时候,用它录音就行了,它会自动帮你把语音转化为文字,然后同时保存在手机里,转写服务支持 iOS 系统自带或者 Whisper ,自带的仅限于 1 分钟的音频时长。还可以开启 AI 总结功能,自定义提示词,对转写内容总结,输出一份标准日记。


微信公众号「padluo」,分享数据科学家的自我修养,既然遇见,不如一起成长。关注【数据分析】公众号,后台回复【文章】,获得整理好的【数据分析】文章全集。

数据分析二维码.gif

<think>好的,我现在需要回答用户关于语音识别技术基本概念的问题。用户之前已经询问过光符号识别技术(OCR),现在转向语音识别,可能是在比较不同识别技术或者想了解相关领域。首先,我需要明确用户的需求,确保回答的结构和内容符合他们的预期。 首先,我需要回忆语音识别技术的基本概念,包括定义、关键组成部分、技术流程、应用场景等。可能需要分点来阐述,保持与之前OCR回答的结构一致,便于用户对比。同时,用户可能对技术原理感兴趣,但作为基本概念,不需要太深入的技术细节,但需要涵盖主要步骤和关键技术。 接下来,要确保使用中文回答,并且按照用户的要求,使用正确的LaTeX格式,特别是行内公式要用$...$,独立公式用$$...$$。例如,在提到MFCC时可能需要公式,或者声学模型中的概率计算。 同时,要注意用户可能对技术演进、应用场景和挑战感兴趣,需要包含这些部分。另外,用户之前的OCR回答中有历史演进、技术原理分步、应用案例表格等,可以借鉴类似结构,但要根据语音识别的特点调整。 需要检查是否有遗漏的关键点,比如语音识别中的预处理、特征提取、声学模型、语言模型、解码器等组成部分。另外,还要提到当前的挑战,如噪声环境、口音、多语种支持等,以及主流的工具和框架,如Kaldi、DeepSpeech等,可能用户需要这些信息作为参考。 还要注意避免技术术语过于复杂,保持解释的易懂性。比如,解释声学模型时,可以提到它如何将声音信号转化为音素或字词,而语言模型则处理上下文关系。同时,结合应用实例,如智能助手、语音输入法等,让用户更容易理解。 最后,确保回答结构清晰,分点明确,使用适当的标题和子标题,可能用项目符号或表格来组织内容。检查LaTeX格式是否正确,比如声学模型中的概率公式是否用$...$包裹,或者MFCC的计算步骤是否需要独立公式。 总结,我需要组织以下内容: 1. 定义和概述 2. 核心组成部分(预处理、特征提取、声学模型、语言模型、解码) 3. 技术流程步骤 4. 关键技术(如HMM、DNN、端到端模型) 5. 应用场景 6. 技术挑战 7. 常用工具和框架 确保每个部分简明扼要,符合用户之前获得的OCR回答的结构,同时突出语音识别的独特之处,如实时性、环境噪声的影响等。另外,可能需要提到最新的趋势,如端到端模型、多语种支持、低资源语言处理等,展示技术的前沿发展。</think>### **一、基本定义** 语音识别技术(ASR,Automatic Speech Recognition)是将人类语音信号转换为计算机可读文本的核心技术,其本质是**声学信号到语义符号的映射**。例如: - 手机语音助手(如Siri、小爱同学) - 会议实时字幕生成 - 语音输入法(微信语音转文字) --- ### **二、核心组成部分** 1. **预处理** - 分帧加窗:将连续语音切分为20-40ms的短帧(公式:$x[n] \cdot w[n]$,常用汉明窗) - 降噪:抑制环境噪声(如谱减法、维纳滤波) 2. **特征提取** - **MFCC(梅尔频率倒谱系数)**: 1. 傅里叶变换获取频谱 2. 梅尔滤波器组滤波(模拟人耳听觉特性) 3. 取对数后做DCT变换(公式:$c_n = \sum_{k=1}^{K} \log{E_k} \cdot \cos\left[\frac{\pi n}{K}\left(k-\frac{1}{2}\right)\right]$) - 其他特征:FBANK(滤波器组能量)、PLP(感知线性预测) 3. **声学模型** - **传统方法**:GMM-HMM(高斯混合模型+隐马尔可夫模型) - HMM状态对应音素(如汉语拼音的声母/韵母) - 输出概率:$P(o_t|s_i) = \sum_{m=1}^{M} w_{i,m} \mathcal{N}(o_t; \mu_{i,m}, \Sigma_{i,m}})$ - **深度学习方法**: - DNN-HMM(深度神经网络替代GMM) - 端到端模型(如CTC、RNN-T、Transformer) 4. **语言模型** - **N-gram**:基于统计的上下文预测(如$P(w_i|w_{i-1},w_{i-2})$) - **神经网络语言模型**:BERT、GPT等预训练模型提升长距离依赖建模 5. **解码器** - 动态搜索最优路径(如Viterbi算法、束搜索) - 联合优化声学与语言模型得分(公式:$\arg\max_W P(A|W)P(W)$) --- ### **三、技术流程示例** 以“打开空调”指令为例: 1. 麦克风采集音频 → 2. 降噪后提取MFCC → 3. 声学模型输出音素序列 → 4. 语言模型修正为“打开空调” → 5. 触发智能家居控制 --- ### **四、关键技术挑战** | 问题类型 | 具体表现 | 解决方法 | |----------------|---------------------------------------|-----------------------------------| | **环境噪声** | 车载场景信噪比<5dB时错误率上升50% | 多麦克风阵列波束成形 | | **说话人差异** | 方言识别率比普通话低30% | 方言语音数据增强 | | **重叠语音** | 多人同时说话导致字错误率>80% | 说话人分离(如TasNet) | | **低资源语言** | 藏语等语种标注数据不足100小时 | 迁移学习+无监督预训练 | --- ### **五、主流工具与框架** - **Kaldi**:基于HMM的传统ASR工具链(支持WFST解码) - **ESPnet**:端到端语音识别框架(集成Transformer、Conformer) - **DeepSpeech**:基于RNN-T的开源模型(百度DeepSpeech2中文WER 12.7%) - **商用API**:Azure Speech-to-Text(支持100+语种实时转写) --- ### **六、发展趋势** 1. **端到端模型**:简化传统流水线(如Google的LAS模型) 2. **多模态融合**:结合唇动特征提升噪声鲁棒性 3. **边缘计算**:在手机端实现离线识别(如TensorFlow Lite部署) 4. **个性化适配**:少量样本微调模型适应用户口音 当前最先进系统(如Whisper)在LibriSpeech测试集上词错误率(WER)已低于3%,接近人类水平。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值