Communitygithub.com

CacinieP/video2knowledge

Convierte vídeos en subtítulos con marcas de tiempo y artefactos de conocimiento estructurados.

¿Qué es video2knowledge?

Video2Knowledge es una skill para agentes de IA que convierte vídeos en subtítulos con marcas de tiempo y artefactos de conocimiento estructurados, todo ello de forma completamente local. Ofrece tres rutas de ingestión: (1) un VLM multimodal nativo (de hasta 4B parámetros, vía Ollama) que lee fotogramas de vídeo para generar subtítulos con marcas de tiempo; (2) un sistema ASR que transcribe el audio a subtítulos con marcas de tiempo, usando faster-whisper localmente o FunASR Paraformer para mandarín (mejorando la precisión del 44% al 94% en homófonos); y (3) una ruta de fusión dual que combina ASR y VLM para vídeos con diapositivas y narración. Luego refina los subtítulos en un documento de conocimiento estructurado (con plantillas personalizadas), una página HTML autocontenida, un CSV de tarjetas de conocimiento deduplicadas, un mazo Anki apkg, y notas ilustradas (图文笔记) en dos vistas: la completa con narración citada y una versión destilada (纯享版) para repaso. Todo el procesamiento permanece local de forma predeterminada; los endpoints ASR/LLM en la nube son opt-in y están explícitamente etiquetados como que suben datos a un tercero. La skill es compatible con Ollama, modelos VLM de código abierto (como las series MiniCPM y Qwen) y sistemas ASR locales. Está diseñada para transcripción y resumen de vídeos, creación de tarjetas de estudio a partir de conferencias o grabaciones, y para convertir presentaciones con diapositivas en apuntes de estudio detallados.

Compatible con~Claude Code✓Codex CLI~Cursor
npx skills add CacinieP/video2knowledge

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace video2knowledge?

Convierte un vídeo en: subtítulos con marcas de tiempo → documento de conocimiento → HTML / tarjetas Anki / 图文笔记. Dos rutas de ingestión locales, toda la inferencia es local por defecto (sin API en la nube). El procesamiento permanece completamente local — los vídeos, subtítulos y resultados nunca se suben; viven en una carpeta runs/ local (gitignorada). El repositorio solo registra cambios de código/configuración.

La única excepción es opt-in y nunca automática: --backend openai-api / mimo-asr (ASR) y --api-base (documento de conocimiento, cualquier endpoint compatible con OpenAI) envían ese audio o texto de subtítulo al tercero que usted nombre. Si no los pasa, todo permanece en el host. Dígalo explícitamente cuando los recomiende.

Requisitos previos y configuración inicial

Requerido en el host: ollama, ffmpeg, python3 (o uv). Una sola vez:

bash scripts/setup_models.sh

Esto (idempotentemente) detecta automáticamente el perfil de hardware de su máquina (RAM / GPU / Apple Silicon / NVIDIA) mediante scripts/hardware_profile.py, luego descarga el VLM recomendado, crea un venv en .venv/ e instala faster-whisper + genanki. Vea lo que eligió:

python3 scripts/hardware_profile.py

Los perfiles van desde tiny (máquinas de 4 GB → whisper-tiny + qwen3.5:0.8b) hasta high-gpu (NVIDIA ≥8 GB → whisper-large-v3 + qwen3.5:9b en CUDA). Tabla completa y ajuste en references/hardware-profiles.md. Sobrescriba cualquier opción con variables de entorno (VLM_MODEL=, ASR_DEFAULT_MODEL=, ...) o indicadores CLI.

Active el venv antes de ejecutar cualquier paso de python:

source .venv/bin/activate

Elija una ruta de ingestión (Paso 1)

Árbol de decisión:

  • Pista de audio clara (conferencia, charla, entrevista, narración) → Ruta 2 (ASR). Más rápida, texto más preciso, marcas de tiempo detalladas. Para mandarín, prefiera el backend FunASR Paraformer — pregunte a la máquina con python3 scripts/hardware_profile.py --recommend. → references/path2-asr.md
  • Silencioso / solo diapositivas / grabación de pantalla, o necesita texto en pantalla y diagramas → Ruta 1 (multimodal). → references/path1-multimodal.md
  • Vídeo de diapositivas/PPT con pista de audio (el caso común de cursos en línea): el contenido principal está en la pantalla (tablas, fórmulas, ejemplos) Y el orador narra → Ruta 3 (fusión de dos rutas). Ejecuta ASR para la narración + VLM OCR para las diapositivas y las fusiona por marca de tiempo. → references/path3-fusion.md

Las rutas 1 y 2 emiten el mismo esquema de segmento ({inicio,fin,texto}), por lo que el paso 2 es independiente de la ruta. La ruta 3 emite un merged.json fusionado consumido por el --merged del paso 2.

