mcp-video-analyzer

Convierte cualquier video — YouTube, Instagram, TikTok, Loom, URLs directas o archivos locales — en transcripciones, fotogramas clave, texto OCR y metadatos para agentes de IA.

Documentación

mcp-video-analyzer

mcp-video-analyzer

Convierte cualquier video — YouTube, Instagram, TikTok, Loom, X, Vimeo, enlaces directos, archivos locales — en transcripciones, fotogramas clave, texto OCR y metadatos para agentes de IA.

npm license awesome-mcp-servers mcpservers.org

mcp-video-analyzer MCP server

Ningún MCP de video existente combina transcripciones + fotogramas visuales + metadatos en una sola herramienta. Este lo hace — en Loom, las principales plataformas de yt-dlp (YouTube/Vimeo/TikTok/Instagram/X/Twitch/Dailymotion/Facebook), URLs de video directas y archivos locales.

¿Quieres un pipeline completo, no solo una herramienta? social-knowledge-base está construido sobre este servidor — descarga cuentas completas de creadores de Instagram (reels, stories, destacados), las transcribe y convierte el resultado en una base de conocimiento buscable y consultable por RAG con notas generadas por IA. Usa este MCP cuando quieras análisis por video dentro de un agente; usa social-knowledge-base cuando quieras archivar y consultar una cuenta completa.

Instalación

Requisitos previos

  • Node.js 22.12+ — necesario para ejecutar el servidor mediante npx
  • yt-dlprequerido para URLs de YouTube/Vimeo/TikTok/Instagram/X/Twitch/Dailymotion/Facebook; opcional para todo lo demás (mejora la calidad de descarga de Loom). Instálalo con pip install yt-dlp
  • Chrome/Chromium (opcional) — alternativa para extracción de fotogramas si yt-dlp no está disponible

Sin yt-dlp o Chrome, las URLs directas y los archivos locales aún obtienen fotogramas — el ffmpeg-static incluido realiza la extracción, y Loom recurre a la descarga desde su propio CDN. Las URLs de plataformas (YouTube, etc.) se degradan a una advertencia clara de "instala yt-dlp". Las transcripciones, metadatos y comentarios nunca requieren ninguno de ellos.

Hay tres formas de acceso: el plugin de /video (Claude Code — comando de barra + servidor MCP auto-configurado), una configuración de servidor MCP estándar (cualquier cliente MCP), o la habilidad portátil + CLI (Codex, Cursor, Copilot y cualquier agente con shell — sin necesidad de MCP).

Claude Code — plugin de /video (recomendado)

/plugin marketplace add guimatheus92/mcp-video-analyzer
/plugin install video@mcp-video-analyzer

Esto añade el comando de barra /video y registra automáticamente el servidor MCP — sin necesidad de claude mcp add:

/video https://youtu.be/jNQXAC9IVRw what happens at 0:10?
/video ~/Movies/screen-recording.mp4 when does the UI break?

Otros agentes — Codex, Cursor, Copilot, Gemini CLI, …

npx skills add guimatheus92/mcp-video-analyzer

Instala la habilidad video (formato Agent Skills) en cada agente detectado en tu máquina. Los agentes sin el servidor MCP configurado recurren automáticamente a la CLI incluida — configuración cero.

Claude Code (solo MCP)

claude mcp add video-analyzer -- npx mcp-video-analyzer@latest

Luego reinicia Claude Code o inicia una nueva conversación.

VS Code / Cursor

Añade a tu archivo de configuración de MCP:

  • VS Code: File → Preferences → Settings → search "MCP" o edita ~/.vscode/mcp.json / %APPDATA%\Code\User\mcp.json (Windows)
  • Cursor: Settings → MCP Servers → Add
{
  "servers": {
    "mcp-video-analyzer": {
      "type": "stdio",
      "command": "npx",
      "args": ["mcp-video-analyzer@latest"]
    }
  }
}

Luego recarga la ventana (Ctrl+Shift+P → "Developer: Reload Window").

Claude Desktop

Añade a tu archivo de configuración de Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "video-analyzer": {
      "command": "npx",
      "args": ["mcp-video-analyzer@latest"]
    }
  }
}

Luego reinicia Claude Desktop.

CLI (de un solo uso, sin cliente MCP)

El mismo motor se expone como un comando de un solo uso — esto es lo que usa la habilidad video en agentes sin MCP, y funciona de forma independiente en cualquier terminal:

npx -y mcp-video-analyzer@latest analyze "https://youtu.be/jNQXAC9IVRw"

