[Meetily后端框架] Whisper转录服务器 | 后端服务管理脚本
第七章:Whisper转录服务器
欢迎回来!
到目前为止,我们已经深入探索了"meeting-minutes"项目的"大脑"——Python后端。
我们已经了解了它如何通过后端API网关接收文本转录,使用摘要数据结构(Pydantic模型)理解输出结构,通过巧妙的转录处理逻辑结合AI模型交互(Pydantic-AI代理)处理文本,并利用数据库管理保存所有内容。
但问题是,如果后端处理的是文本,那么最初的文本转录从何而来?特别是当原始输入是会议录音的音频文件时?
这就是Whisper转录服务器的用武之地~
Whisper转录服务器解决什么问题?
假设我们有一个会议的音频录音。在后端进行任何摘要提取或行动项提取之前,我们需要将语音转换为文字——即生成转录文本。
这种将音频转换为文本的任务称为**自动语音识别(ASR)**。这是一个需要专用模型的计算密集型过程。
我们的项目需要可靠的ASR执行方式。
虽然有些Python库可以实现此功能,但运行强大的ASR模型通常需要更接近硬件的编程语言(如C++
)。Whisper转录服务器正是为此而生。
可以将其想象成一个专用的高效速记员,专门负责监听音频文件(我们的会议录音)并快速提供文字转录。
Whisper转录服务器是什么?
本项目中的Whisper转录服务器是:
- 独立服务:作为独立程序运行,与主Python后端应用分离
- 基于
whisper.cpp
构建:这是OpenAI流行Whisper ASR模型的C++移植版本。C++常用于需要高性能的任务(如音频处理
和直接在计算机硬件CPU/GPU上运行机器学习模型
) - 专用工具:唯一职责是接收音频并返回文本,不涉及摘要生成、数据库操作或前端API处理
- 依赖项:虽然是独立服务,但主Python后端需要依赖此服务器来获取音频文件的转录文本
它会在后台静默运行,监听来自Python后端的请求。
工作原理(概述)
核心交互流程非常简单:
- Python后端(或其他客户端应用)持有音频文件
- 后端通过本地网络连接将
音频文件发送至运行的Whisper转录服务器
- Whisper服务器接收音频,加载适当的Whisper模型,
通过模型处理音频生成转录文本
- Whisper服务器将
生成的文本转录返回至后端
这清晰展示了服务器的专注角色:获取音频、使用模型文件、返回文本。
配置Whisper服务器
由于Whisper服务器是独立的C++程序,需要先进行编译构建。项目包含专门用于此的脚本:
backend/build_whisper.cmd
(适用于Windows)backend/build_whisper.sh
(适用于Linux/macOS)
这些脚本会下载必要的whisper.cpp
代码(作为git子模块),编译服务器可执行文件,并下载所需的Whisper模型文件。
编译可执行文件
脚本进入whisper.cpp
目录,使用cmake
和make
(常见的C++构建工具)来编译服务器代码:
# 摘自build_whisper.sh的简化片段
log_info "进入whisper.cpp目录..."
cd whisper.cpp || handle_error "进入目录失败"log_info "构建whisper.cpp..."
rm -rf build # 清理旧构建
mkdir build && cd build || handle_error "创建构建目录失败"log_info "配置CMake..."
cmake -DCMAKE_C_FLAGS="-w" -DCMAKE_CXX_FLAGS="-w" .. || handle_error "CMake配置失败"make -j4 || handle_error "编译失败" cd .. # 返回上级目录
log_success "构建成功完成"
说明:
进入whisper.cpp
目录,创建build
目录,运行cmake
根据CMakeLists.txt
文件配置构建过程,然后运行make
编译C++源码生成可执行文件(包括whisper-server
)。
下载模型
脚本还会下载特定的Whisper模型文件。这些文件包含ASR模型执行转录所需的数据(类似"速记员大脑"的数据)。文件名类似ggml-small.bin
、ggml-medium.bin
等,模型选择会影响转录速度和准确率。
# 摘自build_whisper.sh的简化片段
MODEL_NAME="ggml-$MODEL_SHORT_NAME.bin" # 例如ggml-small.bin# 检查模型是否存在,不存在则下载
if [ -f "$MODEL_DIR/$MODEL_NAME" ]; thenlog_success "模型文件存在:$MODEL_DIR/$MODEL_NAME"
elselog_warning "模型文件不存在:$MODEL_DIR/$MODEL_NAME"log_info "下载模型中..."# 调用专门下载模型的脚本./models/download-ggml-model.sh $MODEL_SHORT_NAME || handle_error "下载失败"# 移动下载的模型到正确目录mv "./models/$MODEL_NAME" "$MODEL_DIR/" || handle_error "移动模型失败"
fi
说明:
脚本根据用户选择的短名称(如small
)确定完整的模型文件名。检查文件是否存在,若不存在则通过download-ggml-model.sh
脚本下载,并移动到whisper-server-package
内的models
目录。
运行这些构建脚本后,将获得whisper-server
可执行文件和至少一个ggml-*.bin
模型文件。
运行Whisper服务器
与Python后端类似,Whisper服务器需要先运行才能接收请求。主启动脚本(clean_start_backend.sh
、start_with_output.ps1
)确保先启动Whisper服务器再启动Python后端。
脚本使用生成的whisper-server-package
目录中的辅助脚本来运行服务器:run-server.sh
或run-server.cmd
。
简化版的运行脚本示例:
#!/bin/bash# 默认配置
HOST="127.0.0.1" # 仅监听本地
PORT="8178" # 监听端口
MODEL="models/ggml-large-v3.bin" # 默认模型路径# ...(解析命令行参数如--model、--port、--host的逻辑)...# 运行服务器
./whisper-server \--model "$MODEL" \--host "$HOST" \--port "$PORT" \--diarize \--print-progress# 其他选项如--diarize启用说话人区分功能
说明:
此脚本执行编译后的whisper-server
程序,传递命令行参数:
--model
:指定加载的模型文件(.bin)--host
和--port
:设置监听地址和端口(默认127.0.0.1:8178
)--diarize
:启用说话人区分功能,识别音频中的不同说话者
运行主启动脚本(clean_start_backend.sh
)时,会执行此run-server.sh
脚本(通常在后台)来启动Whisper服务器。
Whisper服务器的API(/inference端点)
whisper.cpp
服务器暴露简单的HTTP API。后端主要使用/inference
端点来接收音频文件并返回转录文本。
根据whisper.cpp/examples/server/README.md
文件,可以使用curl
工具与该端点交互:
curl 127.0.0.1:8178/inference \
-H "Content-Type: multipart/form-data" \
-F file="@<文件路径>" \
-F response_format="json" \
-F language="en"
# ...其他参数选项...
说明:
curl 127.0.0.1:8178/inference
:服务器端点地址-H "Content-Type: multipart/form-data"
:表示发送包含文件的数据-F file="@<文件路径>"
:发送音频文件内容-F response_format="json"
:要求返回JSON格式结果-F language="en"
:提示音频语言
服务器处理音频文件后返回的JSON响应示例:
{"text": "这是测试录音。说话人一陈述内容。说话人二做出回复。"// ...可能包含分段、时间戳等信息...
}
其中的text
字段包含Python后端所需的关键转录文本。
⭕Whisper服务端(简化版)
查看C++代码(backend/whisper-custom/server/server.cpp
)了解/inference
端点处理流程:
// 简化版C++代码
int main(int argc, char ** argv) {// ...(参数解析和初始化)...// 加载Whisper模型struct whisper_context * ctx = whisper_init_from_file_with_params(params.model.c_str(), cparams);Server svr; // 创建HTTP服务器实例// 定义/inference端点处理svr.Post(sparams.request_path + sparams.inference_path, [&](const Request &req, Response &res){std::lock_guard<std::mutex> lock(whisper_mutex); // 线程安全锁// 1. 检查请求是否包含音频文件if (!req.has_file("file")) {res.set_content("{\"error\":\"缺少'file'字段\"}", "application/json");return;}auto audio_file = req.get_file_value("file"); // 获取文件内容// 2. 获取请求参数whisper_params current_params = params; // 使用默认参数get_req_parameters(req, current_params);// 3. 读取和处理音频数据std::vector<float> pcmf32; // 音频数据存储if (!::read_wav(audio_file.content, pcmf32, pcmf32s, current_params.diarize)) {res.set_content("{\"error\":\"读取WAV文件失败\"}", "application/json");return;}// 4. 运行转录模型whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY);if (whisper_full_parallel(ctx, wparams, pcmf32.data(), pcmf32.size(), current_params.n_processors) != 0) {res.set_content("{\"error\":\"处理音频失败\"}", "application/json");return;}// 5. 格式化输出std::string result_content;if (current_params.response_format == json_format) {json jres = json{ {"text", output_str(ctx, current_params, pcmf32s)} };result_content = jres.dump();res.set_content(result_content, "application/json");} // ...其他格式处理...});// 启动服务器监听svr.bind_to_port(sparams.hostname, sparams.port);svr.listen_after_bind();// 清理资源whisper_free(ctx);return 0;
}
使用Whisper语音识别模型构建的HTTP服务端程序,主要功能是接收音频文件
并返回文字转录结果
。
核心流程
初始化阶段
加载
预训练的Whisper语音识别模型创建
HTTP服务器实例准备接收请求
请求处理阶段
检查
请求合法性:验证是否包含音频文件字段参数
获取:读取客户端提交的转录参数(如语言、响应格式等)- 音频
预处理
:将上传的WAV文件解码为模型需要的PCM格式 - 语音识别:调用Whisper模型进行并行转录计算
结果格式化
:将识别结果转换为JSON等指定格式返回
终止阶段
- 释放模型内存
- 关闭服务器
关键技术点
- 线程安全机制:通过
lock_guard
确保多线程安全 - 错误处理:对每个关键步骤进行错误检测并返回JSON格式错误信息
参数可配置
:支持运行时调整转录参数- 多格式输出:默认支持JSON响应格式
数据流向
客户端音频文件 → HTTP请求 → WAV解码
→ Whisper模型 → 文本结果 → JSON响应 → 客户端
流程复述:
- 初始化时加载Whisper模型
- 配置HTTP服务器并定义POST请求处理
- 检查请求有效性并获取音频文件
- 读取音频数据到内存缓冲区
- 调用
whisper_full_parallel
执行语音识别 - 根据请求格式生成响应内容
- 启动监听循环处理请求
lock_guard
的作用
lock_guard
是C++中的一种工具,它在构造时自动加锁,析构时自动解锁,确保多线程下某段代码不会被多个线程同时执行。
WAV解码
将WAV音频文件的二进制数据
转换成可以播放的声音信号
。
要点
- **Whisper转录服务器**是基于C++(
whisper.cpp
)构建的高性能独立服务
,用于音频转文本 - 是Python后端处理音频输入时的必要依赖
- 运行时需要加载特定的Whisper模型文件(.bin)
- 项目包含构建脚本编译服务器和下载模型,以及**运行脚本**启动服务
- 暴露HTTP API(主要使用
/inference
端点)接收音频并返回转录文本 - 内部使用
whisper.cpp
库函数进行模型加载、音频读取、转录执行和输出格式化
理解Whisper转录服务器可以明确音频输入的文本转录来源,完善后端处理流程的数据源头。
下一步
我们已经覆盖了meeting-minutes
后端的主要组件及其关键依赖——Whisper转录服务器。
我们已经了解后端如何处理文本,以及音频如何被转换为文本。但这些独立组件(Python后端和Whisper服务器)如何作为整体系统启动和管理?
在最终章,我们将介绍后端服务管理脚本,通过简单命令即可构建、启动和停止所有必要服务。
第八章:后端服务管理脚本
第八章:后端服务管理脚本
欢迎来到meeting-minutes
后端教程的最终章!
我们已经涵盖了诸多内容:从前端入口(第一章:后端API网关)及其文档(第二章:API文档),到数据结构(第三章:摘要数据结构(Pydantic模型))、核心处理逻辑(第四章:转录处理逻辑)及其与AI模型的交互(第五章:AI模型交互(Pydantic-AI代理)),再到数据保存(第六章:数据库管理),最后是通过专用章节第七章:Whisper转录服务器实现音频到文本的转换。
我们现在已经了解,后端系统并非单一程序,而是由至少两个需要持续运行的主要部分构成:
- Python后端应用:包含
API网关
、文本处理逻辑
和数据库管理
的主体部分 - Whisper转录服务器:实现
音频转文本
的独立程序
手动按正确顺序
启动这些组件、确保端口监听正确
、可能需要清理旧进程
等操作,对初学者而言既繁琐又容易出错。
服务管理脚本解决什么问题?
想象我们正在发射火箭(我们的后端系统),需要:
- 确保所有必要部件已就绪(如Whisper服务器可执行文件)
- 清理发射场(终止旧服务进程)
- 启动引擎(Whisper服务器)
- 激活主火箭系统并确保通信正常(Python后端连接Whisper服务器)
后端服务管理脚本将此流程自动化。这些简单的命令行文件(Linux/macOS用.sh
,Windows用.cmd
)将必要步骤封装成单一命令,如同自动化发射序列或后端服务控制面板。
核心管理脚本
backend/
目录包含关键脚本:
build_whisper.sh
/build_whisper.cmd
:构建C++版Whisper服务器及下载模型(初始化或更新后使用)clean_start_backend.sh
/clean_start_backend.cmd
:主启动脚本(终止旧实例并启动Whisper与Python后端)check_status.cmd
(Windows专用,Linux/macOS可用ps
和lsof
):查看服务运行状态start_with_output.ps1
(Windows PowerShell脚本,由start_with_output.cmd
调用):调试时在新窗口显示输出
我们重点解析构建与启动相关的核心脚本。
构建Whisper服务器(build_whisper)
如第七章所述,该脚本负责编译C++源码。执行backend/build_whisper.sh
或.cmd
时执行以下关键步骤:
-
更新Git子模块:
git submodule update --init --recursive
:: Windows版 git submodule update --init --recursive
说明:获取
whisper.cpp
项目代码至backend/whisper.cpp
-
部署定制服务文件:
cp -r ../whisper-custom/server/* "examples/server/"
xcopy /E /Y /I ..\whisper-custom\server examples\server\
说明:使用项目定制版服务端代码覆盖默认实现
-
执行C++编译:
cd whisper.cpp/build cmake .. make -j4
cd whisper.cpp\build cmake .. -DBUILD_SHARED_LIBS=OFF -DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_SERVER=ON cmake --build . --config Release
说明:生成
whisper-server
可执行文件 -
下载语音模型:
./models/download-ggml-model.sh $MODEL_SHORT_NAME mv "./models/$MODEL_NAME" "$PACKAGE_DIR/models/"
call download-ggml-model.cmd %MODEL_SHORT_NAME% move "whisper.cpp\models\%MODEL_NAME%" "%PACKAGE_DIR%\models\"
说明:获取Whisper服务器所需的
.bin
模型文件 -
文件打包:
mkdir -p "$PACKAGE_DIR/models" cp build/bin/whisper-server "$PACKAGE_DIR/" cp "$MODEL_DIR/$MODEL_NAME" "$PACKAGE_DIR/models/"
mkdir "%PACKAGE_NAME%" mkdir "%PACKAGE_NAME%\models" copy "whisper.cpp\build\bin\Release\whisper-server.exe" "%PACKAGE_NAME%\" copy "whisper.cpp\models\%MODEL_NAME%" "%PACKAGE_NAME%\models\"
说明:将运行所需文件集中至
whisper-server-package
目录 -
配置Python环境:
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt
python -m venv venv call venv\Scripts\activate.bat pip install -r requirements.txt
说明:创建Python虚拟环境并安装依赖
构建脚本只需执行一次即可完成环境准备。
启动后端(clean_start_backend)
最常用脚本,执行backend/clean_start_backend.sh
或.cmd
时工作流程:
-
清理旧进程:
pkill -f "whisper-server" 2>/dev/null
taskkill /F /FI "IMAGENAME eq whisper-server.exe" 2>nul
说明:终止占用端口5167和8178的旧进程
-
启动Whisper服务:
cd "$PACKAGE_NAME" ./run-server.sh --model "models/$MODEL_NAME" & WHISPER_PID=$! cd ..
cd "%PACKAGE_NAME%" start "Whisper Server" cmd /k "whisper-server.exe --model models\%MODEL_NAME% --host 127.0.0.1 --port 8178 --diarize --print-progress" cd ..
说明:后台启动语音识别服务
-
服务启动等待:
sleep 2
timeout /t 5 >nul
说明:确保语音服务就绪后再启动后端
-
激活Python环境:
source venv/bin/activate
call venv\Scripts\activate.bat
-
启动Python后端:
python app/main.py & PYTHON_PID=$!
start "Python Backend" cmd /k "call venv\Scripts\activate.bat && python app\main.py"
-
状态验证:
sleep 10 lsof -i :8178 lsof -i :5167
timeout /t 10 >nul netstat -ano | findstr :8178 netstat -ano | findstr :5167
后端启动流程示意图:
辅助脚本
check_status.cmd
:Windows环境服务状态检查(进程与端口监听)start_with_output
系列:在新窗口启动服务实时显示日志(调试专用)
脚本化管理的优势
优势项 | 说明 |
---|---|
操作简便 | 单命令启动复杂系统 |
可靠性增强 | 确保服务启动顺序正确并清理残留进程 |
流程自动化 | 自动处理编译和环境配置等重复性工作 |
环境一致性 | 提供跨平台的标准化操作流程 |
故障排查 | 状态检查脚本和输出窗口便于问题诊断 |
总结
本章解析了后端服务管理脚本的核心价值:通过build_whisper
实现环境准备,借助clean_start_backend
实现服务启动自动化。
这些脚本作为控制面板,隐藏了多进程管理的复杂性,确保系统可靠启动。
至此我们已完成meeting-minutes
后端核心概念的全栈解析,从API入口到AI交互,从数据存储到语音转录,最终通过管理脚本实现系统整合。祝贺完成本教程体系!