Subtítulos (speech to text)¶
Sapsan puede reconocer la voz en un stream grabado y escribirla en una pista de subtítulos aparte. El reconocimiento corre en el motor Whisper integrado (whisper.cpp) sobre el archivo DVR: un worker en segundo plano lee el audio grabado, lo transcribe y añade fotogramas de subtítulos de vuelta al archivo. La pista de subtítulos se sirve luego en HLS y DASH como WebVTT.
Como el worker lee del archivo y no toca el stream en vivo, no puede romperlo: si el reconocimiento no da abasto, los subtítulos simplemente se atrasan y después se ponen al día. Por eso el stream debe tener el DVR activado.
Requisitos previos¶
-
Una compilación con la feature
whisper. El reconocimiento de voz enlaza una pila nativa whisper.cpp + ffmpeg, así que viene desactivado por defecto:bash make release FEATURES=whisper # o: cargo build --release --features whisperEn Apple Silicon añada Metal para la aceleración por GPU (mucho más rápido):
--features whisper,metal. -
DVR activado en el stream (el worker lee y escribe el archivo).
-
Un archivo de modelo. Los modelos se nombran por un nombre corto (
tiny,base,small,medium,large-v3); Sapsan resuelve el nombre a un archivo GGMLggml-<nombre>.binen el directorio de modelos:WHISPER_MODELS_DIRsi está definido, si no,~/.cache/whisper-models.
Descargue un modelo una sola vez, por ejemplo
medium:bash mkdir -p ~/.cache/whisper-models curl -L -o ~/.cache/whisper-models/ggml-medium.bin \ https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin
Configuración¶
Añada un bloque speech2text a un stream que ya tenga DVR:
streams:
news:
inputs:
- rtsp:
url: rtsp://admin:password@10.0.0.5/stream0
dvr:
root: /storage
speech2text:
model: medium # tiny | base | small | medium (por defecto) | large-v3
language: ru # ISO-639-1; omitir para autodetección
audio_track: a1 # pista de audio de origen (por defecto: la primera pista de audio)
max_window_secs: 30 # límite de la ventana de reconocimiento, s (por defecto 30, máx. 120)
Campos:
| Campo | Significado | Por defecto |
|---|---|---|
model |
Modelo por nombre corto; se resuelve en ggml-<nombre>.bin |
medium |
language |
Idioma del reconocimiento (ISO-639-1) | auto |
audio_track |
Identificador de la pista de audio de origen | la primera pista de audio |
max_window_secs |
Límite superior de la ventana de análisis | 30 |
Validación: un stream con speech2text pero sin dvr se rechaza; max_window_secs debe estar en 1..=120; language debe ser un código de 2–3 letras.
Los cambios se aplican al recargar (SIGHUP / central): el worker se reinicia solo si el bloque speech2text cambió de verdad.
Verificación offline (antes de activarlo en un stream)¶
El CLI subtitle (compilado con la feature whisper) ejecuta exactamente el mismo reconocedor de producción sobre un archivo local, escribe el resultado al lado y, si el archivo ya lleva una pista de subtítulos, calcula una métrica de cercanía. Es la forma más rápida de elegir modelo e idioma y de evaluar la calidad:
subtitle recognize movie.mkv --lang ru --model medium
# procesar solo un fragmento (p. ej., 2 minutos desde 25:00) para una comprobación rápida:
subtitle recognize movie.mkv --lang ru --start-sec 1500 --limit-sec 120
Archivos de salida, junto al archivo de entrada:
movie.subtitles.json— fotogramas estructurados de subtítulos con procedencia completa (ventana de audio, modelo, hash, prompt, diagnóstico por cue), suficiente para reproducir una ejecución;movie.vtt— la proyección WebVTT;movie.diff.txt— un lado a lado del texto de referencia contra el reconocido (cuando el archivo tiene una pista de subtítulos de referencia).
Si el archivo tiene subtítulos de referencia, el CLI imprime WER (word error rate) y CER (character error rate), globalmente y por ventana. Nota: contra una pista de subtítulos elaborada de forma independiente, el WER mide la divergencia de traducción, no el error de ASR — léalo como una señal relativa entre ejecuciones y revise el diff a ojo.
Cualquier archivo .mkv/.mp4 sirve como entrada.
Verificación en un stream¶
Una vez activado speech2text en un stream con DVR:
-
La información de medios del stream gana una pista de subtítulos. Compruebe el playlist maestro de HLS — ahora contiene un rendition
EXT-X-MEDIA:TYPE=SUBTITLES, y las variantes lo referencian conSUBTITLES="subs":bash curl -s "http://server/streaming/<stream>/index.m3u8" | grep -i subtitleEn DASH el manifiesto gana un
AdaptationSetconcontentType="text". -
Abra el archivo en un reproductor con soporte de subtítulos (o el URL de HLS/DASH) y active la pista de subtítulos. Los subtítulos aparecen con retraso mientras el worker alcanza el borde en vivo, y luego lo siguen.
-
Vigile los contadores del reconocimiento en el endpoint de métricas (segundos procesados, tamaño del hueco / retraso, errores).
Como el worker no tiene estado — el progreso se deduce del borde de la pista de subtítulos en el archivo —, tras un reinicio continúa desde el mismo hueco, completa con subtítulos el archivo ya acumulado y nunca duplica un fotograma.
Cómo funciona¶
La unidad de trabajo del worker es el hueco entre la cobertura del audio y la cobertura de los subtítulos en el archivo. Lee el audio del hueco, lo decodifica a PCM mono de 16 kHz, pasa Whisper por ventanas deslizantes (con un gate de silencio contra las alucinaciones y reanclaje en los segmentos completos) y añade fotogramas estructurados de subtítulos. El WebVTT entregado a los reproductores es una proyección de esos fotogramas; los fotogramas almacenados guardan además procedencia y diagnóstico de Whisper para la depuración.