La salida estándar es un único documento JSON — metadata, transcript, ocrResults, timeline, warnings, frameCount y frames como entradas de { time, filePath, mimeType } que apuntan a fotogramas clave JPEG copiados a --out (por defecto: el directorio de caché por usuario — %LOCALAPPDATA% en Windows, ~/Library/Caches en macOS, $XDG_CACHE_HOME o ~/.cache en Linux — bajo mcp-video-analyzer/<url-hash>/; establece MCP_CACHE_DIR a una ruta absoluta para reubicarlo). A diferencia del directorio temporal donde solía vivir, nada elimina esa ubicación, por lo que los fotogramas persisten hasta que los borres — los directorios se crean 0700. El progreso se transmite por stderr, por lo que stdout se puede canalizar directamente a un analizador JSON. Los fallos parciales terminan en warnings con código de salida 0; solo los fallos graves salen con 1.

IndicadorDescripción
--detail <level>brief (metadatos + transcripción, sin fotogramas), standard (por defecto), detailed
--max-frames <n>Máximo de fotogramas clave, 1–60 (el valor por defecto se adapta a la duración)
--max-width <px>Límite de ancho para los fotogramas emitidos (por defecto 800, o MCP_FRAME_MAX_WIDTH); 0 mantiene la resolución original — ver Tamaño de fotograma
--fields <list>Filtro de salida — subconjunto separado por comas: metadata,transcript,frames,comments,chapters,ocrResults,timeline,aiSummary. Filtra solo el JSON emitido; usa --detail brief para omitir realmente la descarga/extracción de fotogramas
--force-refreshOmite la caché y vuelve a analizar
--ocr-language <codes>Idiomas de Tesseract (por defecto eng+por)
--model <name> / --language <code>Anulaciones de Whisper para la transcripción de respaldo
--out <dir>Dónde se copian las imágenes de los fotogramas

Ejecuta sin argumentos (npx mcp-video-analyzer@latest) para iniciar el servidor MCP stdio — la CLI es puramente aditiva.

Verifica que funciona

Una vez instalado, pregunta a tu asistente de IA:

Analyze this video: https://www.youtube.com/watch?v=jNQXAC9IVRw

(también funciona con un enlace de Instagram/TikTok/Loom, una URL directa de .mp4 o una ruta de archivo local). Si el servidor está conectado, llamará automáticamente a la herramienta analyze_video.

Herramientas

Ocho herramientas — la IA elige la más económica para la tarea y la llama automáticamente. Haz clic en cualquier herramienta para expandir sus parámetros y ejemplos.

HerramientaQué hace
analyze_videoAnálisis completo: transcripción + fotogramas clave + OCR + línea de tiempo + metadatos
analyze_videosVersión por lotes, un resultado estructurado por fuente (reanudable)
get_transcriptSolo transcripción (subtítulos nativos o respaldo de Whisper)
get_metadataMetadatos + comentarios + capítulos, sin descarga
get_framesSolo fotogramas clave (detección de cambio de escena o muestreo denso de 1 fps)
analyze_momentAnálisis profundo de un rango de tiempo (ráfaga de fotogramas + transcripción + OCR)
get_frame_atUn solo fotograma en una marca de tiempo
get_frame_burstN fotogramas en una ventana estrecha (movimiento/animación)
analyze_video — análisis completo de video

Extrae todo de una URL de video en una sola llamada:

> Analyze this video: https://www.youtube.com/watch?v=abc123...

Devuelve:

  • Transcripción con marcas de tiempo y hablantes
  • Fotogramas clave extraídos mediante detección de cambio de escena (deduplicados automáticamente). Para clips estáticos sin cortes de escena — p. ej., Reels/Stories de personas hablando donde solo cambia una superposición de texto en pantalla — recurre automáticamente a un muestreo temporal uniforme para que aún obtengas fotogramas (y OCR) en lugar de un resultado vacío.
  • Texto OCR extraído de los fotogramas (código, mensajes de error, texto de interfaz, precios/fechas/CTAs visibles en pantalla)
  • Línea de tiempo anotada que fusiona transcripción + fotogramas + OCR en una vista unificada de "qué pasó y cuándo"
  • Metadatos (título, duración, plataforma)
  • Comentarios de los espectadores
  • Capítulos y resumen de IA (cuando estén disponibles)

La IA llamará automáticamente a esta herramienta cuando vea una URL de video — no es necesario pedirlo.

