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/detones en tiempo real sobre lo que se dice y lo que sucede en pantalla
- Producir resúmenes de sesión, una línea de tiempo buscable y enlaces de evidencia reproducibles
Ingesta + transmisión de video
- Ingestar un archivo o URL y devolver un enlace de flujo web reproducible
- Transcodificar/normalizar: códec, bitrate, fps, resolución, relación de aspecto
Indexar + buscar (marcas de tiempo + evidencia)
- Construir índices visuales, de palabras habladas y de palabras clave
- Buscar y devolver momentos exactos con marcas de tiempo y evidencia reproducible
- Crear automáticamente clips a partir de los resultados de búsqueda
Edición y generación de línea de tiempo
- Subtítulos: generar, traducir, incrustar
- Superposiciones: texto/imagen/marca, subtítulos animados
- Audio: música de fondo, locución, doblaje
- Composición programática y exportaciones mediante operaciones de línea de tiempo
Transmisiones en vivo (RTSP) + monitoreo
- Conectar transmisiones RTSP/en vivo
- Ejecutar comprensión visual y de palabras habladas en tiempo real y emitir eventos/alertas para flujos 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 indexación, consulta de búsqueda, rangos de clip, ediciones de línea de tiempo, reglas de alerta
Salidas comunes
- URL de flujo
- 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, cambie al directorio del proyecto y cargue 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á exportado)
- Archivo
.envdel proyecto en el directorio actual
Si la clave falta, videodb.connect() genera AuthenticationError automáticamente.
NO escriba un archivo de script cuando un comando corto en línea funcione.
Al escribir Python en línea (python -c "..."), use siempre código formateado correctamente — use punto y coma para separar declaraciones y manténgalo legible. Para cualquier cosa de más de ~3 declaraciones, use 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, instale sin el extra de captura:
pip install videodb python-dotenv
2. Configurar clave API
El usuario debe establecer VIDEO_DB_API_KEY usando cualquiera de los métodos:
- Exportar en terminal (antes de iniciar Claude):
export VIDEO_DB_API_KEY=tu-clave - Archivo
.envdel proyecto: GuardeVIDEO_DB_API_KEY=tu-claveen el archivo.envdel proyecto
Obtenga una clave API gratuita en console.videodb.io (50 subidas gratuitas, sin tarjeta de crédito).
NO lea, escriba ni maneje la clave API usted mismo. Siempre deje que el usuario la configure.
Referencia rápida
Subir medios
# 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() genera InvalidRequestError cuando no se encuentran resultados.
# Siempre envuélvalo en try/except y trate "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 — genera un error si ya existe un
# índice de escenas. Extraiga el ID del índice existente del error.
try:
scene_index_id = video.index_scenes(
extraction_type=SceneExtractionType.shot_based,
prompt="Describe el contenido visual en 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
# Use score_threshold para filtrar ruido de baja relevancia (recomendado: 0.3+)
try:
results = video.search(
query="persona escribiendo en una pizarra",
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 valide las marcas de tiempo antes de construir una línea de tiempo:
startdebe ser >= 0 (los valores negativos se aceptan silenciosamente 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
# Cambiar resolución, calidad o relación de aspecto en el 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 redes 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 limite a un segmento corto usando
start/endcuando sea posible - Para videos completos, use
callback_urlpara procesamiento asíncrono - Recorte el video en una
Timelineprimero, luego reencuadre el resultado más corto
from videodb import ReframeMode
# Siempre prefiera reencuadrar un segmento corto:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
# Reencuadre asíncrono para videos completos (devuelve None, resultado vía webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")
# Preajustes: "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="un atardecer sobre montañas",
aspect_ratio="16:9",
)
Manejo de errores
from videodb.exceptions import AuthenticationError, InvalidRequestError
try:
conn = videodb.connect()
except AuthenticationError:
print("Verifique su VIDEO_DB_API_KEY")
try:
video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
print(f"Subida fallida: {e}")
Errores comunes
| Escenario | Mensaje de error | Solución |
|---|---|---|
| Indexar un video ya indexado | Spoken word index for video already exists | Use 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 | Extraiga 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 | Capture la excepción y trate como resultados vacíos (shots = []) |
| Reencuadre agota el tiempo | Se bloquea indefinidamente en videos largos | Use start/end para limitar el segmento, o pase callback_url para asíncrono |
| Marcas de tiempo negativas en Timeline | Produce silenciosamente un flujo dañado | Siempre valide start >= 0 antes de crear VideoAsset |
generate_video() / create_collection() falla | Operation not allowed o maximum limit | Características restringidas por plan — informe al usuario sobre 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."
- "Ingesta este archivo y devuelve un enlace de flujo reproducible."
- "Indexa esta carpeta y encuentra cada escena con personas, devuelve marcas de tiempo."
- "Genera subtítulos, incrústalos y agrega música de fondo ligera."
- "Conecta esta URL RTSP y alerta cuando una persona entre en la zona."
Grabación de pantalla (Captura de escritorio)
Use 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
- Elija directorio de estado:
STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}" - Inicie el listener:
VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" & - Obtenga el ID de WebSocket:
cat "$STATE_DIR/videodb_ws_id" - Ejecute el código de captura (consulte reference/capture.md para el flujo de trabajo completo)
- Eventos escritos en:
$STATE_DIR/videodb_events.jsonl
Use --clear cada vez que inicie una ejecución de captura nueva para que los eventos de transcripción y visuales obsoletos no se filtren en 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 está en el directorio reference/ adyacente a este archivo SKILL.md. Use la herramienta Glob para localizarla si es necesario.
- reference/api-reference.md - Referencia completa de la API del SDK de Python de VideoDB
- 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 comunes de procesamiento de video y ejemplos
No use ffmpeg, moviepy o herramientas de codificación local cuando VideoDB admita la operación. Lo siguiente se maneja todo en el servidor por VideoDB — recorte, combinación de clips, superposición de audio o música, adición de 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 recurra 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 de VideoDB |
|---|---|
| La plataforma rechaza la relación de aspecto o resolución del video | video.reframe() o conn.transcode() con VideoConfig |
| Necesita redimensionar video para Twitter/Instagram/TikTok | video.reframe(target="vertical") o target="square" |
| Necesita cambiar resolución (ej. 1080p → 720p) | conn.transcode() con VideoConfig(resolution=720) |
| Necesita superponer audio/música en video | AudioAsset en una Timeline |
| Necesita agregar subtítulos | video.add_subtitle() o CaptionAsset |
| Necesita combinar/recortar clips | VideoAsset en una Timeline |
| Necesita generar locución, 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 bajo skills/videodb/reference/.
Use las copias locales anteriores en lugar de seguir enlaces de repositorios externos en tiempo de ejecución.