Volver al dev log

Dev log

DevLog #02: Cómo Construimos un Teleprompter de Estudio 100% Gratis y Sin Registro (Retos de Audio, Web Workers y Algoritmos)

Crónica técnica de cómo resolvimos el bloqueo de CoreAudio en macOS, sincronizamos karaoke inmune a la minimización con Web Workers y unificamos tomas WAV 48kHz en el navegador sin backend.

Por Equipo de Ingeniería · Arquitectura WebGPU & Audio

  • devlog
  • teleprompter
  • web audio api
  • web workers
  • youtube
  • ingenieria
  • wav 48khz

Si alguna vez has intentado buscar un teleprompter online para grabar un guion de YouTube, un reel o una lección de un curso, seguro conoces la frustración: la mayoría de herramientas web te obligan a crear una cuenta, te ponen marcas de agua, te cobran suscripciones mensuales de $15 USD o te llenan la pantalla de publicidad invasiva que distrae tu mirada de la cámara.

Nuestra premisa para el Teleprompter Online fue radical: **cero registro, cero publicidad, 100% privado en tu navegador y con calidad de estudio profesional (WAV 48 kHz y video HD)**. Pero construir una herramienta que funcione de forma impecable en cualquier dispositivo sin depender de servidores nos llevó a enfrentar retos de ingeniería web fascinantes.

Herramienta Interactiva

¿Quieres probar el Teleprompter de Estudio ahora?

Graba tus guiones con karaoke de velocidad ajustable, tomas concatenadas y cero límites. 100% gratis en tu navegador.

Reto 1: El Bloqueo de Hardware en CoreAudio (macOS) y WASAPI

Al principio, el medidor de volumen (VU meter), el grabador de audio WAV y el motor de reconocimiento abrían sus propias instancias de navigator.mediaDevices.getUserMedia(). En navegadores de escritorio, especialmente Chrome sobre macOS con procesadores Apple Silicon (M1/M2/M3), forzar sampleRate: 48000 en múltiples contextos de audio simultáneos provocaba una colisión en el demonio del sistema operativo (coreaudiod).

El resultado: el micrófono dejaba de responder silenciosamente o se colgaba en un estado zombi. Para resolverlo creamos la arquitectura **Single Audio Pipeline (AudioPipeline.ts)**.

Singleton maestro de audio con reloj nativo de hardware
// AudioPipeline.ts: 1 solo MediaStream maestro y 1 solo AudioContext
export class AudioPipeline {
  private static instance: AudioPipeline
  private audioContext: AudioContext | null = null
  private masterStream: MediaStream | null = null

  public async ensureReady(): Promise<void> {
    if (!this.masterStream || !this.masterStream.active) {
      this.masterStream = await navigator.mediaDevices.getUserMedia({
        audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false }
      })
      // Sin sampleRate forzado: se sincroniza con el reloj nativo del hardware
      this.audioContext = new AudioContext()
    }
  }

  public createTap(fftSize: number = 128): AudioTap {
    const analyser = this.audioContext.createAnalyser()
    this.sourceNode.connect(analyser)
    return { analyser, dispose: () => this.sourceNode.disconnect(analyser) }
  }
}

Reto 2: La Congelación en '1' del Contador 3-2-1

Un error común en aplicaciones web es solicitar permisos o inicializar grafos de audio en el momento exacto en que termina la cuenta regresiva. Si el navegador tarda 400 milisegundos en negociar el driver de audio, el contador visual se congela en el número '1' antes de saltar a la grabación.

Implementamos el patrón de grabación de los DAWs profesionales (como Pro Tools o Logic Pro): dividimos el motor en prepare() asíncrono (que adquiere el hardware antes de que comience el '3') y begin() 100% síncrono que inicia la captura en exactamente 0.0 milisegundos cuando el contador llega a cero.

Reto 3: Ejecución Inmune a Minimizar la Ventana (Web Workers)

Cuando grabas un video de YouTube o haces una presentación con diapositivas, es habitual minimizar la ventana del navegador o alternar entre aplicaciones como OBS Studio. Sin embargo, los navegadores modernos aplican un ahorro de energía agresivo: **congelan requestAnimationFrame a 0 FPS y reducen los setInterval a solo 1 tick por segundo**.

Para evitar que el teleprompter se desfasara o se detuviera al minimizar la pantalla, implementamos dos capas de resiliencia:

1. **Web Worker de Latidos Constantes**: Un hilo secundario aislado mediante un Blob URL que emite ticks ininterrumpidos independientemente del estado de la ventana. 2. **Avance Matemático por Timestamps (performance.now())**: En vez de sumar palabras secuencialmente (+1), calculamos la posición exacta: palabra = floor((tiempoActual - inicioFrase) / msPorPalabra). Si minimizas la pestaña por 8 segundos y regresas, el prompter salta exactamente a la frase y palabra precisa en la que deberías estar.

Reto 4: Ergonomía Móvil con Barras Táctiles Estilo iPhone

Los elementos <input type='range'> nativos de HTML son incómodos de usar en teléfonos: el punto de agarre es diminuto y se pierde fácilmente con el pulgar. Diseñamos un componente personalizado de 48px de alto inspirado en las cápsulas de control de brillo y volumen de iOS (IOSCapsuleSlider), con setPointerCapture para que puedas arrastrar suavemente o tocar en cualquier punto con respuesta visual instantánea.

Reto 5: Unir y Descargar Múltiples Tomas WAV en el Navegador

Al grabar un video largo, los creadores suelen hacer 3, 5 o 10 tomas cortas de diferentes párrafos. Subir estos archivos pesados a un servidor para unirlos añadiría tiempo de espera y consumiría ancho de banda.

Diseñamos un motor de concatenación WAV 100% del lado del cliente (wavUtils.ts). Decodifica los Blobs grabados en AudioBuffers, reserva una matriz continua en memoria con un micro-espacio de silencio de 250 ms entre tomas para evitar clics acústicos, y genera un archivo WAV master de 16 bits a 48.000 Hz listo para importar en Premiere, DaVinci Resolve o nuestro Editor de Video WebGPU.

Librerías y Tecnologías Utilizadas

• **Web Audio API (AudioContext, AudioWorklet)**: Captura lineal y procesamiento de audio sin filtros destructivos. • **fastest-levenshtein**: Algoritmo de distancia de edición ultra rápido para alineación fonética de texto. • **Web Workers (Inline Blobs)**: Temporización continua en segundo plano inmune a la minimización del navegador. • **WaveSurfer.js**: Visualización de forma de onda SoundCloud interactiva para reproducción de tomas. • **Tailwind CSS & Lucide Icons**: Interfaz oscura de estudio cinematográfico con diseño 100% responsivo.

Herramienta Interactiva

Comienza a Grabar tus Videos Hoy Mismo

Sin registro, sin descargas y sin pagar suscripciones. Todo tu flujo de grabación y edición en un solo lugar.

Prueba el editor tal como está hoy

Todo lo que lees en el dev log ya corre en la beta pública.