第七章: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交互,從數據存儲到語音轉錄,最終通過管理腳本實現系統整合。祝賀完成本教程體系!