<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Speech Recognition on kenji.blog</title><link>http://kenji.blog/de/tags/speech-recognition/</link><description>Recent content in Speech Recognition on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/speech-recognition/index.xml" rel="self" type="application/rss+xml"/><item><title>Wie man die Spracherkennungs-KI (Whisper) in ein C++-Projekt integriert</title><link>http://kenji.blog/de/p/whisper-cpp-integration-guide/</link><pubDate>Fri, 11 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/de/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 Wie man die Spracherkennungs-KI (Whisper) in ein C++-Projekt integriert" />&lt;h2 id="1-einführung-warum-spracherkennung-in-c">1. Einführung: Warum Spracherkennung in C++?
&lt;/h2>&lt;p>Seit das von OpenAI entwickelte hochpräzise Spracherkennungsmodell &amp;ldquo;Whisper&amp;rdquo; als Open Source veröffentlicht wurde, wird es in verschiedenen Anwendungen eingesetzt. Die Nutzung in einer Python-Umgebung (PyTorch-basiert) ist üblich, aber bei der Integration in &lt;strong>Edge-Geräte (Smartphones, IoT-Geräte, eingebettete Systeme)&lt;/strong> oder &lt;strong>native C++-Anwendungen, die eine hohe Echtzeitleistung erfordern&lt;/strong> (Game-Engines, DAW-Software, Robotik usw.), wird die Abhängigkeit vom Python-Interpreter zu einem großen Leistungsengpass.&lt;/p>
&lt;p>Hier kommt &lt;strong>&lt;a class="link" href="https://github.com/ggerganov/whisper.cpp" target="_blank" rel="noopener"
>whisper.cpp&lt;/a>&lt;/strong>, entwickelt von Georgi Gerganov, zur Rettung. Diese Bibliothek basiert auf &lt;code>ggml&lt;/code>, einer Tensor-Berechnungsbibliothek für maschinelles Lernen. Sie reduziert Abhängigkeiten auf ein absolutes Minimum und realisiert Whisper-Inferenz ausschließlich in C/C++.&lt;/p>
&lt;p>In diesem Artikel werden wir ausführlich erläutern, wie Sie mithilfe dieser &lt;code>whisper.cpp&lt;/code> hochmoderne Spracherkennungsfunktionen in Ihr eigenes C++-Projekt integrieren können. Dabei decken wir alles ab: von den Grundlagen der Audiosignalverarbeitung über die detaillierte Nutzung der API, Speicherverwaltung, Multithreading-Optimierung bis hin zu Implementierungsmustern für die Echtzeitverarbeitung.&lt;/p>
&lt;hr>
&lt;h2 id="2-audiosignalverarbeitung-und-eingabeanforderungen-von-whisper">2. Audiosignalverarbeitung und Eingabeanforderungen von Whisper
&lt;/h2>&lt;p>Damit die KI Sprache verstehen kann, ist es notwendig, das analoge Signal &amp;ldquo;Ton&amp;rdquo; in digitale Daten umzuwandeln und in ein Format (Tensor) zu bringen, das das KI-Modell verarbeiten kann. Das von Whisper geforderte Audioformat ist sehr streng.&lt;/p>
&lt;h3 id="21-von-whisper-gefordertes-audioformat">2.1 Von Whisper gefordertes Audioformat
&lt;/h3>&lt;p>Das Whisper-Modell akzeptiert Audiodaten mit den folgenden Spezifikationen als Eingabe:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Abtastrate (Sample Rate)&lt;/strong>: 16.000 Hz (16 kHz)&lt;/li>
&lt;li>&lt;strong>Kanalanzahl (Channels)&lt;/strong>: 1 (Mono)&lt;/li>
&lt;li>&lt;strong>Datentyp (Data Type)&lt;/strong>: 32-Bit-Gleitkommazahl (&lt;code>float&lt;/code> in C/C++)&lt;/li>
&lt;li>&lt;strong>Normalisierung (Normalization)&lt;/strong>: Werte skaliert im Bereich $[-1.0, 1.0]$&lt;/li>
&lt;/ul>
&lt;p>Wenn beispielsweise eine Audiodatei in CD-Qualität (44,1 kHz, Stereo, 16-Bit-PCM) als Eingabe verwendet wird, müssen zuvor ein Downsampling, ein Downmix der Kanäle und eine Formatkonvertierung durchgeführt werden.&lt;/p>
&lt;p>Die Formel zur Berechnung der Datenübertragungsrate lautet wie folgt:&lt;/p>
$$ \text{Data Rate (bytes/sec)} = \text{Sample Rate} \times \text{Channels} \times \frac{\text{Bit Depth}}{8} $$
&lt;p>Die Datengröße pro Sekunde für die Whisper-Anforderungen (16 kHz, 1 Kanal, 32-Bit-Float) beträgt:&lt;/p>
$$ 16000 \times 1 \times \frac{32}{8} = 64,000 \text{ bytes/sec (64 KB/s)} $$
&lt;p>Da dies sehr leichtgewichtig ist, ist eine ausreichende Pufferung auch auf Edge-Geräten mit begrenzter Speicherbandbreite möglich.&lt;/p>
&lt;h3 id="22-mathematik-der-mel-spektrogramm-konvertierung">2.2 Mathematik der Mel-Spektrogramm-Konvertierung
&lt;/h3>&lt;p>Intern verarbeitet Whisper 1D-Audiowellendaten (Raw Waveform) nicht direkt. Sie werden in ein &lt;strong>Mel-Spektrogramm (Mel-Spectrogram)&lt;/strong> umgewandelt, eine Frequenzdarstellung, die dem menschlichen Gehör nahekommt, bevor sie in das Transformer-Modell eingegeben werden. &lt;code>whisper.cpp&lt;/code> enthält diesen Konvertierungsprozess innerhalb seiner C++-Implementierung, aber das Verständnis der Mechanik ist hilfreich für die Rauschunterdrückung und Optimierung der Vorverarbeitung.&lt;/p>
&lt;p>Die Formel zur Umwandlung einer normalen Frequenz $f$ (Hz) in die Mel-Skala $m$ wird wie folgt approximiert:&lt;/p>
$$ m = 2595 \log_{10} \left( 1 + \frac{f}{700} \right) $$
&lt;p>Umgekehrt lautet die inverse Transformation von der Mel-Skala zur Frequenz wie folgt:&lt;/p>
$$ f = 700 \left( 10^{\frac{m}{2595}} - 1 \right) $$
&lt;p>Darüber hinaus wird die Audiowellenform durch eine &lt;strong>Kurzzeit-Fourier-Transformation (STFT: Short-Time Fourier Transform)&lt;/strong> in den Zeit-Frequenz-Bereich transformiert. Die diskrete Form der STFT mit einer Fensterfunktion $w(n)$ wird wie folgt ausgedrückt:&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>(Hier ist $N$ die FFT-Fenstergröße, $H$ die Hop-Größe und $w(n)$ eine Fensterfunktion wie das Hann-Fenster)&lt;/em>&lt;/p>
&lt;p>Das Whisper-Modell verwendet typischerweise eine Fenstergröße $N = 400$ (25 ms), eine Hop-Größe $H = 160$ (10 ms) und eine 80-dimensionale Mel-Filterbank. Diese Merkmalsextraktion wird automatisch (und dank SIMD-Befehlen schnell) ausgeführt, wenn &lt;code>whisper_full()&lt;/code> in &lt;code>whisper.cpp&lt;/code> aufgerufen wird.&lt;/p>
&lt;hr>
&lt;h2 id="3-architektur-und-pipeline-design">3. Architektur und Pipeline-Design
&lt;/h2>&lt;p>Lassen Sie uns eine Audioverarbeitungs-Pipeline in einer C++-Anwendung entwerfen. Der Ablauf beginnt mit einer Datei- oder Mikrofoneingabe, durchläuft die Vorverarbeitung, gefolgt von der Inferenz durch &lt;code>whisper.cpp&lt;/code>, und endet mit der Textausgabe.&lt;/p>
&lt;div class="mermaid">graph TD
A["Audioquelle (Mikrofon/Datei)"] -->|Rohbytes, z.B. 48kHz Stereo| B["Audio-Decoder &amp; Resampler (FFmpeg/miniaudio)"]
B -->|16kHz Mono 32-Bit-Float| C["Ringpuffer / Speicherarray"]
C -->|PCM-Daten einspeisen| D["whisper.cpp Kern (ggml)"]
D --> E["Mel-Spektrogramm-Extraktion"]
E --> F["Transformer Encoder-Decoder"]
F --> G["Text-Token-Generierung"]
G --> H["Textausgabe (UTF-8 String)"]&lt;/div>
&lt;p>Der Bereich, für den die Anwendung verantwortlich sein sollte, ist der &lt;strong>Abschnitt von A bis C in der obigen Abbildung (Audio-Decodierung und Resampling)&lt;/strong>. Da &lt;code>whisper.cpp&lt;/code> selbst keinen Audio-Decoder enthält, ist es die beste Praxis, es in Kombination mit Bibliotheken wie FFmpeg oder &lt;code>miniaudio&lt;/code> zu verwenden.&lt;/p>
&lt;hr>
&lt;h2 id="4-bauen-und-integrieren-von-whispercpp">4. Bauen und Integrieren von whisper.cpp
&lt;/h2>&lt;p>Hier sind die Schritte zur Integration von &lt;code>whisper.cpp&lt;/code> in Ihr Projekt. Die Verwendung von CMake ist am vielseitigsten.&lt;/p>
&lt;h3 id="cmakeliststxt-konfigurieren">CMakeLists.txt konfigurieren
&lt;/h3>&lt;p>&lt;code>whisper.cpp&lt;/code> wird entweder als Quellcode in das Projekt aufgenommen oder als Submodul hinzugefügt und verlinkt.&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"># Aktivieren von CPU-Erweiterungsbefehlen (AVX, F16C, etc.)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Auf MacOS wird das NEON/Accelerate-Framework automatisch aktiviert
&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>Mit dieser Konfiguration wird das hochoptimierte &lt;code>ggml&lt;/code>-Backend von &lt;code>whisper.cpp&lt;/code> erstellt und statisch mit Ihrer Anwendung verlinkt.&lt;/p>
&lt;hr>
&lt;h2 id="5-details-zur-c-api-und-implementierungsschritte">5. Details zur C++-API und Implementierungsschritte
&lt;/h2>&lt;p>Nun schauen wir uns den tatsächlichen C++-Code an und erklären, wie man die API aufruft.&lt;/p>
&lt;h3 id="51-kontextinitialisierung-und-modell-laden">5.1 Kontextinitialisierung und Modell-Laden
&lt;/h3>&lt;p>In &lt;code>whisper.cpp&lt;/code> werden alle Zustände und Speicherzuweisungen durch die Struktur &lt;code>whisper_context&lt;/code> verwaltet.&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. Parameter-Initialisierung
&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-Beschleunigung (CuBLAS/Metal) verwenden, falls verfügbar
&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. Modell laden (Binärmodell im ggml-Format)
&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;Fehler: Fehler beim Laden des Modells - &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;Modell erfolgreich geladen.&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>Die Modelldatei liegt in einem einzigartig quantisierten &lt;code>.bin&lt;/code>-Format vor. Sie können das Konvertierungsskript aus dem offiziellen Repository verwenden oder es direkt von HuggingFace herunterladen. In Umgebungen mit strengen Speicherbeschränkungen reduziert die Verwendung von 4-Bit-quantisierten Modellen (z. B. &lt;code>ggml-base-q4_0.bin&lt;/code>) den RAM-Verbrauch auf etwa ein Viertel.&lt;/p>
&lt;h3 id="52-konfiguration-der-inferenzparameter">5.2 Konfiguration der Inferenzparameter
&lt;/h3>&lt;p>Als nächstes richten wir &lt;code>whisper_full_params&lt;/code> ein, um das Verhalten der Inferenz zu steuern.&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. Einstellen der Parameter für die vollständige Inferenz (Verwendung von 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">// Einstellung der Thread-Anzahl (am besten an die Anzahl der physischen CPU-Kerne anpassen)
&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">// Spracheinstellung (&amp;#34;auto&amp;#34; für automatische Erkennung, &amp;#34;de&amp;#34; für die Angabe von Deutsch)
&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;de&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">// Unterdrückung der Standardausgabe für Zwischenergebnisse (zur Kontrolle innerhalb der App)
&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">// Übersetzungsfunktion (true, wenn deutsches Audio direkt in englischen Text übersetzt werden soll)
&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-vorbereitung-der-audiodaten-und-ausführung-der-inferenz">5.3 Vorbereitung der Audiodaten und Ausführung der Inferenz
&lt;/h3>&lt;p>Hier gehen wir davon aus, dass 16-kHz-Audiodaten bereits in &lt;code>std::vector&amp;lt;float&amp;gt;&lt;/code> gespeichert sind.&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">// Virtuelle Audiodaten (tatsächlich PCM-Daten von einer Datei oder einem Mikrofon)
&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 Sekunden lang (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. Ausführung der Inferenz
&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;Fehler: Ausführung von whisper_full fehlgeschlagen.&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-extrahieren-der-ergebnisse">5.4 Extrahieren der Ergebnisse
&lt;/h3>&lt;p>Wenn &lt;code>whisper_full&lt;/code> abgeschlossen ist, werden die Erkennungsergebnisse im Kontext nach Segmenten gespeichert.&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. Ergebnisse abrufen und anzeigen
&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">// Zeitstempel abrufen (Einheit: 10 ms)
&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. Speicher freigeben
&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>Dieser Codeblock ist die grundlegendste Vorlage für die Verwendung von Whisper in C++.&lt;/p>
&lt;hr>
&lt;h2 id="6-fortgeschrittene-implementierung-von-echtzeit-spracherkennung">6. Fortgeschrittene Implementierung von Echtzeit-Spracherkennung
&lt;/h2>&lt;p>Das Verarbeiten von vorab aufgezeichneten Dateien ist einfach, aber um die Benutzererfahrung (UX) einer Anwendung zu verbessern, ist eine &amp;ldquo;Echtzeit-Spracherkennung (Streaming-Erkennung)&amp;rdquo; über den Mikrofoneingang erforderlich.&lt;/p>
&lt;p>Um dies zu implementieren, sind eine Multithreading-Architektur und die Verwaltung des Audiostreams durch einen Ringpuffer (Ring Buffer) unerlässlich.&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "Audio-Thread (Hohe Priorität)"
A["Audio-Capture-API (CoreAudio/WASAPI/ALSA)"] -->|Callback| B["Resampler (auf 16kHz)"]
B --> C["Ringpuffer"]
end
subgraph "Haupt- / Worker-Thread"
C -->|30ms-1000ms Chunk entnehmen| D["Sprachaktivitätserkennung (VAD)"]
D -->|Wenn Sprache erkannt| E["PCM-Puffer ansammeln"]
E -->|Inferenz auslösen| F["whisper_full()"]
F --> G["UI/Text aktualisieren"]
end&lt;/div>
&lt;h3 id="61-die-bedeutung-der-voice-activity-detection-vad">6.1 Die Bedeutung der Voice Activity Detection (VAD)
&lt;/h3>&lt;p>Bei der Echtzeitverarbeitung ist es eine Verschwendung von Rechenressourcen, ständig Inferenzen auch für stille Abschnitte durchzuführen. Indem man einen VAD-Algorithmus (einen einfachen energie-basierten Schwellenwertprozess oder WebRTC VAD usw.) in die vorhergehende Stufe einfügt, wird die Steuerung erreicht: &lt;strong>&amp;ldquo;Starten Sie die Pufferung nur, wenn eine Äußerung beginnt, und stoßen Sie &lt;code>whisper_full&lt;/code> an dem Punkt an, an dem die Äußerung endet (eine bestimmte Zeit der Stille).&amp;rdquo;&lt;/strong>&lt;/p>
&lt;h3 id="62-sliding-window-ansatz">6.2 Sliding-Window-Ansatz
&lt;/h3>&lt;p>Wenn eine Äußerung lange andauert, verwenden wir die &amp;ldquo;Sliding-Window&amp;rdquo;-Methode, bei der die Inferenz alle paar Sekunden durch Ausschneiden von Chunks durchgeführt wird. Wenn Sie den Ton jedoch einfach abhacken, wird er mitten in einem Wort abgeschnitten und die Erkennungsgenauigkeit sinkt erheblich.&lt;/p>
&lt;p>Als Gegenmaßnahme verwenden wir eine Methode (Überlappung), bei der &lt;strong>&amp;ldquo;die Inferenz immer den Kontext der vorherigen N Sekunden in der Vergangenheit einschließt&amp;rdquo;&lt;/strong>. &lt;code>whisper.cpp&lt;/code> hat auch eine Funktion namens &lt;code>wparams.prompt_tokens&lt;/code>, die vergangene Text-Token als Prompt übernimmt, was eine hochgenaue Streaming-Erkennung unter Beibehaltung des Kontexts ermöglicht.&lt;/p>
&lt;hr>
&lt;h2 id="7-speicherverwaltung-und-optimierung-für-edge-geräte">7. Speicherverwaltung und Optimierung für Edge-Geräte
&lt;/h2>&lt;p>Wir werden uns eingehend mit Leistung und Speichereffizienz befassen, dem größten Vorteil von &lt;code>whisper.cpp&lt;/code>.&lt;/p>
&lt;h3 id="71-die-leistungsfähigkeit-der-ggml-tensorbibliothek">7.1 Die Leistungsfähigkeit der ggml-Tensorbibliothek
&lt;/h3>&lt;p>Das Backend von &lt;code>whisper.cpp&lt;/code>, &lt;code>ggml&lt;/code>, ist eine C-Tensorbibliothek ohne Abhängigkeiten. Das wichtigste Merkmal ist, dass es eine &lt;strong>dynamische Quantisierung (Quantization)&lt;/strong> von Gewichtsdaten unterstützt.&lt;/p>
&lt;p>Berechnen wir beispielsweise die Speichergröße des Modells Whisper &lt;code>Small&lt;/code> (ca. 240 Millionen Parameter).
Im Normalfall (16-Bit-Float = 2 Byte):&lt;/p>
$$ \text{Memory (FP16)} \approx 244,000,000 \times 2 \text{ bytes} \approx 488 \text{ MB} $$
&lt;p>Wenn dies in eine 4-Bit-Quantisierung (Q4_0-Format) umgewandelt wird, beträgt der Durchschnitt 0,5 Byte pro Parameter (etwa 0,56 Byte einschließlich Overhead wie Skalierungsfaktoren).&lt;/p>
$$ \text{Memory (Q4\_0)} \approx 244,000,000 \times 0.56 \text{ bytes} \approx 137 \text{ MB} $$
&lt;p>In Umgebungen mit strengen RAM-Einschränkungen, wie iOS-Geräten und Raspberry Pi, hängt diese Reduzierung des Speicherbedarfs direkt mit der Gesamtstabilität der Anwendung zusammen.&lt;/p>
&lt;h3 id="72-nutzung-von-hardwarebeschleunigung">7.2 Nutzung von Hardwarebeschleunigung
&lt;/h3>&lt;p>Obwohl die CPU allein durch AVX2- und NEON-Befehle schnell genug ist, unterstützt &lt;code>whisper.cpp&lt;/code> auch Hardwarebeschleunigung verschiedener GPUs und NPUs als Backends.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Apple Silicon (Mac/iOS)&lt;/strong>: Metal-API-Unterstützung über &lt;code>ggml-metal&lt;/code>. Ultraschnelle Inferenz mittels GPU.&lt;/li>
&lt;li>&lt;strong>NVIDIA GPU (Windows/Linux)&lt;/strong>: &lt;code>cuBLAS&lt;/code>-Unterstützung. Geben Sie beim CMake-Build &lt;code>-DWHISPER_CUBLAS=ON&lt;/code> an.&lt;/li>
&lt;li>&lt;strong>Intel (Windows/Linux)&lt;/strong>: Unterstützung für das &lt;code>OpenVINO&lt;/code>-Backend. Kann die NPU der neuesten Intel Core-Prozessoren nutzen.&lt;/li>
&lt;/ul>
&lt;p>Wenn Sie diese Beschleuniger in C++-Projekten verwenden, müssen Sie den Quellcode fast nicht ändern. Solange &lt;code>cparams.use_gpu = true;&lt;/code> bei der Kontextinitialisierung gesetzt ist, wird automatisch an die Hardware delegiert, basierend auf dem erstellten Backend.&lt;/p>
&lt;h3 id="73-abstimmung-von-caches-und-thread-anzahl">7.3 Abstimmung von Caches und Thread-Anzahl
&lt;/h3>&lt;p>Die Einstellung von &lt;code>wparams.n_threads&lt;/code> ist sehr wichtig. Ein bloßes Erhöhen der Thread-Anzahl wird die Leistung aufgrund eines Speicherbandbreiten-Engpasses (Memory Bound) nicht verbessern.&lt;/p>
&lt;p>Als Faustregel ist es ideal, die Anzahl der Threads mit der folgenden Formel zu bestimmen:&lt;/p>
$$ N_{\text{threads}} = \min(\text{Physische CPU-Kerne}, 4 \sim 8) $$
&lt;p>Wenn logische Kerne wie Hyper-Threading einbezogen werden, treten häufig Cache-Konflikte auf und die Inferenzgeschwindigkeit sinkt im Gegenteil. Daher ist es eine eiserne Regel, diese auf die &lt;strong>Anzahl der physischen Kerne&lt;/strong> einzustellen. Wenn Sie &lt;code>std::thread::hardware_concurrency()&lt;/code> in C++11 verwenden, gibt es die Anzahl der logischen Kerne zurück, daher wird empfohlen, die Anzahl der physischen Kerne fest zu codieren oder eine API auf Betriebssystemebene entsprechend Ihrer Umgebung zu verwenden, um sie zu erhalten.&lt;/p>
&lt;hr>
&lt;h2 id="8-zusammenfassung">8. Zusammenfassung
&lt;/h2>&lt;p>In diesem Artikel haben wir ausführlich, von der Theorie über die Praxis bis hin zur Optimierung, erklärt, wie man die modernste Spracherkennungs-KI mithilfe von &lt;code>whisper.cpp&lt;/code> in C++-Projekte integriert.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Einhaltung der Eingabeanforderungen&lt;/strong>: Strikte Einhaltung von 16 kHz, 1 Kanal, 32-Bit-Float.&lt;/li>
&lt;li>&lt;strong>Intuitive API-Nutzung&lt;/strong>: Ein einfaches Design, bei dem die Inferenz mit nur &lt;code>whisper_init_from_file_with_params&lt;/code> und &lt;code>whisper_full&lt;/code> abgeschlossen wird.&lt;/li>
&lt;li>&lt;strong>Echtzeitverarbeitung&lt;/strong>: Multithreading-Steuerung mit VAD und Sliding Window.&lt;/li>
&lt;li>&lt;strong>Überwältigende Optimierung&lt;/strong>: Vorteile der 4-Bit-Quantisierung durch &lt;code>ggml&lt;/code> und Hardware-Backends wie Metal/cuBLAS.&lt;/li>
&lt;/ul>
&lt;p>Bitte machen Sie sich &lt;code>whisper.cpp&lt;/code> zunutze, um Spracherkennungsanwendungen zu entwickeln, die nativ, schnell und sicher laufen, frei von der Abhängigkeit von riesigen Python-Umgebungen und Cloud-APIs. Eine lokal abgeschlossene KI wird aus Gründen des Datenschutzes und der Latenzzeit eine äußerst wichtige Schlüsseltechnologie in der zukünftigen Softwareentwicklung sein.&lt;/p></description></item></channel></rss>