<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Whisper.cpp on kenji.blog</title><link>http://kenji.blog/zh-tw/tags/whisper.cpp/</link><description>Recent content in Whisper.cpp on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/zh-tw/tags/whisper.cpp/index.xml" rel="self" type="application/rss+xml"/><item><title>如何將語音辨識AI（Whisper）整合至C++專案</title><link>http://kenji.blog/zh-tw/p/whisper-cpp-integration-guide/</link><pubDate>Fri, 11 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/zh-tw/p/whisper-cpp-integration-guide/</guid><description>&lt;img src="http://kenji.blog/p/whisper-cpp-integration-guide/img/eyecatch.jpg" alt="Featured image of post 如何將語音辨識AI（Whisper）整合至C++專案" />&lt;h2 id="1-簡介為什麼選擇在c中進行語音辨識">1. 簡介：為什麼選擇在C++中進行語音辨識
&lt;/h2>&lt;p>OpenAI開發的高精度語音辨識模型「Whisper」自開源以來，已被廣泛應用於各種應用程式中。雖然在Python環境（基於PyTorch）中使用非常普遍，但若要將其整合至&lt;strong>邊緣裝置（智慧型手機、IoT設備、嵌入式系統）&lt;/strong>，或是&lt;strong>要求高度即時性的原生C++應用程式&lt;/strong>（遊戲引擎、DAW軟體、機器人技術等）時，對Python直譯器的依賴會成為效能上的重大瓶頸。&lt;/p>
&lt;p>這時候的救星，就是由Georgi Gerganov所開發的 &lt;strong>&lt;a class="link" href="https://github.com/ggerganov/whisper.cpp" target="_blank" rel="noopener"
>whisper.cpp&lt;/a>&lt;/strong>。該函式庫以機器學習專用的張量運算函式庫 &lt;code>ggml&lt;/code> 為基礎，將依賴關係降至最低，僅使用C/C++便實現了Whisper的推論。&lt;/p>
&lt;p>本文將徹底解說如何使用這個 &lt;code>whisper.cpp&lt;/code>，將最高水準的語音辨識功能整合至您專屬的C++專案中，內容涵蓋語音訊號處理基礎、API詳細使用方法、記憶體管理、多執行緒最佳化，以及即時處理的實作模式。&lt;/p>
&lt;hr>
&lt;h2 id="2-語音訊號處理與whisper的輸入要求">2. 語音訊號處理與Whisper的輸入要求
&lt;/h2>&lt;p>為了讓AI理解語音，必須將作為類比訊號的「聲音」轉換為數位資料，並落實為AI模型可以處理的格式（張量）。Whisper所要求的語音格式非常嚴格。&lt;/p>
&lt;h3 id="21-whisper要求的音訊格式">2.1 Whisper要求的音訊格式
&lt;/h3>&lt;p>Whisper模型接受符合以下規格的語音資料作為輸入：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>取樣率 (Sample Rate)&lt;/strong>: 16,000 Hz (16 kHz)&lt;/li>
&lt;li>&lt;strong>聲道數 (Channels)&lt;/strong>: 1 (單聲道)&lt;/li>
&lt;li>&lt;strong>資料型態 (Data Type)&lt;/strong>: 32-bit 浮點數 (&lt;code>float&lt;/code> in C/C++)&lt;/li>
&lt;li>&lt;strong>正規化 (Normalization)&lt;/strong>: 縮放至 $[-1.0, 1.0]$ 範圍的值&lt;/li>
&lt;/ul>
&lt;p>舉例來說，若將CD音質（44.1kHz, 立體聲, 16-bit PCM）的語音檔案作為輸入，必須事先進行降取樣（Downsampling）、聲道混合（Mixdown）以及格式轉換。&lt;/p>
&lt;p>資料傳輸率的計算公式如下：&lt;/p>
$$ \text{Data Rate (bytes/sec)} = \text{Sample Rate} \times \text{Channels} \times \frac{\text{Bit Depth}}{8} $$
&lt;p>在Whisper的要求（16kHz, 1ch, 32-bit Float）下，1秒鐘的資料大小為：&lt;/p>
$$ 16000 \times 1 \times \frac{32}{8} = 64,000 \text{ bytes/sec (64 KB/s)} $$
&lt;p>由於非常輕量，即使在記憶體頻寬受限的邊緣裝置上，也能夠游刃有餘地進行緩衝（Buffering）。&lt;/p>
&lt;h3 id="22-梅爾頻譜圖轉換的數學原理">2.2 梅爾頻譜圖轉換的數學原理
&lt;/h3>&lt;p>在Whisper內部，並非直接處理一維的語音波形資料（Raw Waveform）。而是會先轉換為接近人類聽覺特性的頻率表示方式——&lt;strong>梅爾頻譜圖 (Mel-Spectrogram)&lt;/strong>，再輸入至Transformer模型。&lt;code>whisper.cpp&lt;/code> 在其C++實作中已內含了此轉換處理，但了解其機制有助於對策雜訊與最佳化前處理。&lt;/p>
&lt;p>將一般頻率 $f$ (Hz) 轉換為梅爾尺度 $m$ 的公式近似如下：&lt;/p>
$$ m = 2595 \log_{10} \left( 1 + \frac{f}{700} \right) $$
&lt;p>反之，從梅爾尺度轉換回頻率的逆轉換如下：&lt;/p>
$$ f = 700 \left( 10^{\frac{m}{2595}} - 1 \right) $$
&lt;p>此外，語音波形會透過&lt;strong>短時距傅立葉變換 (STFT: Short-Time Fourier Transform)&lt;/strong> 轉換至時間-頻率域。使用窗函數 $w(n)$ 的STFT離散形式可表示為：&lt;/p>
$$ X(m, k) = \sum_{n=0}^{N-1} x(n + mH) w(n) e^{-j \frac{2\pi}{N} k n} $$
&lt;p>
&lt;em>(在此，$N$ 為FFT的視窗大小，$H$ 為平移大小 (Hop Size)，$w(n)$ 為漢明窗 (Hann Window) 等窗函數)&lt;/em>&lt;/p>
&lt;p>Whisper模型通常使用視窗大小 $N = 400$ (25ms)、平移大小 $H = 160$ (10ms)，以及80維的梅爾濾波器組。這項特徵提取會在呼叫 &lt;code>whisper.cpp&lt;/code> 內的 &lt;code>whisper_full()&lt;/code> 時自動（並且使用SIMD指令高速地）執行。&lt;/p>
&lt;hr>
&lt;h2 id="3-架構與管線設計">3. 架構與管線設計
&lt;/h2>&lt;p>讓我們來設計C++應用程式中的語音處理管線。流程從檔案輸入或麥克風輸入開始，經過前處理，接著使用 &lt;code>whisper.cpp&lt;/code> 進行推論，最後輸出文字。&lt;/p>
&lt;div class="mermaid">graph TD
A["音訊來源 (麥克風/檔案)"] -->|Raw Bytes, e.g. 48kHz Stereo| B["音訊解碼器與重新取樣器 (FFmpeg/miniaudio)"]
B -->|16kHz Mono 32-bit Float| C["環形緩衝區 / 記憶體陣列"]
C -->|Feed PCM Data| D["whisper.cpp 核心 (ggml)"]
D --> E["梅爾頻譜圖擷取"]
E --> F["Transformer 編碼器-解碼器"]
F --> G["文字 Token 生成"]
G --> H["文字輸出 (UTF-8 字串)"]&lt;/div>
&lt;p>應用程式端應負責的是上圖中 &lt;strong>A 到 C 的區段（音訊解碼與重新取樣）&lt;/strong>。由於 &lt;code>whisper.cpp&lt;/code> 本身不包含語音檔案的解碼器，因此搭配 FFmpeg 或 &lt;code>miniaudio&lt;/code> 等函式庫使用是最佳實務。&lt;/p>
&lt;hr>
&lt;h2 id="4-whispercpp-的建置與導入">4. whisper.cpp 的建置與導入
&lt;/h2>&lt;p>將 &lt;code>whisper.cpp&lt;/code> 整合至專案的步驟。使用CMake是通用性最高的方式。&lt;/p>
&lt;h3 id="cmakeliststxt-的設定">CMakeLists.txt 的設定
&lt;/h3>&lt;p>可以將 &lt;code>whisper.cpp&lt;/code> 作為原始碼納入專案，或作為子模組 (submodule) 加入並連結。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.14&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">WhisperApp&lt;/span> &lt;span class="s">C&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">17&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 啟用CPU擴充指令集（AVX, F16C等）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 若在MacOS上，會自動啟用NEON/Accelerate框架
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">WHISPER_SUPPORT_SDL2&lt;/span> &lt;span class="s">OFF&lt;/span> &lt;span class="s">CACHE&lt;/span> &lt;span class="s">BOOL&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> &lt;span class="s">FORCE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">whisper.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">whisper_app&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">whisper_app&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">whisper&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過此設定，將會建置 &lt;code>whisper.cpp&lt;/code> 高度最佳化過的 &lt;code>ggml&lt;/code> 後端，並靜態連結至應用程式中。&lt;/p>
&lt;hr>
&lt;h2 id="5-c-api詳細說明與實作步驟">5. C++ API詳細說明與實作步驟
&lt;/h2>&lt;p>接下來我們一邊看實際的C++程式碼，一邊解說API的呼叫方式。&lt;/p>
&lt;h3 id="51-內容初始化與模型載入">5.1 內容初始化與模型載入
&lt;/h3>&lt;p>在 &lt;code>whisper.cpp&lt;/code> 中，所有的狀態與記憶體配置皆由 &lt;code>whisper_context&lt;/code> 結構體進行管理。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;whisper.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. 初始化參數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="nc">whisper_context_params&lt;/span> &lt;span class="n">cparams&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_context_default_params&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">use_gpu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 當可使用GPU硬體加速（CuBLAS/Metal）時啟用
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. 載入模型 (ggml格式的二進位模型)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">model_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;models/ggml-base.bin&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">struct&lt;/span> &lt;span class="nc">whisper_context&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_init_from_file_with_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model_path&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">cparams&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;錯誤: 模型載入失敗 - &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">model_path&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;已成功載入模型。&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>模型檔案為專門量化過的 &lt;code>.bin&lt;/code> 格式。可以使用官方儲存庫中的轉換腳本，或直接從HuggingFace下載。在記憶體限制嚴格的環境中，透過使用4-bit量化模型（例如：&lt;code>ggml-base-q4_0.bin&lt;/code>），可將RAM消耗量減少至約1/4。&lt;/p>
&lt;h3 id="52-推論參數設定">5.2 推論參數設定
&lt;/h3>&lt;p>接著設定控制推論行為的 &lt;code>whisper_full_params&lt;/code>。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. 設定完整推論用參數 (使用Greedy Sampling)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="nc">whisper_full_params&lt;/span> &lt;span class="n">wparams&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_full_default_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">WHISPER_SAMPLING_GREEDY&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 設定執行緒數量 (配合CPU實體核心數為最佳)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">wparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_threads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 語言設定 (自動判斷為 &amp;#34;auto&amp;#34;，指定日文為 &amp;#34;ja&amp;#34;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">wparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">language&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;ja&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 抑制中間結果的標準輸出（為了在應用程式內控制）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">wparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">print_progress&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">wparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">print_realtime&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 翻譯功能 (若要將日文語音直接翻譯為英文文字則設為 true)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">wparams&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">translate&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-語音資料準備與推論執行">5.3 語音資料準備與推論執行
&lt;/h3>&lt;p>此處假設16kHz的語音資料已經儲存在 &lt;code>std::vector&amp;lt;float&amp;gt;&lt;/code> 中。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 虛擬的語音資料 (實際上是從檔案或麥克風取得的PCM資料)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 3秒鐘 (16000 Hz * 3 sec = 48000 samples)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">float&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">pcmf32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">48000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.0f&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. 執行推論
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">whisper_full&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">wparams&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pcmf32&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">pcmf32&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;錯誤: whisper_full 執行失敗。&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">whisper_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="54-結果擷取">5.4 結果擷取
&lt;/h3>&lt;p>當 &lt;code>whisper_full&lt;/code> 完成後，辨識結果將會以片段 (Segment) 為單位儲存於 context 中。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. 取得並顯示結果
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_segments&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_full_n_segments&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">n_segments&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_full_get_segment_text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 取得時間戳記 (單位: 10ms)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">t0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_full_get_segment_t0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">t1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">whisper_full_get_segment_t1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">t0&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">10.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; ms -&amp;gt; &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">t1&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">10.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; ms]: &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">text&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 6. 釋放記憶體
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">whisper_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>此程式碼區塊將是在C++中使用Whisper的最基本樣板。&lt;/p>
&lt;hr>
&lt;h2 id="6-即時語音辨識的進階實作">6. 即時語音辨識的進階實作
&lt;/h2>&lt;p>處理已錄製完成的檔案很簡單，但為了提升應用程式的UX，從麥克風輸入的「即時語音辨識（串流辨識）」是不可或缺的。&lt;/p>
&lt;p>要實作這項功能，多執行緒架構以及透過環形緩衝區（Ring Buffer）來管理語音串流是必要的。&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "音訊執行緒 (高優先級)"
A["音訊擷取 API (CoreAudio/WASAPI/ALSA)"] -->|Callback| B["重新取樣器 (至16kHz)"]
B --> C["環形緩衝區"]
end
subgraph "主執行緒 / 工作執行緒"
C -->|Pop 30ms-1000ms chunk| D["語音活動偵測 (VAD)"]
D -->|If speech detected| E["累積 PCM 緩衝區"]
E -->|Trigger Inference| F["whisper_full()"]
F --> G["更新 UI/文字"]
end&lt;/div>
&lt;h3 id="61-語音活動偵測-vad-的重要性">6.1 語音活動偵測 (VAD) 的重要性
&lt;/h3>&lt;p>在即時處理中，不斷對無音部分執行推論會浪費運算資源。透過在前端加入VAD演算法（簡單的基於能量閾值處理，或WebRTC VAD等），可以進行**「僅在開始說話時才開始緩衝，並在說話結束（一定時間的無音）時觸發 &lt;code>whisper_full&lt;/code>」** 的控制。&lt;/p>
&lt;h3 id="62-滑動視窗-sliding-window-策略">6.2 滑動視窗 (Sliding Window) 策略
&lt;/h3>&lt;p>當語音持續較長時，會採用每隔幾秒裁切區塊進行推論的「滑動視窗」手法。然而，若單純將語音直接切斷，可能會在單字中途被切斷，導致辨識精準度顯著下降。&lt;/p>
&lt;p>作為對策，會使用**「推論時始終包含過去N秒的上下文」**（使其重疊）的手法。&lt;code>whisper.cpp&lt;/code> 中也有一項名為 &lt;code>wparams.prompt_tokens&lt;/code> 的功能，可以將過去的文字 Token 作為提示 (Prompt) 繼承下來，從而實現維持上下文的高精準度串流辨識。&lt;/p>
&lt;hr>
&lt;h2 id="7-記憶體管理與邊緣裝置的最佳化">7. 記憶體管理與邊緣裝置的最佳化
&lt;/h2>&lt;p>接著我們將深入探討 &lt;code>whisper.cpp&lt;/code> 最大的優勢——效能與記憶體效率。&lt;/p>
&lt;h3 id="71-ggml-張量函式庫的威力">7.1 ggml 張量函式庫的威力
&lt;/h3>&lt;p>&lt;code>whisper.cpp&lt;/code> 的後端 &lt;code>ggml&lt;/code> 是一個不具依賴關係的C語言張量函式庫。它最大的特色，在於支援&lt;strong>權重資料的動態量化 (Quantization)&lt;/strong>。&lt;/p>
&lt;p>舉例來說，我們來計算 Whisper &lt;code>Small&lt;/code> 模型（約2億4000萬個參數）的記憶體大小。
在一般情況下（16-bit Float = 2 bytes）：&lt;/p>
$$ \text{Memory (FP16)} \approx 244,000,000 \times 2 \text{ bytes} \approx 488 \text{ MB} $$
&lt;p>若將其轉換為 4-bit 量化（Q4_0 格式），每個參數平均為0.5 bytes（包含縮放係數等額外開銷後約為0.56 bytes）。&lt;/p>
$$ \text{Memory (Q4\_0)} \approx 244,000,000 \times 0.56 \text{ bytes} \approx 137 \text{ MB} $$
&lt;p>在 iOS 裝置或 Raspberry Pi 等 RAM 限制嚴格的環境中，減少這種記憶體佔用量會直接關係到應用程式整體的穩定性。&lt;/p>
&lt;h3 id="72-活用硬體加速">7.2 活用硬體加速
&lt;/h3>&lt;p>雖然單靠 CPU 搭配 AVX2 或 NEON 指令集就已足夠快速，但 &lt;code>whisper.cpp&lt;/code> 也支援各種 GPU、NPU 的硬體加速作為後端。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Apple Silicon (Mac/iOS)&lt;/strong>: 透過 &lt;code>ggml-metal&lt;/code> 支援 Metal API。使用 GPU 進行超高速推論。&lt;/li>
&lt;li>&lt;strong>NVIDIA GPU (Windows/Linux)&lt;/strong>: 支援 &lt;code>cuBLAS&lt;/code>。在 CMake 建置時指定 &lt;code>-DWHISPER_CUBLAS=ON&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Intel (Windows/Linux)&lt;/strong>: 支援 &lt;code>OpenVINO&lt;/code> 後端。可活用最新 Intel Core 處理器上的 NPU。&lt;/li>
&lt;/ul>
&lt;p>若要在 C++ 專案中使用這些加速器，幾乎不需要修改原始碼。只要在上下文初始化時設定了 &lt;code>cparams.use_gpu = true;&lt;/code>，系統就會根據建置好的後端，自動將運算卸載 (Offload) 至硬體。&lt;/p>
&lt;h3 id="73-快取與執行緒數量的調校">7.3 快取與執行緒數量的調校
&lt;/h3>&lt;p>&lt;code>wparams.n_threads&lt;/code> 的設定非常重要。即使盲目增加執行緒數量，也會因為記憶體頻寬的瓶頸 (Memory Bound) 而無法提升效能。&lt;/p>
&lt;p>根據經驗法則，理想情況是使用以下計算公式來決定執行緒數量：&lt;/p>
$$ N_{\text{threads}} = \min(\text{實體 CPU 核心數}, 4 \sim 8) $$
&lt;p>若包含 Hyper-Threading 等邏輯核心，通常會發生快取爭用而導致推論速度反而下降，因此設定為&lt;strong>實體核心數&lt;/strong>是鐵則。由於使用 C++11 的 &lt;code>std::thread::hardware_concurrency()&lt;/code> 會回傳邏輯核心數，建議根據環境寫死數值 (Hardcode)，或是透過作業系統層級的 API 來取得實體核心數。&lt;/p>
&lt;hr>
&lt;h2 id="8-總結">8. 總結
&lt;/h2>&lt;p>本文中，我們從理論到實踐，再到最佳化，詳細解說了如何活用 &lt;code>whisper.cpp&lt;/code> 將最高水準的語音辨識 AI 整合至 C++ 專案中。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>遵守輸入要求&lt;/strong>: 徹底執行 16kHz, 1ch, 32-bit Float。&lt;/li>
&lt;li>&lt;strong>直覺的 API 使用&lt;/strong>: 僅靠 &lt;code>whisper_init_from_file_with_params&lt;/code> 與 &lt;code>whisper_full&lt;/code> 就能完成推論的簡潔設計。&lt;/li>
&lt;li>&lt;strong>即時處理化&lt;/strong>: 透過 VAD 與滑動視窗進行的多執行緒控制。&lt;/li>
&lt;li>&lt;strong>壓倒性的最佳化&lt;/strong>: 透過 &lt;code>ggml&lt;/code> 進行 4-bit 量化，以及受惠於 Metal/cuBLAS 等硬體後端。&lt;/li>
&lt;/ul>
&lt;p>請務必在開發能夠擺脫對龐大 Python 環境或雲端 API 的依賴，並在原生環境中高速且安全運作的語音處理應用程式時，善用 &lt;code>whisper.cpp&lt;/code>。從隱私保護與低延遲的角度來看，完全在地端運行的 AI 必將成為未來軟體開發中極為重要的關鍵技術。&lt;/p></description></item></channel></rss>