Saltar al contenido
Volver al blog
8 min de lectura

IA on-device móvil: NPU, Whisper y privacidad real

Cómo ejecutar IA on-device móvil con TFLite, NNAPI y GPU delegate, transcribir voz con Whisper local y por qué la privacidad on-device no es marketing.

IAIA on-deviceEdgeReact NativeWhisperTFLite

Cada vez que una app móvil manda tu voz a un servidor para “entender” lo que dices, hay un coste oculto: latencia, una factura de inferencia que crece con cada usuario, y datos personales viajando a una nube que el usuario no controla. La alternativa lleva años madurando y hoy ya es viable en gama media: ejecutar el modelo dentro del teléfono. Esto es lo que he aprendido llevando IA on-device móvil a aplicaciones reales, desde recomendadores en React Native hasta transcripción de voz con Whisper.

Qué significa “on-device” y por qué importa

On-device es que la inferencia ocurre en el propio dispositivo, sin red. Suena obvio, pero cambia tres ecuaciones a la vez:

  • Privacidad real, no declarada. Si el audio o la imagen nunca salen del teléfono, no hay nada que filtrar, interceptar ni retener. Es el mismo principio que apliqué en RecruitSecure AI, donde el matching de candidatos corre 100% local con Transformers.js precisamente para no mover CVs a ningún servidor. La diferencia con un “no guardamos tus datos” es que aquí no hay datos que guardar.
  • Coste marginal cero. Una llamada a una API de transcripción cuesta dinero por minuto. Multiplica por 50.000 usuarios activos y el modelo de negocio se resiente. On-device, el cómputo lo paga el dispositivo del usuario: tu factura de inferencia es cero.
  • Offline y baja latencia. Sin ida y vuelta a la red, la respuesta es inmediata y funciona en el metro, en el campo o con cobertura intermitente. Para una app de campo offline-first como appxdata esto no es un lujo, es el requisito.

El precio a pagar es trabajar con cómputo limitado y con la fragmentación del hardware Android. Ahí es donde está la ingeniería de verdad.

El runtime: TFLite, NNAPI y el GPU delegate

En Android el caballo de batalla sigue siendo TensorFlow Lite (ahora LiteRT), y la decisión que más afecta al rendimiento no es el modelo, sino el delegate: a qué unidad del SoC delegas la inferencia.

  • CPU (XNNPACK). El camino seguro. Funciona en todos los dispositivos y para modelos pequeños cuantizados a int8 suele ser más que suficiente. Es el suelo del que parto siempre.
  • GPU delegate. Para modelos de visión con mucha convolución, mover la inferencia a la GPU baja la latencia y libera la CPU para la UI. El coste es un warm-up inicial (compilar los shaders) que conviene hacer fuera del hilo crítico.
  • NNAPI / NPU. La capa de Android que enruta hacia el acelerador neuronal (la NPU) cuando existe. Cuando funciona, es lo más eficiente en energía. El problema es la fragmentación: el mismo modelo puede volar en un Pixel y caer a CPU silenciosamente en otro fabricante. Por eso nunca asumo NPU: la trato como una optimización oportunista, con fallback a GPU y a CPU.

La regla práctica que sigo: cuantiza primero, acelera después. Pasar un modelo de float32 a int8 reduce el tamaño a una cuarta parte y muchas veces da más mejora real en gama media que pelearse con un delegate exótico. Y mide siempre la latencia de extremo a extremo —preprocesado incluido—, no solo el tiempo de inferencia, una lección que aprendí desplegando visión con YOLOv8 en el borde y que reaparece idéntica en móvil.

Tengo un precedente directo de esto en IoT: en PlantsCare la clasificación de imágenes de planta corre con EfficientNet-B0 sobre TensorFlow Lite, un modelo elegido por su relación tamaño/precisión justamente para vivir cerca del borde. El móvil es el mismo problema con otra carcasa.

React Native sin tirar de la nube

En React Native el patrón que me funciona es claro: el modelo y el preprocesado pesado van en un módulo nativo (Kotlin/Swift o C++ vía JSI), y JavaScript orquesta. Es exactamente la arquitectura de Cherry TV, donde el recomendador on-device y la búsqueda fuzzy sobre miles de canales se ejecutan en el dispositivo, con la lógica de IA en TypeScript y los módulos nativos en Kotlin para lo que toca al hardware. Hermes y la New Architecture ayudan, pero la decisión de fondo es no cruzar el puente JS por cada frame o cada token.

Whisper en el dispositivo: STT local de verdad

