# rust-scribe `rust-scribe` 是一個高效能的影片/音頻逐字稿轉寫工具,使用 Rust 語言編寫,並結合了 [Whisper.cpp](https://github.com/ggerganov/whisper.cpp) 的強大轉寫能力與 [FFmpeg](https://ffmpeg.org/) 的音頻處理功能,可自動生成帶有時間碼的逐字稿。 ## 功能特性 - **高效音頻提取**:利用 FFmpeg 直接從影片或音頻檔案中提取並重採樣為 Whisper 所需的格式 (16kHz, Mono, f32) - **精準轉寫**:基於 OpenAI Whisper 模型,提供高精度的語音轉文字功能 - **時間碼支援**:自動產生精確到毫秒的逐字稿時間戳,格式為 `HH:MM:SS.mmm(fXX)` (25fps) - **語言自動檢測**:若未指定語言,可自動偵測輸入音頻的語言 - **優化進度顯示**:在轉寫過程中提供即時的處理進度、耗時與預估剩餘時間 - **自動存檔**:支援定期自動存檔,避免長時間轉寫因意外中斷而遺失進度 - **中斷續處理**:支援從上次中斷點繼續處理 - **語言分段檢測**:自動檢測每段文字的語言類型,生成帶語言標籤的逐字稿 - **特殊內容識別**:自動識別 Music (音樂) 和 Empty (空文字) 分段 ## 前置需求 在編譯與執行前,請確保系統已安裝以下環境: 1. **Rust 環境**:請安裝 [Rustup](https://rustup.rs/) 2. **FFmpeg**:系統必須安裝 FFmpeg 開發庫 - macOS: `brew install ffmpeg` - Ubuntu/Debian: `sudo apt install libavcodec-dev libavformat-dev libavutil-dev libswresample-dev` 3. **Whisper 模型**:請準備 Whisper 的 `.bin` 模型檔案,並放置於 `models/` 目錄中 ## 編譯與安裝 ```bash # 複製專案 git clone cd rust-scribe # 編譯 Release 版本 (建議) cargo build --release ``` ## 使用方式 ### 基本使用 ```bash ./target/release/rust-scribe --model models/ ``` ### 參數說明 | 參數 | 說明 | 必填 | |------|------|------| | `` | 欲轉寫的影片或音頻檔案路徑 | ✅ | | `-m, --model ` | Whisper 模型檔案路徑 | ✅ | | `-l, --language ` | 指定轉寫語言 (例如 `zh`, `en`)。若不指定將自動偵測 | ❌ | | `-v, --verbose` | 開啟詳細轉寫進度輸出 | ❌ | | `--save-interval ` | 每 N 個分段自動存檔一次 (預設: 100) | ❌ | | `--max-duration <秒>` | 限制處理的最大時長(用於測試) | ❌ | ### 使用範例 ```bash # 基本使用,自動檢測語言,每 10 個分段存檔 cargo run --release -- video.mp4 --model models/ggml-base.bin --save-interval 10 # 指定中文轉寫 cargo run --release -- lecture.mkv --model models/ggml-base.bin --language zh # 限制處理前 60 秒(用於測試) cargo run --release -- video.mp4 --model models/ggml-base.bin --max-duration 60 ``` ## 輸出檔案 程式會生成兩個輸出檔案: ### 1. `.asr.json` - 基本逐字稿 包含基本的轉寫結果: ```json { "input_file": "video.mp4", "language": "English", "segments": [ { "start": "00:00:05.120(f03)", "end": "00:00:08.560(f14)", "text": "Hello everyone", "language": "English" } ] } ``` ### 2. `.asrx.json` - 帶語言檢測的逐字稿 包含每段文字的語言檢測結果: ```json { "input_file": "video.mp4", "segments": [ { "start": "00:00:05.120(f03)", "end": "00:00:08.560(f14)", "text": "Hello everyone", "language": "English", "confidence": 0.98 }, { "start": "00:00:10.000(f00)", "end": "00:00:13.000(f00)", "text": "[Music]", "language": "Music", "confidence": 1.0 } ] } ``` ## 進度顯示說明 轉寫過程中會顯示即時進度: ``` ═══════════════════════════════════════════════════════════ 🎙️ Transcribing (this may take a few minutes)... 💡 Auto-saving every 10 segments 📋 Legend: P = Processed (已處理分段數) A = ASR saved (.asr.json 已存檔數) X = Lang detect saved (.asrx.json 已存檔數) ═══════════════════════════════════════════════════════════ 🔄 Progress: [71:05/114:39] 62.0% | Elapsed: 03:04 | Remaining: 01:54 | P:1112 A:1110 X:1110 | English:500 Unknown:52 Music:58 ``` ### 進度列格式說明 - **時間進度**:`[已處理時間/總時長] 完成百分比` - **時間統計**:`Elapsed: 已耗時 | Remaining: 預估剩餘時間` - **分段統計**:`P:已處理數 A:ASR存檔數 X:語言檢測存檔數` - **語言統計**:各語言類型的分段數量(依序顯示) ### 特殊類型標籤 - **Music**:音樂或背景音效段落 - **Empty**:空文字或純空白段落 - **Unknown**:語言識別置信度低於 0.5 的段落 ## 中斷續處理 程式支援中斷後繼續處理: 1. 當程式偵測到已存在的輸出檔案時,會詢問是否繼續 2. 選擇 `[C] Continue` 會從上次中斷點繼續 3. 選擇 `[R] Restart` 會刪除舊檔案重新開始 兩個檔案(`.asr.json` 和 `.asrx.json`)會同步處理。 ## 語言檢測說明 使用 [whatlang](https://github.com/greyblake/whatlang-rs) 函式庫進行語言檢測: - **置信度 ≥ 0.5**:顯示檢測到的語言名稱 - **置信度 < 0.5**:標註為 "Unknown" - **Music**:自動識別包含 [Music] 或 (music) 標記的段落 - **Empty**:空文字或純空白段落 ## 專案結構 ``` rust-scribe/ ├── src/ │ └── main.rs # 核心邏輯 ├── models/ # Whisper 模型檔案 ├── Cargo.toml # 專案配置 ├── Cargo.lock # 依賴鎖定 ├── README.md # 使用文檔 ├── AGENTS.md # 開發者規範 └── .cargo/ └── config.toml # Cargo 配置 ``` ## 開發者規範 請參閱 `AGENTS.md` 了解詳細的代碼風格、編譯與測試指南。 ## 許可證 MIT License ## 致謝 - [Whisper.cpp](https://github.com/ggerganov/whisper.cpp) - OpenAI Whisper 的 C++ 實現 - [FFmpeg](https://ffmpeg.org/) - 音頻處理函式庫 - [whisper-rs](https://github.com/tazz4843/whisper-rs) - Whisper.cpp 的 Rust 綁定 - [whatlang](https://github.com/greyblake/whatlang-rs) - 自然語言檢測函式庫