Habilidad VideoDB
Percepción + memoria + acciones para video, transmisiones en vivo y sesiones de escritorio.
Cuándo usarla
Percepción de escritorio
- Iniciar/detener una sesión de escritorio capturando pantalla, micrófono y audio del sistema
- Transmitir contexto en vivo y almacenar memoria episódica de la sesión
- Ejecutar alertas/desencadenantes en tiempo real sobre lo que se dice y sucede en pantalla
- Producir resúmenes de sesión, una línea de tiempo buscable y enlaces de evidencia reproducibles
Ingesta de video + transmisión
- Ingerir un archivo o URL y devolver un enlace de transmisión web reproducible
- Transcodificar/normalizar: códec, tasa de bits, fps, resolución, relación de aspecto
Indexar + buscar (marcas de tiempo + evidencia)
- Construir índices visual, de palabras habladas y de palabras clave
- Buscar y devolver momentos exactos con marcas de tiempo y evidencia reproducible
- Crear clips automáticamente a partir de los resultados de búsqueda
Edición y generación en línea de tiempo
- Subtítulos: generar, traducir, incrustar
- Superposiciones: texto/imagen/marca, subtítulos animados
- Audio: música de fondo, voz en off, doblaje
- Composición programática y exportaciones mediante operaciones de línea de tiempo
Transmisiones en vivo (RTSP) + monitoreo
- Conectar fuentes RTSP/en vivo
- Ejecutar comprensión visual y hablada en tiempo real y emitir eventos/alertas para flujos de trabajo de monitoreo
Cómo funciona
Entradas comunes
- Ruta de archivo local, URL pública, o URL RTSP
- Solicitud de captura de escritorio: iniciar / detener / resumir sesión
- Operaciones deseadas: obtener contexto para comprensión, especificación de transcodificación, especificación de índice, consulta de búsqueda, rangos de clip, ediciones de línea de tiempo, reglas de alerta
Salidas comunes
- URL de transmisión
- Resultados de búsqueda con marcas de tiempo y enlaces de evidencia
- Activos generados: subtítulos, audio, imágenes, clips
- Cargas de eventos/alertas para transmisiones en vivo
- Resúmenes de sesión de escritorio y entradas de memoria
Ejecutar código Python
Antes de ejecutar cualquier código de VideoDB, cambia al directorio del proyecto y carga las variables de entorno:
from dotenv import load_dotenv
load_dotenv(".env")
import videodb
conn = videodb.connect()
Esto lee VIDEO_DB_API_KEY de:
- Entorno (si ya está exportada)
- Archivo
.envdel proyecto en el directorio actual
Si la clave falta, videodb.connect() lanza AuthenticationError automáticamente.
NO escribas un archivo de script cuando un comando corto en línea funcione.
Al escribir Python en línea (python -c "..."), usa siempre código formateado correctamente — usa punto y coma para separar declaraciones y mantenlo legible. Para cualquier cosa de más de ~3 declaraciones, usa un heredoc en su lugar:
python << 'EOF'
from dotenv import load_dotenv
load_dotenv(".env")
import videodb
conn = videodb.connect()
coll = conn.get_collection()
print(f"Videos: {len(coll.get_videos())}")
EOF
Configuración
Cuando el usuario pida "configurar videodb" o similar:
1. Instalar SDK
pip install "videodb[capture]" python-dotenv
Si videodb[capture] falla en Linux, instala sin el extra capture:
pip install videodb python-dotenv
2. Configurar clave API
El usuario debe establecer VIDEO_DB_API_KEY usando cualquiera de los siguientes métodos:
- Exportar en terminal (antes de iniciar Claude):
export VIDEO_DB_API_KEY=tu-clave - Archivo
.envdel proyecto: GuardaVIDEO_DB_API_KEY=tu-claveen el archivo.envdel proyecto
Obtén una clave API gratuita en console.videodb.io (50 subidas gratis, sin tarjeta de crédito).
NO leas, escribas ni manejes la clave API tú mismo. Siempre deja que el usuario la configure.
Referencia rápida
Subir contenido multimedia
# URL
video = coll.upload(url="https://example.com/video.mp4")
# YouTube
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
# Archivo local
video = coll.upload(file_path="/path/to/video.mp4")
Transcripción + subtítulo
# force=True omite el error si el video ya está indexado
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()
Buscar dentro de videos
from videodb.exceptions import InvalidRequestError
video.index_spoken_words(force=True)
# search() lanza InvalidRequestError cuando no se encuentran resultados.
# Siempre envuelve en try/except y trata "No results found" como vacío.
try:
results = video.search("demostración de producto")
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
Búsqueda de escenas
import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestError
# index_scenes() no tiene parámetro force — lanza un error si ya existe un
# índice de escenas. Extrae el ID del índice existente del error.
try:
scene_index_id = video.index_scenes(
extraction_type=SceneExtractionType.shot_based,
prompt="Describe el contenido visual de esta escena.",
)
except Exception as e:
match = re.search(r"id\s+([a-f0-9]+)", str(e))
if match:
scene_index_id = match.group(1)
else:
raise
# Usa score_threshold para filtrar ruido de baja relevancia (recomendado: 0.3+)
try:
results = video.search(
query="persona escribiendo en una pizarra blanca",
search_type=SearchType.semantic,
index_type=IndexType.scene,
scene_index_id=scene_index_id,
score_threshold=0.3,
)
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
Edición de línea de tiempo
Importante: Siempre valida las marcas de tiempo antes de construir una línea de tiempo:
startdebe ser >= 0 (los valores negativos se aceptan en silencio pero producen salida dañada)startdebe ser <endenddebe ser <=video.length
from videodb.timeline import Timeline
from videodb.asset import VideoAsset, TextAsset, TextStyle
timeline = Timeline(conn)
timeline.add_inline(VideoAsset(asset_id=video.id, start=10, end=30))
timeline.add_overlay(0, TextAsset(text="El Fin", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()
Transcodificar video (cambio de resolución / calidad)
from videodb import TranscodeMode, VideoConfig, AudioConfig
# Cambia resolución, calidad o relación de aspecto del lado del servidor
job_id = conn.transcode(
source="https://example.com/video.mp4",
callback_url="https://example.com/webhook",
mode=TranscodeMode.economy,
video_config=VideoConfig(resolution=720, quality=23, aspect_ratio="16:9"),
audio_config=AudioConfig(mute=False),
)
Reencuadrar relación de aspecto (para plataformas sociales)
Advertencia: reframe() es una operación lenta del lado del servidor. Para videos largos puede tomar
varios minutos y puede agotar el tiempo de espera. Mejores prácticas:
- Siempre limita a un segmento corto usando
start/endcuando sea posible - Para videos de duración completa, usa
callback_urlpara procesamiento asíncrono - Recorta el video en una
Timelineprimero, luego reencuadra el resultado más corto
from videodb import ReframeMode
# Siempre prefiere reencuadrar un segmento corto:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
# Reencuadre asíncrono para videos de duración completa (devuelve None, resultado vía webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")
# Ajustes preestablecidos: "vertical" (9:16), "square" (1:1), "landscape" (16:9)
reframed = video.reframe(start=0, end=60, target="square")
# Dimensiones personalizadas
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
Medios generativos
image = coll.generate_image(
prompt="una puesta de sol sobre montañas",
aspect_ratio="16:9",
)
Manejo de errores
from videodb.exceptions import AuthenticationError, InvalidRequestError
try:
conn = videodb.connect()
except AuthenticationError:
print("Verifica tu VIDEO_DB_API_KEY")
try:
video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
print(f"Error de subida: {e}")
Errores comunes
| Escenario | Mensaje de error | Solución |
|---|---|---|
| Indexar un video ya indexado | Spoken word index for video already exists | Usa video.index_spoken_words(force=True) para omitir si ya está indexado |
| El índice de escenas ya existe | Scene index with id XXXX already exists | Extrae el scene_index_id existente del error con re.search(r"id\s+([a-f0-9]+)", str(e)) |
| La búsqueda no encuentra coincidencias | InvalidRequestError: No results found | Captura la excepción y trata como resultados vacíos (shots = []) |
| Reencuadre se agota | Se bloquea indefinidamente en videos largos | Usa start/end para limitar el segmento, o pasa callback_url para asíncrono |
| Marcas de tiempo negativas en Timeline | Produce silenciosamente una transmisión dañada | Siempre valida start >= 0 antes de crear VideoAsset |
generate_video() / create_collection() falla | Operation not allowed o maximum limit | Funciones restringidas por plan — informa al usuario sobre los límites del plan |
Ejemplos
Indicaciones canónicas
- "Inicia la captura de escritorio y alerta cuando aparezca un campo de contraseña."
- "Graba mi sesión y produce un resumen procesable cuando termine."
- "Ingiere este archivo y devuelve un enlace de transmisión reproducible."
- "Indexa esta carpeta y encuentra cada escena con personas, devuelve marcas de tiempo."
- "Genera subtítulos, incrústalos y añade música de fondo suave."
- "Conecta esta URL RTSP y alerta cuando una persona entre en la zona."
Grabación de pantalla (Captura de escritorio)
Usa ws_listener.py para capturar eventos WebSocket durante las sesiones de grabación. La captura de escritorio es compatible solo con macOS.
Inicio rápido
- Elige el directorio de estado:
STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}" - Inicia el oyente:
VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" & - Obtén el ID de WebSocket:
cat "$STATE_DIR/videodb_ws_id" - Ejecuta el código de captura (consulta reference/capture.md para el flujo de trabajo completo)
- Eventos escritos en:
$STATE_DIR/videodb_events.jsonl
Usa --clear cada vez que inicies una ejecución de captura nueva para que los eventos de transcripción y visuales antiguos no contaminen la nueva sesión.
Consultar eventos
import json
import os
import time
from pathlib import Path
events_dir = Path(os.environ.get("VIDEODB_EVENTS_DIR", Path.home() / ".local" / "state" / "videodb"))
events_file = events_dir / "videodb_events.jsonl"
events = []
if events_file.exists():
with events_file.open(encoding="utf-8") as handle:
for line in handle:
try:
events.append(json.loads(line))
except json.JSONDecodeError:
continue
transcripts = [e["data"]["text"] for e in events if e.get("channel") == "transcript"]
cutoff = time.time() - 300
recent_visual = [
e for e in events
if e.get("channel") == "visual_index" and e["unix_ts"] > cutoff
]
Documentación adicional
La documentación de referencia se encuentra en el directorio reference/ junto a este archivo SKILL.md. Usa la herramienta Glob para localizarla si es necesario.
- reference/api-reference.md - Referencia completa de la API de VideoDB Python SDK
- reference/search.md - Guía detallada de búsqueda de video (palabras habladas y basada en escenas)
- reference/editor.md - Edición de línea de tiempo, activos y composición
- reference/streaming.md - Transmisión HLS y reproducción instantánea
- reference/generative.md - Generación de medios impulsada por IA (imágenes, video, audio)
- reference/rtstream.md - Flujo de trabajo de ingesta de transmisiones en vivo (RTSP/RTMP)
- reference/rtstream-reference.md - Métodos del SDK RTStream y pipelines de IA
- reference/capture.md - Flujo de trabajo de captura de escritorio
- reference/capture-reference.md - SDK de captura y eventos WebSocket
- reference/use-cases.md - Patrones y ejemplos comunes de procesamiento de video
No uses ffmpeg, moviepy o herramientas de codificación locales cuando VideoDB soporte la operación. Las siguientes operaciones se manejan todas del lado del servidor por VideoDB: recortar, combinar clips, superponer audio o música, agregar subtítulos, superposiciones de texto/imagen, transcodificación, cambios de resolución, conversión de relación de aspecto, redimensionamiento para requisitos de plataforma, transcripción y generación de medios. Solo recurre a herramientas locales para operaciones listadas bajo Limitaciones en reference/editor.md (transiciones, cambios de velocidad, recorte/zoom, gradación de color, mezcla de volumen).
Cuándo usar qué
| Problema | Solución VideoDB |
|---|---|
| La plataforma rechaza la relación de aspecto o resolución del video | video.reframe() o conn.transcode() con VideoConfig |
| Necesitas redimensionar video para Twitter/Instagram/TikTok | video.reframe(target="vertical") o target="square" |
| Necesitas cambiar la resolución (ej. 1080p → 720p) | conn.transcode() con VideoConfig(resolution=720) |
| Necesitas superponer audio/música en video | AudioAsset en una Timeline |
| Necesitas agregar subtítulos | video.add_subtitle() o CaptionAsset |
| Necesitas combinar/recortar clips | VideoAsset en una Timeline |
| Necesitas generar voz en off, música o efectos de sonido | coll.generate_voice(), generate_music(), generate_sound_effect() |
Procedencia
El material de referencia para esta habilidad se encuentra localmente en skills/videodb/reference/.
Usa las copias locales anteriores en lugar de seguir enlaces de repositorios externos en tiempo de ejecución.