Ruta 1 — Subtítulos multimodales

python3 scripts/mm_caption.py \
  --video VIDEO --out-dir OUT \
  --model openbmb/minicpm-v4.6:latest --interval 2.0

Salidas: OUT/captions.srt, OUT/captions.json, OUT/frames/.

Para vídeos de diapositivas/PPT, use el muestreo dedup (de propósito general, sin ajuste de umbral) más el prompt OCR de tabla/fórmula:

python3 scripts/mm_caption.py \
  --video VIDEO --out-dir OUT \
  --mode dedup --prompt-ocr

Ruta 2 — Transcripción ASR

¿Qué motor? Pregunte primero a la máquina:

python3 scripts/hardware_profile.py --recommend

Medido en un curso de mandarín de 61.5 h, ambos motores en la misma conferencia de 30 minutos con la misma lista de 39 términos hotword:

términos homófonos correctosvelocidad
faster-whisper small + hotwords44%2.5× tiempo real
Paraformer-zh (FunASR, CPU)94%12–16× tiempo real

Los hotwords no pueden solucionar esto: 背谱/被谱 son idénticos en pinyin y tono, por lo que el audio en sí es ambiguo. La recomendación se basa en la RAM, no en la VRAM — la ventaja de Paraformer es la precisión en mandarín y se ejecuta en CPU. Si tiene una GPU, déjela libre para el VLM: ejecutar whisper y el VLM juntos convierte una solicitud de 8 tokens de 3.8 s a más de 60 s.

Predeterminado (local, faster-whisper):

python3 scripts/asr_caption.py \
  --video VIDEO --out-dir OUT \
  --model small --language zh \
  --hotwords "término uno, término dos"   # sesgo de jerga opcional mediante initial_prompt

Paraformer (recomendado para mandarín; necesita su propio venv — el pin de tokenizers de funasr no se coinstala con el entorno principal):

bash scripts/setup_models.sh --with-funasr     # construye .venv-funasr, imprime la ruta

python3 .venv-funasr/bin/python scripts/asr_funasr.py \
  --video VIDEO --out-dir OUT --language zh --hotwords "背谱,视谱,音阶"

Existen motores en la nube para hosts que no pueden transcribir localmente, y son opt-in — suben el audio a un tercero. bash scripts/setup_models.sh --with-openai-client agrega el SDK openai que necesita; --backend openai-api toma cualquier endpoint compatible con OpenAI y --backend mimo-asr es para puertas de enlace con forma de chat que no devuelven marcas de tiempo. Consulte references/path2-asr.md.

Salidas: OUT/subtitles.{srt,vtt,json}.

Luego repare los homófonos. ASR escucha sonidos, no palabras, por lo que los términos del dominio aparecen escritos incorrectamente y el error se propaga a todos los artefactos posteriores. Medido: 20 clases de error genuino en 46 lugares, 100% de precisión.

python3 scripts/fix_homophones.py --subtitles OUT/subtitles.json

Coincide con pinyin sensible al tono, no con distancia de edición, y reescribe subtitles.srt / .vtt para que coincidan. Ejecútelo antes del paso 2. --dry-run para previsualizar, --block 实度 para poner en la lista negra un fragmento, --glossary @terms.txt para agregar los suyos propios.

Ruta 3 — Fusión de dos rutas (ASR × VLM)

Ejecute la ruta 2 y luego la ruta 1 (OCR), realimente los términos de OCR como hotwords de ASR, fusione y construya a partir del archivo fusionado:

# 1a. ASR
python3 scripts/asr_caption.py --video VIDEO --out-dir OUT --language zh
# 1b/1c. fotogramas dedup + VLM OCR
python3 scripts/mm_caption.py --video VIDEO --out-dir OUT --mode dedup --prompt-ocr
# 1d. términos OCR -> hotwords + verificación de cobertura (vuelva a ejecutar ASR con
#     --hotwords @OUT/ocr_hotwords.txt cuando la cobertura sea baja)
python3 scripts/hotwords_from_ocr.py --captions OUT/captions.json \
  --subtitles OUT/subtitles.json --out OUT/ocr_hotwords.txt
# 2. fusionar por marca de tiempo + verificación de alineación semántica
python3 scripts/merge_visual.py --subtitles OUT/subtitles.json --visual OUT/captions.json --out OUT/merged.json
# 3. construir (paso 2 con --merged)
python3 scripts/build_knowledge.py --subtitles OUT/subtitles.json --merged OUT/merged.json --out-dir OUT --format all

