whisper.cpp incluye una ruta opcional de codificador Core ML para Apple Silicon. Es la función que esperarías que activara una app de dictado para Mac. Voice Type la desactiva a la fuerza y ejecuta el backend de Metal en su lugar.
El motivo es un desajuste de forma (shape), y proviene de cómo el dictado en vivo agrupa el audio en lotes.
TL;DR
- Un paquete de codificador Core ML compilado espera una forma de entrada fija.
- El dictado en vivo produce lotes de longitud variable, porque el agrupador se niega a cortar una frase por la mitad.
- Por eso Voice Type desactiva la ruta de Core ML al crear el contexto y ejecuta Metal, que acepta audio de longitud variable.
- Eliminar la ruta también eliminó una descarga de entre 163 MB y 1,17 GB por modelo.
Por qué los lotes varían de longitud
Voice Type no envía al reconocedor fragmentos de duración fija marcados por un temporizador. Un detector de actividad de voz en streaming marca las regiones de habla, y el agrupador acumula regiones completas. No divide una solo porque se haya disparado un temporizador.
Las reglas que deciden cuándo se envía un lote al modelo dependen todas del habla, no del reloj:
- El objetivo del lote en vivo es de 29 segundos, limitado a un rango de 15 a 29 segundos.
- Un lote de menos de 5 segundos nunca se envía por una pausa. Espera y la siguiente frase se le une.
- Un envío por pausa necesita al menos 400 ms de silencio tras una región de habla cerrada.
- Si añadir la siguiente región completa superaría el objetivo, primero se envía el lote actual y la región completa inicia el siguiente.
- Cuando sueltas la tecla de acceso rápido, lo que quede se envía sin importar la longitud.
La consecuencia es que la longitud del lote es una distribución, no una constante. Un lote puede durar 5 segundos o 31. Es el comportamiento correcto para el dictado, porque la alternativa es cortar una palabra por la mitad en el límite de una ventana.
Lo que eso cuesta en Core ML
Un modelo de Core ML se compila de antemano en un paquete .mlmodelc con sus dimensiones de entrada fijadas. Si le das audio de una longitud para la que no fue compilado, o bien rellenas hasta la forma fija, lo que supone pagar trabajo del codificador por silencio, o bien mantienes varias variantes compiladas, lo que supone varios paquetes en disco.
Voice Type no toma ninguna de las dos opciones. La ruta del codificador Core ML se desactiva a la fuerza donde se crea el contexto de whisper, con un comentario que nombra exactamente esto: las restricciones de entrada de forma fija. La política de backend selecciona entonces Metal por defecto, y recurre a la CPU solo en el simulador, cuando un ajuste del usuario desactiva la GPU o cuando el modo seguro se ha activado tras un fallo.
Metal acepta la longitud que produzca el agrupador.
Lo que liberó la eliminación
La compatibilidad con Core ML no solo se desactivó, se eliminó. Las compilaciones anteriores instalaban un paquete de codificador junto a los pesos de cada modelo, ggml-<name>-encoder.mlmodelc, que iba de unos 163 MB a 1,17 GB según el modelo. Esos paquetes se descargaban, se descomprimían y se preparaban por modelo.
Como ya no hay ninguna ruta de código que los elimine, la app incluye una migración única que barre los paquetes de codificador huérfanos del directorio de modelos al actualizar, con cuidado de no tocar nunca los pesos .bin que hay a su lado.
Así que el resultado visible para el usuario de desactivar Core ML es una descarga más pequeña y un directorio de modelos más pequeño, además de un reconocedor al que no le importa cuánto durara tu frase.
La rama discontinua es la ruta que la app deliberadamente no toma. Fuente: whisper.cpp.swift/LibWhisper.swift.
Qué ejecuta realmente Metal
Metal es la API de GPU de bajo nivel de Apple, y en esta app hace dos trabajos distintos.
El contexto de whisper se ejecuta en el backend de Metal, así que el codificador y el decodificador se ejecutan en la GPU. Aparte, el acondicionamiento de audio por lote se ejecuta como su propia etapa de procesamiento de señal antes de que el modelo vea nada: eliminación del desfase de continua (DC), los filtros y el control de volumen, y luego el remuestreo a los 16 kHz que espera el modelo.
Ambos leen de la memoria unificada, así que los búferes de audio no se copian a través de un bus entre la ruta de captura y el modelo.
Lo que no afirmamos
No publicamos aquí un tiempo de finalización. Actualmente no tenemos un script de benchmark que podamos entregarte junto con la cifra, y una cifra de latencia sin forma de reproducirla es marketing.
Lo que es estructural, y cierto sin benchmark: el trabajo que queda al soltar la tecla de acceso rápido está acotado por el objetivo del lote, no por cuánto tiempo hablaste. Un dictado de dos minutos y uno de treinta minutos terminan con la misma cantidad de trabajo pendiente.
Para medirlo en tu propio equipo, dicta la misma frase diez veces y cuenta el intervalo entre soltar la tecla de acceso rápido y la aparición del texto. Esa cifra es la que importa, y es tuya.
Compromisos
Tamaño del modelo frente a precisión. Los modelos más pequeños finalizan más rápido y se pierden más palabras. Voice Type incluye varios tamaños, de 27 MB a 550 MB, así que el compromiso lo decides tú.
Los modelos más grandes encajan con un Mac con Apple Silicon que tenga memoria unificada de sobra. Los más pequeños encajan con un equipo de 8 GB, donde un modelo mayor pasa el tiempo paginando en lugar de decodificando.
Relacionado: Resumen de la tecnología · Detección de actividad de voz · Demo de latencia
