Cómo hacer que Claude analice videos con frames
Extrae frames de un video y envíalos a Claude para que los analice con su capacidad de visión.

- Python 3.9+ instalado
- Cuenta en console.anthropic.com con API key
- ffmpeg instalado (brew/apt/choco)
- Librería opencv-python y anthropic (pip)
- Un video de prueba (.mp4) corto
- Por qué Claude no ingiere video nativamente y cómo resolverlo con frames
- Cómo extraer frames representativos con OpenCV a un intervalo definido
- Cómo codificar imágenes en base64 y enviarlas en un solo mensaje multimodal
- Cómo pedir a Claude un resumen temporal coherente del video
- Cómo controlar costes limitando resolución y número de frames
Instalar dependencias y configurar la API key
Claude (claude-opus-4-8) acepta imágenes en sus mensajes, pero no archivos de video directamente. La estrategia es convertir el video en una secuencia de fotogramas (frames) y enviarlos como imágenes. Primero prepara tu entorno. Crea un entorno virtual para no ensuciar tu sistema y instala las librerías necesarias: el SDK oficial de Anthropic y OpenCV para procesar el video. Luego exporta tu clave API, que obtienes en console.anthropic.com. En España y LATAM el proceso de alta es idéntico; solo asegúrate de tener método de pago activo para superar el tier gratuito. Guarda la clave como variable de entorno en lugar de hardcodearla en el código: es la práctica estándar para evitar filtrarla en repositorios Git.
python -m venv venv
source venv/bin/activate # en Windows: venv\Scripts\activate
pip install anthropic opencv-python
export ANTHROPIC_API_KEY='tu-api-key-aqui'Extraer frames del video con OpenCV
Enviar cada fotograma de un video de 30 fps saturaría el modelo y dispararía el coste. La clave es muestrear: extraer un frame cada N segundos. Este script abre el video, calcula los fps reales y guarda un frame por intervalo definido (por defecto cada 2 segundos). Limitamos también el número máximo de frames a 20 para mantener la petición dentro de límites razonables (Claude admite hasta 100 imágenes por request, pero más frames = más tokens y más coste). Redimensionamos cada frame para que su lado mayor no supere los 768px, tamaño más que suficiente para el análisis visual y que reduce drásticamente el consumo de tokens de visión. Los frames se guardan en una carpeta temporal que reutilizaremos en el siguiente paso.
import cv2, os
def extraer_frames(video_path, intervalo_seg=2, max_frames=20, out_dir='frames'):
os.makedirs(out_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS) or 30
paso = int(fps * intervalo_seg)
guardados, idx = [], 0
while len(guardados) < max_frames:
ok, frame = cap.read()
if not ok:
break
if idx % paso == 0:
h, w = frame.shape[:2]
escala = 768 / max(h, w)
if escala < 1:
frame = cv2.resize(frame, (int(w*escala), int(h*escala)))
ruta = f'{out_dir}/frame_{len(guardados):03d}.jpg'
cv2.imwrite(ruta, frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
guardados.append(ruta)
idx += 1
cap.release()
return guardados
frames = extraer_frames('mi_video.mp4')
print(f'Extraidos {len(frames)} frames')Codificar los frames en base64
La API de Claude recibe imágenes en dos formatos: por URL pública o como datos base64 embebidos. Para archivos locales usamos base64. Cada frame se lee en binario y se convierte a una cadena base64 junto con su media_type (image/jpeg). Construimos una lista de bloques de contenido con el formato exacto que espera el SDK. Este paso es puramente mecánico pero crítico: un media_type incorrecto o un base64 mal formado provoca un error 400. Reutilizamos la lista de rutas del paso anterior. Nota que también podríamos alternar bloques de texto entre imágenes para etiquetar cada frame con su marca de tiempo, lo que ayuda a Claude a razonar sobre la secuencia temporal.
import base64
def frame_a_bloque(ruta, segundo):
with open(ruta, 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
return [
{'type': 'text', 'text': f'Frame en el segundo {segundo}:'},
{'type': 'image', 'source': {
'type': 'base64',
'media_type': 'image/jpeg',
'data': b64
}}
]
bloques = []
for i, ruta in enumerate(frames):
bloques += frame_a_bloque(ruta, i * 2)
print(f'{len(bloques)} bloques de contenido listos')Enviar los frames a Claude y pedir análisis
Ahora componemos el mensaje multimodal: primero un bloque de texto con la instrucción, seguido de todos los bloques de frames. Usamos claude-opus-4-8, el modelo por defecto con capacidad de visión. En el prompt le pedimos explícitamente que trate las imágenes como frames consecutivos de un mismo video y que reconstruya la narrativa temporal, no que describa cada imagen aislada. Esto es lo que diferencia un simple análisis de imágenes de un verdadero 'entendimiento de video'. Ajusta max_tokens según el detalle que necesites en la respuesta.
import anthropic
client = anthropic.Anthropic() # lee ANTHROPIC_API_KEY del entorno
instruccion = {
'type': 'text',
'text': ('Las siguientes imagenes son frames consecutivos de un video, '
'ordenados cronologicamente con su marca de tiempo. '
'Describe que ocurre a lo largo del video como una secuencia '
'temporal coherente, no frame por frame. Incluye acciones, '
'cambios de escena y cualquier texto visible.')
}
msg = client.messages.create(
model='claude-opus-4-8',
max_tokens=1024,
messages=[{'role': 'user', 'content': [instruccion] + bloques}]
)
print(msg.content[0].text)Empaquetar todo en una función reutilizable
Junta los pasos anteriores en una única función analizar_video() que reciba la ruta del video y una pregunta opcional. Así puedes reutilizarla en un pipeline, un endpoint FastAPI o un script batch que procese varios videos. La función limpia también la carpeta temporal al terminar para no acumular frames en disco. Este empaquetado te permite integrarlo fácilmente en aplicaciones reales: por ejemplo, moderación de contenido de una plataforma en LATAM o generación automática de subtítulos descriptivos.
import shutil
def analizar_video(video_path, pregunta=None, intervalo_seg=2, max_frames=20):
frames = extraer_frames(video_path, intervalo_seg, max_frames)
bloques = []
for i, ruta in enumerate(frames):
bloques += frame_a_bloque(ruta, i * intervalo_seg)
texto = pregunta or ('Describe la secuencia temporal de este video '
'a partir de sus frames ordenados.')
instr = {'type': 'text', 'text': texto}
resp = client.messages.create(
model='claude-opus-4-8', max_tokens=1024,
messages=[{'role': 'user', 'content': [instr] + bloques}]
)
shutil.rmtree('frames', ignore_errors=True)
return resp.content[0].text
print(analizar_video('mi_video.mp4', '¿Cuantas personas aparecen y que hacen?'))Optimizar costes y precisión
El coste de un análisis de video escala con el número de frames y su resolución. Para optimizar: usa detección de cambios de escena para muestrear solo frames significativos en lugar de un intervalo fijo, reduce la resolución a 512px si el detalle fino no importa, y agrupa lotes de frames en varias requests si superas límites. Para mayor precisión temporal en videos con audio relevante, combina este flujo con una transcripción (por ejemplo Whisper) y pasa el texto transcrito junto a los frames: Claude así correlaciona lo visual con lo hablado. Monitoriza tu uso en el dashboard de la consola para no llevarte sorpresas en la factura, especialmente si procesas videos en producción.
import cv2
def frames_por_cambio(video_path, umbral=30.0, max_frames=20, out_dir='frames'):
os.makedirs(out_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
prev, guardados, idx = None, [], 0
while len(guardados) < max_frames:
ok, frame = cap.read()
if not ok:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if prev is None or cv2.absdiff(gray, prev).mean() > umbral:
ruta = f'{out_dir}/scene_{len(guardados):03d}.jpg'
cv2.imwrite(ruta, frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
guardados.append(ruta)
prev = gray
idx += 1
cap.release()
return guardadosHas construido un pipeline completo en Python que convierte cualquier video local en frames muestreados, los codifica en base64 y los envía a Claude opus-4-8 para obtener un análisis temporal coherente. Ahora puedes hacer que Claude 'vea' videos respondiendo preguntas sobre su contenido, generando descripciones o moderando material, controlando el coste mediante muestreo por intervalo o por cambio de escena.
Los programas de certificación en español te llevan de principiante a builder profesional con Claude y su API.
Ver todos los programas