El bucle de fusión tiene tres piezas entre rutas: (1) hotwords_from_ocr.py extrae términos en pantalla (n-gramas CJK recurrentes, títulos de diapositivas, acrónimos latinos — heurístico, sin LLM) e informa cuáles el ASR nunca escuchó, la jerga probablemente mal oída; (2) merge_visual.py adjunta imágenes por marca de tiempo, luego reasigna de forma conservadora una línea de narración a una diapositiva ADYACENTE cuando su superposición de palabras con la diapositiva adjunta por marca de tiempo es casi nula y la vecina coincide claramente mejor (desfase del hablante / deriva de la marca de tiempo), marcando los casos inciertos como weak en lugar de adivinar — excepto en diapositivas ESTABLECIDAS (≥60 s en pantalla), donde la elaboración verbal es la norma y no se marca ninguna bandera (--no-semantic restaura la coincidencia pura de marcas de tiempo); (3) build_knowledge.py --merged alimenta al LLM texto intercalado de audio+visual (los límites de los fragmentos nunca cortan una tabla de diapositivas; las líneas de eco de prompt se filtran por huella dactilar de cada campo de lista; los límites de campo se escalan con la duración del vídeo, 3× a las 3 h) con marcadores ⚠️ en notas de intercambio/débiles, y reordena los campos de lista reducidos por map en un solo pase global con el resumen como contexto. Las respuestas del LLM a nivel de fragmento se almacenan en caché en build_cache.json, por lo que una compilación interrumpida de 3 horas se reanuda en lugar de reiniciarse. En lotes, batch_run.py acumula términos de OCR en course_hotwords.txt para que los vídeos posteriores transcriban mejor, y --asr-verify vuelve a transcribir un vídeo cuya cobertura de términos de OCR cayó por debajo del 50%. El modelo de texto predeterminado sigue el mismo perfil de hardware: openbmb/minicpm5-2b (2.5B denso, 1.6 GB) en low/low-mac/mid, y la descarga del VLM de la ruta 1 en high+ (qwen3.5/qwen3.8 son visión+texto unificados, por lo que nada se descarga dos veces). Sobrescriba con --model, o V2K_TEXT_MODEL= para fijar uno para cada ejecución. Medición de calidad: scripts/recall_check.py --run-dir <dir> --draft emite una lista de imprescindibles dorada (términos / números de ambos canales / cobertura de línea de tiempo) que un humano poda en minutos; --golden luego puntúa los artefactos producidos contra ella (líneas de base en tests/golden/BASELINE.md) — el "contenido faltante" se convierte en un número que puede rastrear a través de cambios de parámetros.

Refinar en artefactos de conocimiento (Paso 2)

Apunte build_knowledge.py a la salida .json de cualquier ruta:

python3 scripts/build_knowledge.py \
  --subtitles OUT/subtitles.json \
  --out-dir OUT --format all

Produce, en OUT/:

ArtefactoArchivoSección
2.1 Documento de conocimiento (con plantilla)knowledge.mdusa assets/default-template.md o --template <archivo>
2.2 HTML autocontenidoknowledge.htmllínea de tiempo [mm:ss] enlazable
2.2b Exportación a Office/impresiónknowledge.docx / knowledge.pdf--format docx / --format pdf (auto en --format all cuando python-docx/fpdf2 está instalado)
2.3 Tarjetas de conocimientocards.csvpregunta,respuesta,etiquetas,marca de tiempo,fuente — deduplicadas: una conferencia larga se resume mediante map/reduce sobre fragmentos y el modelo vuelve a preguntar la misma pregunta en cada uno, por lo que cada repetición se elimina (medido: 145 de 1608 tarjetas, en el peor caso 117 filas → 11)
2.4 Notas ilustradas (图文笔记)notes.md + notes.htmlfotogramas clave × narración, consulte a continuación
2.4b Notas Office/impresiónnotes.docx / notes.pdfbuild_notes.py --docx --pdf (fotogramas incrustados)
2.4c Notas destiladas (纯享版)notes-distilled.md / .docx / .pdfmismos nodos y fotogramas, sin narración citada — 42% más pequeño y gratis (renderizado a partir de la salida ya calculada)

Luego convierta las tarjetas a Anki (final 2.3):

python3 scripts/gen_apkg.py --csv OUT/cards.csv --out OUT/cards.apkg --deck "Tarjetas de conocimiento de vídeo"

Notas ilustradas (2.4, 图文笔记)

Una nota desplazable que intercala FOTOGRAMAS CLAVE deduplicados con la narración alrededor de cada marca de tiempo — el artefacto "revísalo como una lectura". Necesita frames.json (de extract_frames.py, generalmente a través del modo dedup de la ruta 1) más los subtítulos de cualquier ruta:

python3 scripts/build_notes.py \
  --subtitles OUT/subtitles.json \
  --frames OUT/frames/frames.json \
  --out-dir OUT --describe-frames