La transcripción de voz (STT) es el caso donde on-device más brilla, porque la voz es de lo más sensible que maneja una app. Whisper de OpenAI se puede ejecutar localmente gracias a whisper.cpp, que lo porta a C/C++ con cuantización agresiva y bindings para móvil.

Las decisiones que de verdad importan al integrar Whisper local:

  • Elige el tamaño correcto. tiny y base son los realistas en móvil; small ya pide gama alta. Para comandos cortos o dictado en español, base cuantizado da un equilibrio sensato entre precisión y consumo. El modelo grande “por si acaso” es la trampa de siempre.
  • Cuantización GGML/int8. Es lo que hace que el modelo quepa en RAM y no funda la batería. Sin cuantizar, Whisper en un teléfono no es práctico.
  • Trocea el audio con VAD. No transcribas streams largos de una sentada: usa detección de actividad de voz (VAD) para alimentar al modelo solo cuando alguien habla. Reduces cómputo y evitas alucinaciones en los silencios, un fallo típico de Whisper.
  • Fija el idioma si lo conoces. Forzar es evita que el modelo gaste pasos detectando idioma y reduce errores en frases cortas.

El resultado es dictado y comandos de voz que funcionan en avión, sin enviar un solo byte de audio a ningún sitio. Para una app de fitness donde el usuario quiere registrar series “con las manos ocupadas”, esto es la diferencia entre una función que se usa y una que depende de tener buena cobertura en el gimnasio del sótano.

Cerrando el bucle: TTS y avatar

El reverso del STT es la síntesis de voz (TTS). Android e iOS traen motores TTS nativos decentes y gratuitos (expo-speech en el ecosistema Expo los expone directamente), suficientes para respuestas habladas sin coste ni red. Si además quieres un avatar que mueva los labios, la pieza barata es mapear los visemas del TTS a blend shapes de un modelo 3D; no necesitas un modelo generativo en el dispositivo para que resulte creíble. Mi criterio: usa lo nativo y gratuito mientras cumpla, y reserva un modelo neuronal de voz solo si la naturalidad es parte del producto.

Una arquitectura on-device que aguanta producción

Junto todo en una pauta que repito proyecto a proyecto:

  1. Capa de abstracción del runtime. El código de la app no habla con TFLite ni con whisper.cpp directamente, sino con una interfaz InferenceEngine. Cambiar de delegate o de backend no debería tocar la UI (principio de inversión de dependencias, y de paso te facilita testear con un mock).
  2. Degradación en cascada. NPU → GPU → CPU, detectado en arranque y cacheado. Si el acelerador no está, la app funciona igual, solo que más despacio. Nunca un crash por hardware.
  3. Carga diferida del modelo. Los modelos pesan; no bloquees el arranque. Cárgalos en background tras el primer render y muestra estado mientras tanto.
  4. Presupuesto de batería y térmico. Inferencia continua calienta y vacía la batería. Para tareas en bucle (voz siempre activa, cámara en vivo) pon límites de frecuencia y respeta el modo de ahorro.
  5. Mide en dispositivos reales y baratos. El emulador miente y tu teléfono de gama alta también. La verdad está en un Android de gama media de hace tres años.

On-device no es “lo mismo pero sin servidor”. Es un cambio de restricciones: cambias coste de nube y riesgo de privacidad por una pelea con el hardware del usuario. Casi siempre vale la pena.

Cuándo NO hacerlo on-device

Por honestidad técnica: on-device no es la respuesta a todo. Modelos grandes de lenguaje generativo, tareas que necesitan datos centralizados frescos, o tareas donde la precisión absoluta pesa más que la privacidad y el coste, siguen pidiendo nube. El patrón híbrido —lo sensible y frecuente en local, lo pesado y ocasional en servidor— suele ser la respuesta adulta. Lo aplico en DevFlow AI, que es local-first pero deja la IA en la nube como opción, no como dependencia.

Cierre

La IA on-device móvil dejó de ser un experimento de laboratorio. Con TFLite/LiteRT y los delegates adecuados, Whisper cuantizado para la voz y TTS nativo para la respuesta, hoy puedes construir experiencias privadas, instantáneas y sin coste marginal que hace tres años exigían una nube cara. El trabajo difícil no es entrenar el modelo: es la ingeniería de sistemas alrededor —cuantización, fallbacks, presupuesto térmico, módulos nativos— que hace que funcione en el teléfono real de un usuario real.

Si estás construyendo una app móvil y quieres meter IA dentro del dispositivo —por privacidad, por coste o porque tiene que funcionar sin cobertura— y quieres una valoración honesta de qué es viable en el hardware de tus usuarios, hablemos. Es justo el tipo de problema en el que disfruto.