<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Whisper on kenji.blog</title><link>http://kenji.blog/es/tags/whisper/</link><description>Recent content in Whisper on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>es</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/es/tags/whisper/index.xml" rel="self" type="application/rss+xml"/><item><title>Cómo integrar la IA de reconocimiento de voz (Whisper) en un proyecto C++</title><link>http://kenji.blog/es/p/whisper-cpp-integration-guide/</link><pubDate>Fri, 11 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/es/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 Cómo integrar la IA de reconocimiento de voz (Whisper) en un proyecto C++" />&lt;h2 id="1-introducción-por-qué-reconocimiento-de-voz-en-c">1. Introducción: ¿Por qué reconocimiento de voz en C++?
&lt;/h2>&lt;p>El modelo de reconocimiento de voz de alta precisión &amp;ldquo;Whisper&amp;rdquo;, desarrollado por OpenAI, ha sido utilizado en diversas aplicaciones desde que se convirtió en código abierto. Aunque su uso en entornos Python (basados en PyTorch) es común, al integrarlo en &lt;strong>dispositivos edge (teléfonos inteligentes, equipos IoT, sistemas embebidos)&lt;/strong> o en &lt;strong>aplicaciones nativas de C++ que requieren alta capacidad de tiempo real&lt;/strong> (motores de juegos, software DAW, robótica, etc.), la dependencia del intérprete de Python se convierte en un importante cuello de botella para el rendimiento.&lt;/p>
&lt;p>Aquí es donde entra en juego el salvador: &lt;strong>&lt;a class="link" href="https://github.com/ggerganov/whisper.cpp" target="_blank" rel="noopener"
>whisper.cpp&lt;/a>&lt;/strong>, desarrollado por Georgi Gerganov. Esta biblioteca, basada en la biblioteca de cálculo tensorial para aprendizaje automático &lt;code>ggml&lt;/code>, reduce las dependencias al límite y logra la inferencia de Whisper únicamente con C/C++.&lt;/p>
&lt;p>En este artículo, explicaremos exhaustivamente cómo utilizar &lt;code>whisper.cpp&lt;/code> para integrar funciones de reconocimiento de voz de primer nivel en sus propios proyectos C++, abarcando desde los fundamentos del procesamiento de señales de audio, el uso detallado de la API, la gestión de memoria, la optimización de múltiples hilos, hasta los patrones de implementación del procesamiento en tiempo real.&lt;/p>
&lt;hr>
&lt;h2 id="2-procesamiento-de-señales-de-audio-y-requisitos-de-entrada-de-whisper">2. Procesamiento de señales de audio y requisitos de entrada de Whisper
&lt;/h2>&lt;p>Para que la IA entienda el habla, es necesario convertir el &amp;ldquo;sonido&amp;rdquo; (una señal analógica) en datos digitales y transformarlo a un formato (tensor) que el modelo de IA pueda procesar. El formato de audio que exige Whisper es muy estricto.&lt;/p>
&lt;h3 id="21-formato-de-audio-exigido-por-whisper">2.1 Formato de audio exigido por Whisper
&lt;/h3>&lt;p>El modelo Whisper acepta como entrada datos de audio con las siguientes especificaciones:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Frecuencia de muestreo (Sample Rate)&lt;/strong>: 16,000 Hz (16 kHz)&lt;/li>
&lt;li>&lt;strong>Número de canales (Channels)&lt;/strong>: 1 (monoaural)&lt;/li>
&lt;li>&lt;strong>Tipo de datos (Data Type)&lt;/strong>: Número de punto flotante de 32 bits (&lt;code>float&lt;/code> en C/C++)&lt;/li>
&lt;li>&lt;strong>Normalización (Normalization)&lt;/strong>: Valores escalados en el rango de $[-1.0, 1.0]$&lt;/li>
&lt;/ul>
&lt;p>Por ejemplo, si se introduce un archivo de audio con calidad de CD (44.1kHz, estéreo, PCM de 16 bits), se debe realizar previamente un submuestreo (downsampling), una mezcla de canales (mixdown) y una conversión de formato.&lt;/p>
&lt;p>La fórmula para calcular la tasa de transferencia de datos es la siguiente:&lt;/p>
$$ \text{Data Rate (bytes/sec)} = \text{Sample Rate} \times \text{Channels} \times \frac{\text{Bit Depth}}{8} $$
&lt;p>El tamaño de los datos por segundo bajo los requisitos de Whisper (16kHz, 1 canal, Float de 32 bits) es:&lt;/p>
$$ 16000 \times 1 \times \frac{32}{8} = 64,000 \text{ bytes/sec (64 KB/s)} $$
&lt;p>Al ser muy ligero, es completamente posible realizar el almacenamiento en búfer (buffering) incluso en dispositivos edge con ancho de banda de memoria limitado.&lt;/p>
&lt;h3 id="22-matemáticas-de-la-conversión-del-espectrograma-de-mel">2.2 Matemáticas de la conversión del espectrograma de Mel
&lt;/h3>&lt;p>Internamente, Whisper no procesa directamente los datos de forma de onda de audio unidimensional (Raw Waveform). Antes de ingresar al modelo Transformer, se convierte a un &lt;strong>espectrograma de Mel (Mel-Spectrogram)&lt;/strong>, que es una representación de frecuencia cercana a las características de la audición humana. &lt;code>whisper.cpp&lt;/code> incluye este proceso de conversión dentro de su implementación en C++, pero comprender su mecanismo es útil para lidiar con el ruido y optimizar el preprocesamiento.&lt;/p>
&lt;p>La fórmula para convertir la frecuencia normal $f$ (Hz) a la escala Mel $m$ se aproxima de la siguiente manera:&lt;/p>
$$ m = 2595 \log_{10} \left( 1 + \frac{f}{700} \right) $$
&lt;p>A la inversa, la conversión inversa de la escala Mel a la frecuencia es la siguiente:&lt;/p>
$$ f = 700 \left( 10^{\frac{m}{2595}} - 1 \right) $$
&lt;p>Además, la forma de onda de audio se convierte al dominio del tiempo y la frecuencia mediante la &lt;strong>Transformada de Fourier de Corto Tiempo (STFT: Short-Time Fourier Transform)&lt;/strong>. La forma discreta de STFT usando una función de ventana $w(n)$ se expresa de la siguiente manera:&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>(Aquí, $N$ es el tamaño de la ventana FFT, $H$ es el tamaño del salto (hop size) y $w(n)$ es una función de ventana, como la ventana de Hann)&lt;/em>&lt;/p>
&lt;p>El modelo Whisper normalmente utiliza un tamaño de ventana $N = 400$ (25ms), un tamaño de salto $H = 160$ (10ms) y un banco de filtros Mel de 80 dimensiones. Esta extracción de características se ejecuta automáticamente (y a alta velocidad utilizando instrucciones SIMD) cuando se llama a &lt;code>whisper_full()&lt;/code> dentro de &lt;code>whisper.cpp&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="3-arquitectura-y-diseño-del-pipeline">3. Arquitectura y diseño del pipeline
&lt;/h2>&lt;p>Diseñemos un pipeline de procesamiento de audio en una aplicación C++. Es el flujo que comienza desde la entrada de archivo o micrófono, pasa por el preprocesamiento, la inferencia mediante &lt;code>whisper.cpp&lt;/code>, y termina en la salida de texto.&lt;/p>
&lt;div class="mermaid">graph TD
A["Fuente de Audio (Micrófono/Archivo)"] -->|Bytes Crudos, ej. 48kHz Estéreo| B["Decodificador de Audio &amp; Resampler (FFmpeg/miniaudio)"]
B -->|16kHz Mono 32-bit Float| C["Búfer Circular / Arreglo de Memoria"]
C -->|Alimentar Datos PCM| D["Núcleo de whisper.cpp (ggml)"]
D --> E["Extracción del Espectrograma de Mel"]
E --> F["Codificador-Decodificador Transformer"]
F --> G["Generación de Tokens de Texto"]
G --> H["Salida de Texto (Cadena UTF-8)"]&lt;/div>
&lt;p>La aplicación debe ser responsable de la &lt;strong>sección desde A hasta C en el diagrama anterior (decodificación de audio y remuestreo)&lt;/strong>. Dado que &lt;code>whisper.cpp&lt;/code> en sí mismo no incluye un decodificador de archivos de audio, la mejor práctica es utilizarlo en combinación con bibliotecas como FFmpeg o &lt;code>miniaudio&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="4-compilación-e-integración-de-whispercpp">4. Compilación e integración de whisper.cpp
&lt;/h2>&lt;p>Estos son los pasos para integrar &lt;code>whisper.cpp&lt;/code> en su proyecto. Usar CMake es lo más versátil.&lt;/p>
&lt;h3 id="configuración-de-cmakeliststxt">Configuración de CMakeLists.txt
&lt;/h3>&lt;p>&lt;code>whisper.cpp&lt;/code> se puede incorporar al proyecto como código fuente o agregarse como submódulo y enlazarse.&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"># Habilitación de instrucciones extendidas de CPU (AVX, F16C, etc.)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Para MacOS, el framework NEON/Accelerate se habilita automáticamente
&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>Con esta configuración, el backend &lt;code>ggml&lt;/code> altamente optimizado de &lt;code>whisper.cpp&lt;/code> se compilará y se enlazará estáticamente a su aplicación.&lt;/p>
&lt;hr>
&lt;h2 id="5-detalles-y-pasos-de-implementación-de-la-api-de-c">5. Detalles y pasos de implementación de la API de C++
&lt;/h2>&lt;p>Ahora, explicaremos cómo llamar a la API observando el código C++ real.&lt;/p>
&lt;h3 id="51-inicialización-del-contexto-y-carga-del-modelo">5.1 Inicialización del contexto y carga del modelo
&lt;/h3>&lt;p>En &lt;code>whisper.cpp&lt;/code>, todos los estados y asignaciones de memoria se gestionan a través de la estructura &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. Inicialización de parámetros
&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">// Usar aceleración GPU (CuBLAS/Metal) si está disponible
&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. Carga del modelo (modelo binario en formato 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;Error: Fallo al cargar el modelo - &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;Modelo cargado con éxito.&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>Los archivos del modelo están en un formato &lt;code>.bin&lt;/code> cuantizado de manera propietaria. Puede utilizar los scripts de conversión en el repositorio oficial o descargarlos directamente de HuggingFace. En entornos con estrictas limitaciones de memoria, el uso de modelos cuantizados de 4 bits (por ejemplo, &lt;code>ggml-base-q4_0.bin&lt;/code>) puede reducir el consumo de RAM a aproximadamente 1/4.&lt;/p>
&lt;h3 id="52-configuración-de-parámetros-de-inferencia">5.2 Configuración de parámetros de inferencia
&lt;/h3>&lt;p>A continuación, configure &lt;code>whisper_full_params&lt;/code>, que controla el comportamiento de la inferencia.&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. Configuración de los parámetros para inferencia completa (usando 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">// Configuración del número de hilos (lo óptimo es ajustarlo al número de núcleos físicos de la 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">// Configuración de idioma (detección automática es &amp;#34;auto&amp;#34;, para japonés se especifica &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">// Suprimir la salida estándar de resultados intermedios (para controlarlo dentro de la aplicación)
&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">// Función de traducción (true si se traduce directamente audio en japonés a texto en inglés)
&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-preparación-de-datos-de-audio-y-ejecución-de-la-inferencia">5.3 Preparación de datos de audio y ejecución de la inferencia
&lt;/h3>&lt;p>Aquí asumimos que los datos de audio a 16kHz ya están almacenados en un &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">// Datos de audio virtuales (en realidad, datos PCM obtenidos de un archivo o micrófono)
&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 segundos (16000 Hz * 3 seg = 48000 muestras)
&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. Ejecución de la inferencia
&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;Error: Fallo al ejecutar 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-extracción-de-resultados">5.4 Extracción de resultados
&lt;/h3>&lt;p>Cuando &lt;code>whisper_full&lt;/code> se completa, los resultados del reconocimiento se guardan en el contexto por segmentos.&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. Obtención y visualización de los resultados
&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">// Obtención de marcas de tiempo (unidad: 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. Liberación de memoria
&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>Este bloque de código sirve como la plantilla más básica para usar Whisper en C++.&lt;/p>
&lt;hr>
&lt;h2 id="6-implementación-avanzada-del-reconocimiento-de-voz-en-tiempo-real">6. Implementación avanzada del reconocimiento de voz en tiempo real
&lt;/h2>&lt;p>Procesar archivos pregrabados es sencillo, pero para mejorar la experiencia de usuario (UX) de una aplicación, se necesita el &amp;ldquo;reconocimiento de voz en tiempo real (reconocimiento en streaming)&amp;rdquo; desde la entrada de un micrófono.&lt;/p>
&lt;p>Para implementar esto, es indispensable gestionar el flujo de audio mediante una arquitectura de múltiples hilos y un búfer circular (Ring Buffer).&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "Hilo de Audio (Alta Prioridad)"
A["API de Captura de Audio (CoreAudio/WASAPI/ALSA)"] -->|Callback| B["Resampler (a 16kHz)"]
B --> C["Búfer Circular"]
end
subgraph "Hilo Principal / Hilo de Trabajo"
C -->|Extraer fragmento de 30ms-1000ms| D["Detección de Actividad de Voz (VAD)"]
D -->|Si se detecta voz| E["Acumular Búfer PCM"]
E -->|Activar Inferencia| F["whisper_full()"]
F --> G["Actualizar UI/Texto"]
end&lt;/div>
&lt;h3 id="61-importancia-de-la-detección-de-actividad-de-voz-vad">6.1 Importancia de la Detección de Actividad de Voz (VAD)
&lt;/h3>&lt;p>En el procesamiento en tiempo real, ejecutar constantemente la inferencia, incluso en partes silenciosas, es un desperdicio de recursos computacionales. Al intercalar un algoritmo VAD (como el procesamiento de umbral basado en energía simple o WebRTC VAD) en la etapa preliminar, se realiza el control de &lt;strong>&amp;ldquo;iniciar el almacenamiento en búfer solo cuando se inicia el habla, y activar &lt;code>whisper_full&lt;/code> en el momento en que el habla termina (un cierto tiempo de silencio)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="62-enfoque-de-ventana-deslizante-sliding-window">6.2 Enfoque de ventana deslizante (Sliding Window)
&lt;/h3>&lt;p>Cuando el habla continúa por mucho tiempo, se utiliza la técnica de &amp;ldquo;ventana deslizante&amp;rdquo;, que recorta fragmentos cada pocos segundos y realiza la inferencia. Sin embargo, si simplemente se corta el audio bruscamente, se cortará a mitad de las palabras y la precisión del reconocimiento disminuirá drásticamente.&lt;/p>
&lt;p>Como contramedida, se utiliza una técnica en la que &lt;strong>&amp;ldquo;siempre se incluye el contexto de los últimos N segundos pasados para realizar la inferencia&amp;rdquo;&lt;/strong> (superposición). &lt;code>whisper.cpp&lt;/code> también tiene una función llamada &lt;code>wparams.prompt_tokens&lt;/code> que transfiere tokens de texto anteriores como indicaciones (prompts), lo que permite un reconocimiento en streaming de alta precisión manteniendo el contexto.&lt;/p>
&lt;hr>
&lt;h2 id="7-gestión-de-memoria-y-optimización-para-dispositivos-edge">7. Gestión de memoria y optimización para dispositivos edge
&lt;/h2>&lt;p>Profundizaremos en el rendimiento y la eficiencia de la memoria, que son las mayores ventajas de &lt;code>whisper.cpp&lt;/code>.&lt;/p>
&lt;h3 id="71-el-poder-de-la-biblioteca-de-tensores-ggml">7.1 El poder de la biblioteca de tensores ggml
&lt;/h3>&lt;p>El backend de &lt;code>whisper.cpp&lt;/code>, &lt;code>ggml&lt;/code>, es una biblioteca de tensores en C sin dependencias. Su mayor característica es que admite la &lt;strong>cuantización dinámica (Quantization) de los datos de los pesos&lt;/strong>.&lt;/p>
&lt;p>Por ejemplo, calculemos el tamaño de memoria del modelo Whisper &lt;code>Small&lt;/code> (aproximadamente 240 millones de parámetros).
En el caso normal (Float de 16 bits = 2 bytes):&lt;/p>
$$ \text{Memory (FP16)} \approx 244,000,000 \times 2 \text{ bytes} \approx 488 \text{ MB} $$
&lt;p>Si se convierte a cuantización de 4 bits (formato Q4_0), será en promedio 0.5 bytes por parámetro (aproximadamente 0.56 bytes si se incluye la sobrecarga como los factores de escala).&lt;/p>
$$ \text{Memory (Q4\_0)} \approx 244,000,000 \times 0.56 \text{ bytes} \approx 137 \text{ MB} $$
&lt;p>En entornos con estrictas limitaciones de RAM, como dispositivos iOS o Raspberry Pi, esta reducción de la huella de memoria (memory footprint) se relaciona directamente con la estabilidad general de la aplicación.&lt;/p>
&lt;h3 id="72-uso-de-la-aceleración-por-hardware">7.2 Uso de la aceleración por hardware
&lt;/h3>&lt;p>Aunque es lo suficientemente rápido solo con la CPU usando instrucciones AVX2 o NEON, &lt;code>whisper.cpp&lt;/code> también admite varios tipos de aceleración de hardware de GPU/NPU como backend.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Apple Silicon (Mac/iOS)&lt;/strong>: Soporte para Metal API mediante &lt;code>ggml-metal&lt;/code>. Inferencia ultra rápida utilizando la GPU.&lt;/li>
&lt;li>&lt;strong>NVIDIA GPU (Windows/Linux)&lt;/strong>: Soporte para &lt;code>cuBLAS&lt;/code>. Especifique &lt;code>-DWHISPER_CUBLAS=ON&lt;/code> al compilar con CMake.&lt;/li>
&lt;li>&lt;strong>Intel (Windows/Linux)&lt;/strong>: Soporte para el backend &lt;code>OpenVINO&lt;/code>. Permite aprovechar la NPU en los procesadores Intel Core más recientes.&lt;/li>
&lt;/ul>
&lt;p>Al utilizar estos aceleradores en un proyecto de C++, casi no es necesario modificar el código fuente. Siempre que se configure &lt;code>cparams.use_gpu = true;&lt;/code> al inicializar el contexto, se descargará automáticamente en el hardware según el backend compilado.&lt;/p>
&lt;h3 id="73-ajuste-de-caché-y-número-de-hilos">7.3 Ajuste de caché y número de hilos
&lt;/h3>&lt;p>La configuración de &lt;code>wparams.n_threads&lt;/code> es muy importante. Aumentar a ciegas el número de hilos no mejorará el rendimiento debido a los cuellos de botella del ancho de banda de la memoria (Memory Bound).&lt;/p>
&lt;p>Como regla empírica, lo ideal es determinar el número de hilos utilizando la siguiente fórmula:&lt;/p>
$$ N_{\text{threads}} = \min(\text{Physical CPU Cores}, 4 \sim 8) $$
&lt;p>Si se incluyen los núcleos lógicos, como en el Hyper-Threading, a menudo se producen conflictos en la caché y la velocidad de inferencia disminuye; por lo tanto, la regla general es establecerlo en el &lt;strong>número de núcleos físicos&lt;/strong>. Como el uso de &lt;code>std::thread::hardware_concurrency()&lt;/code> en C++11 devuelve el número de núcleos lógicos, se recomienda codificar esto (hardcode) según el entorno u obtener el número de núcleos físicos utilizando APIs a nivel del sistema operativo.&lt;/p>
&lt;hr>
&lt;h2 id="8-conclusión">8. Conclusión
&lt;/h2>&lt;p>En este artículo, hemos explicado en detalle cómo utilizar &lt;code>whisper.cpp&lt;/code> para integrar la IA de reconocimiento de voz de primer nivel en proyectos C++, desde la teoría hasta la práctica y la optimización.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cumplimiento de los requisitos de entrada&lt;/strong>: Apego estricto a 16kHz, 1 canal, Float de 32 bits.&lt;/li>
&lt;li>&lt;strong>Uso intuitivo de la API&lt;/strong>: Un diseño simple en el que la inferencia se completa solo con &lt;code>whisper_init_from_file_with_params&lt;/code> y &lt;code>whisper_full&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Procesamiento en tiempo real&lt;/strong>: Control de múltiples hilos mediante VAD y ventana deslizante.&lt;/li>
&lt;li>&lt;strong>Optimización asombrosa&lt;/strong>: Los beneficios de la cuantización de 4 bits con &lt;code>ggml&lt;/code> y los backends de hardware como Metal/cuBLAS.&lt;/li>
&lt;/ul>
&lt;p>Corte la dependencia de entornos de Python enormes y de las APIs en la nube, y utilice &lt;code>whisper.cpp&lt;/code> para el desarrollo de aplicaciones de procesamiento de audio que se ejecuten de manera rápida y segura en entornos nativos. Desde el punto de vista de la protección de la privacidad y la latencia, la IA de ejecución local será una tecnología clave extremadamente importante en el desarrollo de software del futuro.&lt;/p></description></item></channel></rss>