La densidad de nodos es automática. --max-frames 0 (el valor predeterminado) dimensiona la nota a ~1 nodo por 45 segundos, limitado a 12–60: un clip de 12 minutos obtiene 16 nodos, una conferencia de 41 minutos 55, una de 3 horas 60. El antiguo presupuesto de 1 por 4 minutos daba a una conferencia de 37 minutos solo 9 nodos, y el 1 por 90 s que le siguió aún tenía un mínimo de 8 — medido en una biblioteca de 306 vídeos / 61.5 h, el clip medio es de 12.1 min, por lo que el mínimo limitaba la mayor parte de la biblioteca a 8 nodos sin importar cuánto durara el vídeo. El mínimo era lo que había que mover, no el máximo. Pase un --max-frames N explícito para fijarlo. La selección está estratificada por conglomerados: cada ráfaga de cambio conserva su fotograma final establecido, por lo que una ráfaga de animación ya no priva a las diapositivas clave aisladas de su propio nodo.

Por fotograma clave: título de sección del LLM → imagen del fotograma → descripción VLM opcional de la escena (--describe-frames) → nota de 1-2 frases condensada de la ventana de narración → extracto textual 原声.

El prompt 画面 solicita información didáctica, no personas: notas de tono, símbolos de acordes, indicaciones de compás, anotaciones y texto en pantalla — y se niega explícitamente a describir al intérprete ("señora tocando el piano", "explicación con gestos" no son lo que una nota de repaso necesita). Un fotograma sin contenido didáctico legible obtiene su nombre de tema en su lugar ("imagen de interpretación de piano, sin subtítulos"). Este único cambio de prompt es la diferencia entre una nota que ayuda a estudiar y una que narra el vídeo.

Dos vistas, un solo pase. Cada ejecución escribe un par gemelo de las mismas secciones — sin llamada de modelo adicional:

ArchivoContienePara
notes.mdfotogramas + notas + 原声 citadoverificar las palabras exactas del profesor
notes-distilled.mdmismos nodos, mismos fotogramas, sin narración citadarepasar — medido en 295 nodos, las citas en bloque eran el 53% de los caracteres

--docx / --pdf exporta ambas variantes (notes.docx + notes-distilled.docx, y lo mismo para PDF). notes.html incrusta fotogramas como base64 en un solo archivo compartible — esa es solo la vista completa, sin gemelo HTML destilado. Degrada a fotogramas + extractos sin formato cuando no hay ningún modelo accesible.

Dé al VLM un modelo con capacidad visual explícitamente. --describe-frames sin --vlm-model recurre al modelo de texto, que no puede ver; la ejecución advierte y descarta las descripciones en lugar de fallar una vez por fotograma:

python3 scripts/build_notes.py ... --describe-frames \
  --model openbmb/minicpm5-2b --vlm-model openbmb/minicpm-v4.6:latest

Consulte references/outputs.md para conocer el esquema, las ejecuciones de un solo formato y el modo degradado.

Plantillas personalizadas (2.1)

Plantilla predeterminada: assets/default-template.md. Sobrescriba con --template <archivo>:

python3 scripts/build_knowledge.py --subtitles s.json --out-dir o \
  --template ./my-lecture-template.md --format knowledge

Las plantillas son Markdown sin formato que usan {{placeholders}} ({{title}}, {{summary}}, {{bullets}} (resumen rápido de puntos combinados audio/imagen), {{timeline}}, {{key_points}}, {{qa}}, {{glossary}}, {{source}}, {{duration}}, {{date}}, {{meta}}). Solo se rellenan los marcadores que incluya; todo lo demás permanece textual. Especificación completa + 3 plantillas de ejemplo (conferencia / reunión / tutorial) en references/templates.md.

Procesamiento local y seguimiento de cambios

Todo el procesamiento de vídeo permanece en su máquina. Los vídeos, fotogramas extraídos, subtítulos, documentos de conocimiento y tarjetas se escriben en una carpeta local runs/ que está gitignorada — nada sobre su medio se sube o se confirma nunca.

El repositorio de GitHub rastrea solo cambios de código y configuración (scripts, referencias, plantillas, README). Esto proporciona un historial claro de cómo evolucionó la skill, sin exponer ningún medio del usuario. Use mensajes de confirmación descriptivos feat:/fix:/docs:.

Si desea un registro local de una ejecución específica, escriba un manifest.json en esa carpeta de ejecución (ruta tomada, modelos, argumentos, lista de salida) — pero manténgalo local:

cat > "$RUN/manifest.json" <<EOF
{"video":"~/Movies/lecture.mp4","path":"dual-fusion","models":{"vlm":"openbmb/minicpm-v4.6:latest","asr":"paraformer-zh"},"args":"--mode dedup --prompt-ocr --language zh","outputs":["knowledge.md","cards.csv","notes.html"],"date":"2025-02-15"}
EOF

Skills relacionados