Compreensão de vídeo em agentes
Extração de quadros, resumo de vídeos e raciocínio temporal sobre clipes.
Compreensão de vídeo em agentes é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.
Compreensão de vídeo para agentes
A maioria dos LLMs não consegue processar arquivos de vídeo diretamente, mas os agentes podem analisar vídeos extraindo quadros representativos e enviando-os como imagens. Em seguida, o agente raciocina sobre a sequência visual para detectar eventos, mudanças e padrões ao longo do tempo.
Instalação do OpenCV para extração de quadros
O OpenCV (cv2) é a biblioteca padrão para processamento de vídeo em Python. Ele permite abrir arquivos de vídeo, ler seus metadados (taxa de quadros, resolução e quantidade de quadros) e extrair quadros individuais como matrizes NumPy.
# pip install opencv-python-headless
import cv2
def get_video_metadata(video_path: str) -> dict:
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise IOError(f'Cannot open video: {video_path}')
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
duration_s = frame_count / fps if fps > 0 else 0
cap.release()
return {
'fps': round(fps, 2),
'frame_count': frame_count,
'width': width,
'height': height,
'duration_seconds': round(duration_s, 2)
}
meta = get_video_metadata('recording.mp4')
print(meta)Extração de quadros a cada N segundos
Na maioria das tarefas de compreensão de vídeo, não é necessário usar todos os quadros. A amostragem de um quadro a cada N segundos fornece um resumo representativo do conteúdo do vídeo. A 1 quadro por segundo, um vídeo de 60 segundos produz 60 quadros.
import cv2
import os
def extract_frames(
video_path: str,
output_dir: str,
every_n_seconds: float = 5.0
) -> list:
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_interval = int(fps * every_n_seconds)
os.makedirs(output_dir, exist_ok=True)
saved_frames = []
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_idx % frame_interval == 0:
timestamp = round(frame_idx / fps, 2)
fname = f'{output_dir}/frame_{frame_idx:06d}_{timestamp}s.jpg'
cv2.imwrite(fname, frame)
saved_frames.append({'path': fname, 'timestamp': timestamp})
frame_idx += 1
cap.release()
print(f'Extracted {len(saved_frames)} frames')
return saved_framesDetecção de mudança de cena
Em vez de fazer uma amostragem uniforme, extraia quadros nos limites das cenas — momentos em que o conteúdo visual muda significativamente. Isso fornece quadros mais informativos por chamada à API. Use a diferenciação de quadros: se a diferença absoluta média entre quadros consecutivos exceder um limiar, ocorreu uma mudança de cena.
import cv2
import numpy as np
def extract_scene_change_frames(
video_path: str,
output_dir: str,
diff_threshold: float = 30.0
) -> list:
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
os.makedirs(output_dir, exist_ok=True)
prev_gray = None
saved = []
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if prev_gray is not None:
diff = np.mean(np.abs(gray.astype(float) - prev_gray.astype(float)))
if diff > diff_threshold:
ts = round(frame_idx / fps, 2)
fname = f'{output_dir}/scene_{frame_idx:06d}_{ts}s.jpg'
cv2.imwrite(fname, frame)
saved.append({'path': fname, 'timestamp': ts, 'diff': round(diff, 2)})
prev_gray = gray
frame_idx += 1
cap.release()
return savedEnvio de uma sequência de quadros à API de visão
Envie vários quadros extraídos à API de visão em uma única mensagem. Inclua a marcação de tempo de cada quadro para que o modelo possa raciocinar sobre a ordem temporal e a duração. Peça explicitamente raciocínio temporal na sua instrução.
import base64
import anthropic
def describe_video_frames(frame_info_list: list, query: str) -> str:
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
content = []
for fi in frame_info_list:
with open(fi['path'], 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
content.append({
'type': 'text',
'text': f'Frame at {fi["timestamp"]}s:'
})
content.append({
'type': 'image',
'source': {'type': 'base64', 'media_type': 'image/jpeg', 'data': b64}
})
content.append({'type': 'text', 'text': query})
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=1024,
messages=[{'role': 'user', 'content': content}]
)
return response.content[0].textInstruções para raciocínio temporal
O raciocínio temporal exige uma formulação específica da instrução. Peça ao modelo que compare os quadros explicitamente, observe o que mudou, estime a duração das atividades e identifique relações causais entre os quadros.
TEMPORAL_QUERY = (
'You are analysing a video sequence. The frames above are in chronological order '
'with their timestamps shown. Please:\n'
'1. Describe what changed between the first and last frame\n'
'2. Identify any notable events and when they occurred (timestamp)\n'
'3. Summarise the overall activity shown in the video\n'
'4. Estimate the total duration of the main activity\n'
'Be specific about timestamps.'
)
# More targeted temporal query:
CHANGE_DETECTION_QUERY = (
'Compare frame at {start_ts}s and frame at {end_ts}s. '
'List all visible differences in bullet points. '
'Categorise each change as: object_moved, object_added, '
'object_removed, lighting_change, or camera_move.'
)
# Usage:
query = CHANGE_DETECTION_QUERY.format(start_ts=0.0, end_ts=20.0)
if __name__ == '__main__':
print('Temporal reasoning query:')
print(TEMPORAL_QUERY)
print()
print('Change detection query:')
print(query)
Fluxo de resumo de vídeo
Um fluxo completo de resumo de vídeo é: extrair quadros → enviá-los ao modelo de visão em lotes → coletar os resumos de cada lote → sintetizar o resumo final. O processamento em lotes evita exceder o limite da janela de contexto.
def summarise_video(
video_path: str,
every_n_seconds: float = 10.0,
batch_size: int = 5
) -> str:
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
# Extract frames
frames = extract_frames(video_path, '/tmp/video_frames', every_n_seconds)
# Process in batches
batch_summaries = []
for i in range(0, len(frames), batch_size):
batch = frames[i:i + batch_size]
ts_range = f'{batch[0]["timestamp"]}s - {batch[-1]["timestamp"]}s'
query = f'Summarise what happens in this video segment ({ts_range}).'
summary = describe_video_frames(batch, query)
batch_summaries.append(f'[{ts_range}] {summary}')
# Synthesise
all_summaries = '\n\n'.join(batch_summaries)
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content':
f'Here are segment-level video summaries:\n\n{all_summaries}\n\n'
'Write a single coherent summary of the entire video.'
}]
)
return result.content[0].textRastreamento de objetos entre quadros
Peça ao modelo de visão que rastreie objetos específicos ao longo de uma sequência de quadros. Por exemplo: 'Em cada quadro, descreva a posição do carro vermelho: canto superior esquerdo, canto superior direito, centro, canto inferior esquerdo, canto inferior direito.' Isso cria uma trajetória aproximada do movimento sem algoritmos de rastreamento de visão computacional.
def track_object_across_frames(
frames: list,
object_description: str
) -> list:
import anthropic, base64
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
trajectory = []
for fi in frames:
with open(fi['path'], 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=128,
messages=[{
'role': 'user',
'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text':
f'Where is the {object_description} in this frame? '
'Answer with one of: top-left, top-right, centre, '
'bottom-left, bottom-right, not-visible.'}
]
}]
)
trajectory.append({
'timestamp': fi['timestamp'],
'position': response.content[0].text.strip()
})
return trajectoryComo lidar com limites de quantidade de quadros
As janelas de contexto da API de visão têm limites para a quantidade de imagens que pode ser enviada por solicitação (normalmente, de 5 a 20 imagens). Para vídeos longos, use uma abordagem hierárquica: analise os segmentos de forma independente e depois combine os resumos dos segmentos em um resumo final usando uma segunda chamada ao LLM.
MAX_FRAMES_PER_REQUEST = 8
def hierarchical_video_analysis(frames: list, final_query: str) -> str:
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
# Level 1: analyse each chunk
chunk_summaries = []
for i in range(0, len(frames), MAX_FRAMES_PER_REQUEST):
chunk = frames[i:i + MAX_FRAMES_PER_REQUEST]
ts = f'{chunk[0]["timestamp"]}s-{chunk[-1]["timestamp"]}s'
summary = describe_video_frames(
chunk, f'What happens in this segment ({ts})?'
)
chunk_summaries.append(f'Segment {ts}: {summary}')
# Level 2: synthesise all chunk summaries
combined = '\n'.join(chunk_summaries)
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{
'role': 'user',
'content': f'Video segments:\n{combined}\n\n{final_query}'
}]
)
return result.content[0].textCombinação da análise de áudio e vídeo
Para obter a compreensão mais completa, combine a análise visual em nível de quadro com a transcrição de áudio do Whisper. O agente pode correlacionar o que é visto com o que é dito em cada marcação de tempo, possibilitando tarefas avançadas como análise de reuniões ou indexação de tutoriais.
def full_video_analysis(video_path: str) -> dict:
import subprocess
# Step 1: Extract audio track
audio_path = '/tmp/video_audio.mp3'
subprocess.run([
'ffmpeg', '-i', video_path, '-q:a', '0', '-map', 'a',
audio_path, '-y'
], capture_output=True)
# Step 2: Transcribe audio
transcript_data = transcribe_with_timestamps(audio_path)
# Step 3: Extract key frames
frames = extract_frames(video_path, '/tmp/key_frames', every_n_seconds=15.0)
# Step 4: Visual summary
visual_summary = hierarchical_video_analysis(
frames, 'Summarise the visual content.'
)
return {
'transcript': transcript_data['full_text'],
'transcript_segments': transcript_data['segments'],
'visual_summary': visual_summary,
'frame_count': len(frames)
}Limpeza e gerenciamento de quadros
Os quadros extraídos podem se acumular rapidamente. Sempre limpe os arquivos temporários de quadros após o processamento e implemente uma memória cache de quadros indexada por um hash de (caminho do vídeo, taxa de quadros) para evitar a reextração durante análises repetidas do mesmo vídeo.
import os
import shutil
import hashlib
FRAME_CACHE_DIR = '/tmp/frame_cache'
def get_cache_key(video_path: str, every_n_seconds: float) -> str:
content = f'{video_path}:{every_n_seconds}'
return hashlib.md5(content.encode()).hexdigest()[:12]
def get_or_extract_frames(video_path: str, every_n_seconds: float) -> list:
key = get_cache_key(video_path, every_n_seconds)
cache_dir = os.path.join(FRAME_CACHE_DIR, key)
if os.path.exists(cache_dir):
print(f'Cache hit: {key}')
files = sorted(os.listdir(cache_dir))
return [
{'path': os.path.join(cache_dir, f),
'timestamp': float(f.split('_')[-1].replace('s.jpg', ''))}
for f in files if f.endswith('.jpg')
]
return extract_frames(video_path, cache_dir, every_n_seconds)
def clear_frame_cache():
if os.path.exists(FRAME_CACHE_DIR):
shutil.rmtree(FRAME_CACHE_DIR)
print('Frame cache cleared')Verificação de conhecimento
Por que a detecção de mudança de cena é preferível à amostragem uniforme de quadros para a análise de vídeo?
Recapitulação: compreensão de vídeo em agentes
Muito bem! Principais aprendizados desta lição:
- OpenCV: extraia quadros com
cap.read(); faça amostragens a cada N segundos ou nas mudanças de cena - Sequências de quadros: envie-as em ordem cronológica, com marcações de tempo para fornecer contexto temporal
- Análise hierárquica: divida em lotes → resumos dos segmentos → síntese final
- Análise combinada: o ffmpeg extrai o áudio; o Whisper faz a transcrição; faça a comparação com os quadros visuais
- Memória cache de quadros: evite extrações redundantes com um diretório de cache indexado por hash
Próximo: raciocínio entre modalidades — quando o texto diz uma coisa e a imagem mostra outra.
Aprenda AI Agents com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 60
- Aulas
- 239
Perguntas Frequentes
A aula “Compreensão de vídeo em agentes” é grátis?
Sim — o texto completo de “Compreensão de vídeo em agentes” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.
O que vou aprender em “Compreensão de vídeo em agentes”?
Extração de quadros, resumo de vídeos e raciocínio temporal sobre clipes. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Agents?
Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Compreensão de vídeo em agentes”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Agents?
Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Agentes de imagem + texto com Claude Vision e GPT-4V
- Fluxos de trabalho de agentes de áudio + texto
- Compreensão de vídeo em agentes
- Padrões de raciocínio entre modalidades