Opciones:

  • detail — profundidad de análisis: "brief" (metadatos + transcripción truncada, sin fotogramas), "standard" (por defecto), "detailed" (muestreo denso, más fotogramas)
  • fields — matriz de campos específicos a devolver, p. ej. ["metadata", "transcript"]. Disponibles: metadata, transcript, frames, comments, chapters, ocrResults, timeline, aiSummary
  • maxFrames (1-60) — límite de fotogramas extraídos. El valor por defecto escala con la duración del video en detalle standard (~12 para ≤30s hasta 60 para >10min); fijo en 60 en detailed, 0 en brief. Un valor explícito siempre gana
  • threshold (0.0-1.0, por defecto 0.1) — sensibilidad de cambio de escena
  • forceRefresh — omite la caché y vuelve a analizar
  • skipFrames — omite la extracción de fotogramas para análisis solo de transcripción
  • model / language / initialPrompt — anulaciones de Whisper por llamada para la transcripción de respaldo (anula WHISPER_MODEL / WHISPER_LANGUAGE / WHISPER_PROMPT solo para esta llamada — elige un modelo más pesado o un glosario de dominio para un clip difícil sin reiniciar el servidor)
analyze_videos — análisis por lotes
> Analyze every .mp4 in this folder

Ejecuta analyze_video sobre una lista de sources con un límite de concurrency (por defecto 2), devolviendo un resultado estructurado por fuente — recuentos + advertencias en caso de éxito, o un error por elemento en caso de fallo (un archivo defectuoso nunca aborta el lote). Las imágenes de fotogramas no se incrustan y la transcripción/OCR/línea de tiempo completos se devuelven solo cuando fields está establecido; de lo contrario, obtienes recuentos. Combínalo con MCP_WRITE_SIDECARS=1 (abajo) para que el resultado de cada video persista en disco y una re-ejecución se reanude en lugar de recalcular.

get_transcript — solo transcripción
> Get the transcript from this video

Extracción rápida de transcripción. Recurre a la transcripción de Whisper cuando no hay transcripción nativa disponible. Acepta las mismas anulaciones de model / language / initialPrompt por llamada que analyze_video.

get_metadata — solo metadatos
> What's this video about?

Devuelve metadatos, comentarios, capítulos y resumen de IA sin descargar el video.

get_frames — solo fotogramas
> Extract frames from this video with dense sampling

Dos modos:

  • Detección de cambio de escena (por defecto) — captura transiciones visuales
  • Muestreo denso (dense: true) — 1 fotograma/segundo para cobertura completa
analyze_moment — análisis profundo de un rango de tiempo
> Analyze what happens between 1:30 and 2:00 in this video

Combina extracción de ráfaga de fotogramas + transcripción filtrada + OCR + línea de tiempo anotada para un segmento enfocado. Úsalo cuando necesites entender exactamente qué sucede en un momento específico.

get_frame_at — un solo fotograma en una marca de tiempo
> Show me the frame at 1:23 in this video

La IA lee la transcripción, detecta un momento crítico y solicita el fotograma exacto para ver qué hay en pantalla.

get_frame_burst — N fotogramas en un rango de tiempo
> Show me 10 frames between 0:15 and 0:17 of this video

Para movimiento, vibración, animaciones o desplazamiento rápido — el modo ráfaga captura N fotogramas en una ventana estrecha para que la IA pueda ver los cambios fotograma a fotograma.

Niveles de detalle

NivelFotogramasTranscripciónOCRLínea de tiempoCaso de uso
briefNingunoPrimeras 10 entradasNoNoVerificación rápida — ¿de qué trata este video?
standardAdaptativo a la duración: ~12 (≤30s) hasta 60 (>10min), cambio de escenaCompletaPredeterminado — análisis completo
detailedHasta 60 (1fps denso)CompletaAnálisis profundo — cada segundo capturado

Caché

Los resultados se almacenan en caché en memoria durante 10 minutos. Las llamadas posteriores con la misma URL y opciones devuelven resultados al instante. Usa forceRefresh: true para omitir la caché. skipFrames es parte de la caché y de la clave del sidecar, por lo que un análisis solo de transcripción y uno con fotogramas de la misma URL nunca se responden entre sí.

Sidecars persistentes (procesamiento masivo reanudable)

La caché en memoria se pierde al reiniciar, lo que hace que reprocesar un corpus local grande sea costoso. Configura MCP_WRITE_SIDECARS=1 para también persistir resultados junto a cada video local para que el trabajo sobreviva a los reinicios y pueda reanudarse:

  • <stem>.vtt — la transcripción, solo cuando fue generada por el respaldo de Whisper (un <stem>.vtt existente de tu propio pipeline nunca se sobrescribe). Una llamada posterior lo reutiliza a través del lector de sidecar normal y omite Whisper por completo.
  • <stem>.analysis.json + <stem>.frames/ — el resultado completo (fotogramas + OCR + línea de tiempo), claveado por el mtime:size del video y los parámetros de análisis. En una llamada posterior con una marca y parámetros coincidentes, el resultado se devuelve directamente desde el disco (sin extracción, sin OCR).

Esto hace que analyze_videos sobre miles de archivos sea reanudable, y permite que un pipeline externo de transcripción por GPU y este MCP compartan resultados a través del sistema de archivos: el pipeline escribe <stem>.vtt, y el MCP lo recoge en lugar de ejecutar Whisper.

Fuentes admitidas

FuenteTranscripciónMetadatosComentariosFotogramasAutenticación
LoomSí (normalmente necesita yt-dlp — ver nota)Ninguna
YouTube / Vimeo / TikTok / Instagram / X / Twitch / Dailymotion / FacebookSubtítulos nativos (subidos > autogenerados) o respaldo de WhisperSí (título, duración, subidor, vistas, capítulos, fecha de subida)NoSí (limitado a 1080p)yt-dlp instalado; cookies para Instagram / restringido por edad (ver abajo)
URL directa (.mp4, .mov, .mkv, .webm, …)NoSolo duraciónNoNinguna
URL directa + TwelveLabsSí (Pegasus, mejor esfuerzo)Piso de duración + títuloNoTWELVELABS_API_KEY
Archivo local (ruta absoluta o URI file://)Sidecar .vtt/.srt o respaldo de WhisperSondeado vía ffmpeg (duración, dimensiones, códec, presencia de audio)NoNinguna

Fotogramas de Loom: la transcripción, los metadatos y los comentarios provienen directamente de la API de Loom sin herramientas adicionales. La extracción de fotogramas es diferente: Loom sirve la mayoría de los videos como flujos DASH separados de video+audio, que solo yt-dlp (pip install yt-dlp) obtiene y fusiona. La fusión usa el ffmpeg-static incluido, por lo que no se requiere ffmpeg del sistema. Sin yt-dlp, un respaldo directo por CDN aún cubre algunos videos; cuando no puede, obtienes transcripción + metadatos + comentarios más una advertencia que explica por qué faltan los fotogramas.

Archivos locales: pasa una ruta absoluta (p. ej., /Users/you/clip.mp4) o una URI file:// como argumento url a cualquier herramienta. Las rutas relativas se rechazan: el directorio de trabajo del servidor es impredecible desde el cliente MCP. Ten en cuenta que cualquier llamador del servidor MCP puede pedirle que lea cualquier archivo al que el proceso del servidor tenga acceso.

Transcripciones sidecar: si un clip.vtt, clip.srt, clip.en.vtt, etc. vive junto a clip.mp4, se usa como transcripción automáticamente — sin necesidad de ida y vuelta con Whisper. El SRT se convierte a VTT en memoria.

Subtítulos integrados: si no se encuentra un sidecar y el contenedor tiene un flujo de subtítulos integrado (común en .mkv / .mov / .mp4 de grabadores de pantalla), se transmuxa a VTT vía ffmpeg y se usa como transcripción.

Extensiones reconocidas (archivos locales y URLs directas): .mp4 .mov .mkv .webm .avi .m4v .wmv .flv .mpeg .mpg .m2ts .mts .3gp .ogv. La extensión solo controla el enrutamiento — ffmpeg hace el demux real, por lo que la mayoría de los contenedores comunes funcionan. .ts se excluye para evitar colisionar con archivos fuente de TypeScript.

URLs de plataformas vía yt-dlp (YouTube, Instagram, TikTok, …)

Las páginas de video individual en plataformas principales se enrutan a través de yt-dlp (pip install yt-dlp — requerido para estas URLs). Las listas de reproducción, canales y páginas de perfil se rechazan por diseño; pasa URLs de video individuales (agrúpalas con analyze_videos).

  • Transcripción: los subtítulos nativos se prefieren y son gratuitos — primero subtítulos subidos, subtítulos autogenerados como respaldo (la duplicación por ventana deslizante se colapsa). WHISPER_LANGUAGE (p. ej., pt) también se usa para elegir el idioma de los subtítulos. Los videos sin subtítulos en absoluto caen en la cadena normal de Whisper.
  • Metadatos: título, duración, subidor/canal, recuento de vistas, fecha de subida y capítulos — sin necesidad de descarga.
  • Descarga: limitada a 1080p (los fotogramas/OCR no necesitan más), los streams en vivo se omiten, y el audio+video DASH se fusiona con el ffmpeg-static incluido (sin ffmpeg del sistema).
  • Cookies — Instagram y videos restringidos por edad normalmente requieren una sesión iniciada:
Variable de entornoQué haceEjemplo
YTDLP_COOKIESArchivo de cookies (formato Netscape), gana cuando ambos están configuradosC:/secrets/cookies.txt
YTDLP_COOKIES_FROM_BROWSERExtraer cookies de un navegador instaladochrome, edge, firefox

La extracción de cookies del navegador requiere que el navegador esté cerrado en Windows (la base de datos de cookies está bloqueada mientras se ejecuta). Si eso es inconveniente, exporta un cookies.txt una vez (p. ej., con una extensión de navegador "Get cookies.txt") y apunta YTDLP_COOKIES a él. Los videos privados/restringidos por edad sin cookies válidas no bloquean la herramienta — la línea ERROR: de yt-dlp aparece en warnings[].

TwelveLabs Pegasus (opcional)

Configura la variable de entorno TWELVELABS_API_KEY para analizar URLs de video directas con TwelveLabs Pegasus. Pegasus analiza el video en el servidor (visuales y su propio audio) y devuelve una transcripción generada por IA con marcas de tiempo más un resumen de IA como texto — capacidades que el DirectAdapter no puede proporcionar (una URL .mp4 cruda no tiene transcripción ni resumen por sí sola), y sin necesidad de clave de Whisper.

La transcripción es salida de LLM de mejor esfuerzo, no un volcado ASR determinista: se indica a Pegasus que emita filas [MM:SS] line, y las líneas que no coinciden con esa forma se descartan, por lo que la redacción y las marcas de tiempo exactas dependen de la adherencia del modelo a la indicación. Los fallos (clave incorrecta, tiempo de espera, error de API) aparecen en el warnings[] de la herramienta en lugar de devolver silenciosamente una transcripción vacía.

La mayor ventaja está en las rutas solo de texto: get_transcript y get_metadata devuelven una transcripción y resumen de Pegasus para URLs directas — unos pocos KB de texto, sin imágenes de fotogramas, sin costo de token por fotograma. analyze_video en detail: "standard"/"detailed" aún extrae fotogramas además (usa detail: "brief" para mantenerse solo en texto).

Videos largos: el resumen y la transcripción completa comparten una única finalización con tope (max_tokens = 16384), por lo que para videos muy largos la transcripción puede truncarse. Para contenido de varias horas, el fragmentado por ventana de tiempo es el mejor enfoque.

Es completamente opcional y no rompe nada: cuando TWELVELABS_API_KEY está configurado, el TwelveLabsAdapter maneja URLs de video directas (registra la URL pública con TwelveLabs — sin subida); cuando no está configurado, el DirectAdapter las maneja exactamente como antes. Las URLs de Loom no se ven afectadas. Obtén una clave en playground.twelvelabs.io.

Transcripción (respaldo de Whisper)

Cuando una fuente no tiene transcripción nativa (sin sidecar .vtt/.srt, sin subtítulos integrados, sin subtítulos de plataforma), la pista de audio se transcribe con Whisper mediante una cadena de respaldo elegante (en orden de ejecución):

Pistas silenciosas: antes de cualquier ejecución de Whisper, el audio se sondea con ffmpeg volumedetect (primeros 2 minutos). Una pista presente pero muda — común en Reels/Stories silenciados — omite la transcripción por completo y emite una advertencia de que la transcripción vacía es contenido esperado, no un error, ahorrando una ejecución inútil de Whisper.

  1. @huggingface/transformers (nativo JS, cero dependencias externas) — solo opt-in: esta estrategia se ejecuta primero, pero solo cuando WHISPER_HF_MODEL está explícitamente configurado. Cuando no está configurado (el predeterminado), la estrategia se omite por completo, por lo que la CLI de abajo gana y sus configuraciones WHISPER_MODEL/WHISPER_LANGUAGE nunca se sobrescriben silenciosamente.
  2. CLI whisper — se usa cuando se encuentra un ejecutable whisper (pip install -U openai-whisper). Apunta WHISPER_BIN al ejecutable si no está en PATH. Modelo vía WHISPER_MODEL, idioma vía WHISPER_LANGUAGE. El ffmpeg-static incluido se coloca automáticamente en el PATH de la CLI, por lo que no se requiere ffmpeg del sistema.
  3. OpenAI Whisper API — se usa cuando OPENAI_API_KEY está configurado.

¿Sin backend configurado? Si ninguno de los tres está disponible (sin whisper en PATH/WHISPER_BIN, sin OPENAI_API_KEY, sin WHISPER_HF_MODEL), las herramientas de transcripción devuelven una transcripción vacía con una advertencia que te dice cómo habilitar uno — en lugar de un silencioso "sin transcripción". Instala openai-whisper o configura una de las claves anteriores. (La CLI se lanza con PYTHONUTF8=1 para que las transcripciones no inglesas/CJK no bloqueen el proceso de Python en Windows.)

Variable de entornoAplica aPredeterminadoEjemplo
WHISPER_MODELCLI whispertinysmall, medium
WHISPER_LANGUAGECLI whisper / OpenAI APIauto-detecciónpt, en, es
WHISPER_PROMPTCLI whisper / OpenAI APIDoha, Smiles, Livelo, Latam, milheiro
WHISPER_BINCLI whisperwhisper (en PATH)C:/.../Scripts/whisper.exe
WHISPER_DEVICECLI whisper (enviado solo si está configurado)cuda, cpu
WHISPER_COMPUTEsolo whisper-ctranslate2float16, int8_float16, int8
WHISPER_BEAM_SIZECLI whisper (enviado solo si está configurado)5
WHISPER_WORD_TIMESTAMPSCLI whisper (enviado solo si está configurado)off1
WHISPER_HF_MODELHF transformers (opt-in)— (estrategia desactivada)Xenova/whisper-small
OPENAI_API_KEYOpenAI APIsk-…

El modelo tiny predeterminado es rápido pero débil para audio que no está en inglés. Para fuentes en portugués (u otros idiomas que no sean inglés), instale la CLI y configure WHISPER_MODEL=small (o medium) + WHISPER_LANGUAGE=pt para obtener una precisión mucho mejor. Agregue WHISPER_PROMPT con un glosario de dominio (nombres de marcas/lugares) para corregir nombres propios. También puede anular model/language/initialPrompt por llamada en analyze_video / get_transcript / analyze_videos — no se necesita reiniciar.

GPU (faster-whisper): whisper-ctranslate2 (pip install -U whisper-ctranslate2) es una CLI de reemplazo directo con las mismas banderas más --device cuda / --compute_type / --beam_size. Apunte WHISPER_BIN hacia ella y configure WHISPER_DEVICE=cuda (+ opcionalmente WHISPER_COMPUTE=float16). Estas banderas de GPU están restringidas por variables de entorno — solo se pasan cuando están configuradas, por lo que openai-whisper normal (que rechaza --compute_type) sigue funcionando cuando no están configuradas.

Nota para Windows: pip instala whisper.exe en el directorio Scripts/ de Python, que a menudo no está en el PATH que heredan los clientes MCP iniciados desde la interfaz gráfica. Si las transcripciones vuelven vacías, configure WHISPER_BIN con la ruta completa de whisper.exe.

Estrategias de extracción de fotogramas

La extracción de fotogramas utiliza una cadena de respaldo de dos estrategias — no se requiere una única dependencia:

EstrategiaCómo funcionaVelocidadRequisitos
yt-dlp + ffmpeg (principal)Descarga el video, extrae fotogramas mediante detección de escenasRápida, precisayt-dlp (pip install yt-dlp)
Navegador (respaldo)Abre el video en Chrome sin interfaz, busca marcas de tiempo, toma capturas de pantallaMás lenta, no requiere descargaChrome o Chromium instalado

El respaldo es automático — si yt-dlp no está disponible, el servidor intenta la extracción basada en navegador mediante puppeteer-core. Si ninguno está disponible, el análisis aún devuelve transcripción + metadatos + comentarios, solo que sin fotogramas.

Proceso de post-procesamiento

Después de la extracción de fotogramas, el proceso aplica automáticamente:

PasoQué hacePor qué
Deduplicación de fotogramasElimina fotogramas consecutivos casi idénticos usando hash perceptual (dHash + distancia de Hamming)Las grabaciones de pantalla suelen tener momentos estáticos largos — la deduplicación elimina fotogramas redundantes, ahorrando tokens
OCRExtrae texto visible en pantalla de cada fotograma (mediante tesseract.js). Cada fotograma se preprocesa primero — escala de grises + ampliación 2× + normalización de contraste + nitidez — lo que mejora materialmente la precisión en superposiciones estilizadas (precios, fechas, cupones, llamadas a la acción).Captura código, mensajes de error, salida de terminal, texto de interfaz que la transcripción no cubre
Línea de tiempo anotadaFusiona marcas de tiempo de transcripción + marcas de tiempo de fotogramas + texto OCR en una única vista cronológicaLe da a la IA una vista unificada de "qué se dijo, qué cambió visualmente y qué texto apareció" en cada momento

El paso de OCR requiere tesseract.js (incluido como dependencia). Si falla al cargar, el análisis continúa sin OCR — no se pierden fotogramas ni transcripción. El preprocesamiento de OCR está activado por defecto; configure MCP_OCR_PREPROCESS=0 para aplicar OCR a los fotogramas sin procesar.

El OCR siempre lee el fotograma de resolución completa, no la copia enviada al cliente. Los dos tienen trabajos diferentes: el fotograma enviado está limitado por costo de tokens, mientras que el reconocimiento necesita cada píxel que pueda obtener.

Tamaño de fotograma (capturas de interfaz densa)

Los fotogramas enviados están limitados a 800 px de ancho, lo que se adapta al caso común — clips de personas hablando, Reels, reproducciones de errores — donde el sujeto llena el fotograma.

Es el tamaño incorrecto para una captura de interfaz densa: una grabación de terminal, panel, IDE u hoja de cálculo, donde el significado está en texto pequeño. Una grabación de pantalla 1920×1080 sin escalar llega a 800×450, y una fuente de interfaz de 15 px cae por debajo de lo que un modelo de visión puede resolver.

Pase maxWidth por llamada para conservar más (o toda) la resolución de origen — 0 desactiva el límite:

get_frames(url, { maxFrames: 8, maxWidth: 0 })   // source resolution
get_frame_at(url, "2:14", { maxWidth: 1920 })
analyze_video(url, { detail: "standard", maxWidth: 1568 })

Compatible con analyze_video, analyze_videos, analyze_moment, get_frames, get_frame_at y get_frame_burst, y en la CLI como --max-width <px>.

Los fotogramas nativos cuestan varias veces más contexto que el predeterminado, así que aumente el límite deliberadamente — get_frames devuelve hasta 20 fotogramas y analyze_video en detailed hasta 60.

VariableSe aplica aPredeterminadoNotas
MCP_FRAME_MAX_WIDTHAncho del fotograma enviado, en px8000 (o native/full/original) desactiva el límite. Un maxWidth por llamada tiene prioridad sobre ella
MCP_FRAME_JPEG_QUALITYCalidad JPEG del fotograma enviado70Auméntela cuando los glifos finos importen; solo por entorno, no hay parámetro de calidad por llamada. Valores fuera de 1–100 vuelven al predeterminado
MCP_CACHE_DIRRaíz para la caché de tessdata y el --out predeterminado de la CLIdirectorio de caché por usuarioSolo rutas absolutas (un valor relativo se ignora). Úsela cuando $HOME sea de solo lectura o no exista — un contenedor endurecido, ProtectHome=, un directorio de inicio con cuota. La imagen Docker publicada la configura en /tmp/mcp-video-analyzer-cache para que --read-only --tmpfs /tmp funcione de inmediato

Un valor que ninguna variable puede usar — 1e3, 1920px, una calidad de 150 — se rechaza con una advertencia única en stderr y se aplica el predeterminado. No se acepta silenciosamente: el objetivo del ajuste es escapar de una reducción de escala que de otro modo parece un resultado normal.

Prefiera el parámetro por llamada: el servidor se inicia una vez por sesión, por lo que una variable de entorno no puede diferir entre una vista general de un clip de YouTube y una lectura cercana de una grabación de pantalla. El ancho que una llamada realmente usa es parte de la clave de caché y del archivo lateral, por lo que analizar el mismo video a 800 px y luego a maxWidth: 0 vuelve a ejecutar el proceso en lugar de devolver el primer resultado dos veces.

Herramientas complementarias

Chrome DevTools MCP

Para depuración web en vivo junto con el análisis de video, combine este servidor con el Chrome DevTools MCP:

claude mcp add chrome-devtools npx @anthropic-ai/mcp-devtools@latest

Cuándo usar cada uno:

EscenarioHerramienta
Informe de error grabado como video de Loommcp-video-analyzer — extraer transcripción, fotogramas y texto de error de la grabación
Depuración en vivo de una página webChrome DevTools MCP — inspeccionar DOM, consola, red, tomar capturas de pantalla
El video muestra un problema de interfaz, necesita reproducirloUse ambos: analice el video primero, luego abra la página en Chrome DevTools para reproducirlo

Los dos MCP se complementan: el analizador de video entiende contenido grabado, DevTools interactúa con páginas en vivo.

Ejemplo de salida

La carpeta examples/loom-demo/ contiene salidas reales del análisis de un video público de Loom (Boost In-App Demo Video, 2:55).

ArchivoQué muestra
metadata.jsonTítulo, duración, plataforma
transcript.json42 entradas con marcas de tiempo e identificadores de hablante
timeline.jsonVista cronológica unificada (transcripción + fotogramas fusionados)
moment-transcript-0m30s-0m45s.jsonTranscripción filtrada para analyze_moment (0:30–0:45)
full-analysis.jsonSalida completa de analyze_video

Imágenes de fotogramas (19 en total en examples/loom-demo/frames/):

  • scene_*.jpg — detección de cambios de escena (transiciones visuales clave)
  • dense_*.jpg — muestreo denso a 1 fps (cada décimo fotograma guardado como muestra)
  • burst_*.jpg — extracción en ráfaga para análisis de momentos (0:30–0:45)

Regenerar después de cambios: npx tsx examples/generate.ts — requiere yt-dlp + acceso a red.

Desarrollo

# Install dependencies
npm install

# Run all checks (format, lint, typecheck, knip, tests)
npm run check

# Audit dependencies. `security` covers what the published package ships and
# is a blocking CI job; `security:all` adds devDependencies. Both also run on
# a weekly cron, because npm audit reads a live advisory database.
npm run security

# Build
npm run build

# Run E2E tests (requires network; add WHISPER_E2E=1 to include the
# transcription outcome test — needs a whisper CLI installed)
npm run test:e2e

# Just the video-format matrix: a real clip per container/codec
# (mp4/h264+hevc+av1, webm, mkv, mov, avi, m4v, mpeg, mpg, m2ts, mts,
# 3gp, ogv, flv, wmv) decoded end to end. ~15s on a warm cache; the
# first run fetches ~7MB of tesseract traineddata.
npm run test:formats

# Build + boot the real MCP server/CLI (seconds)
npm run test:smoke

# Everything: check → e2e → smoke → verify-package
npm run verify-all

# Open MCP Inspector for manual testing
npm run inspect

Arquitectura

src/
├── index.ts                    # Entry point (shebang + stdio)
├── server.ts                   # FastMCP server + tool registration
├── tools/                      # MCP tool definitions (7 tools)
│   ├── analyze-video.ts        # Full analysis with detail levels + caching
│   ├── analyze-moment.ts       # Deep-dive on a time range
│   ├── get-transcript.ts       # Transcript-only with Whisper fallback
│   ├── get-metadata.ts         # Metadata + comments + chapters
│   ├── get-frames.ts           # Frames-only (scene-change or dense)
│   ├── get-frame-at.ts         # Single frame at timestamp
│   └── get-frame-burst.ts      # N frames in a time range
├── adapters/                   # Source-specific logic
│   ├── adapter.interface.ts    # IVideoAdapter interface + registry
│   ├── loom.adapter.ts         # Loom: authless GraphQL
│   ├── local-file.adapter.ts   # Local files: absolute path or file:// URI
│   ├── twelvelabs.adapter.ts   # TwelveLabs Pegasus: transcript + AI summary (opt-in)
│   └── direct.adapter.ts       # Direct URL: any mp4/webm link
├── processors/                 # Shared processing
│   ├── frame-extractor.ts      # ffmpeg scene detection + dense + burst extraction
│   ├── browser-frame-extractor.ts # Headless Chrome fallback for frames
│   ├── audio-transcriber.ts    # Whisper fallback (HF transformers → CLI → OpenAI)
│   ├── image-optimizer.ts      # sharp resize/compress
│   ├── frame-dedup.ts          # Perceptual dedup (dHash + Hamming distance)
│   ├── frame-ocr.ts            # OCR text extraction (tesseract.js)
│   └── annotated-timeline.ts   # Unified timeline (transcript + frames + OCR)
├── config/
│   └── detail-levels.ts        # brief / standard / detailed config
├── utils/
│   ├── cache.ts                # In-memory TTL cache with LRU eviction
│   ├── field-filter.ts         # Selective field filtering for responses
│   ├── url-detector.ts         # Platform detection from URL
│   ├── vtt-parser.ts           # WebVTT → transcript entries
│   └── temp-files.ts           # Temp directory management
└── types.ts                    # Shared TypeScript interfaces

Licencia

MIT