0Pricing
AI Agents · Leçon

Compréhension vidéo par les agents

Extraction d’images, résumé vidéo et raisonnement temporel sur des extraits.

Compréhension vidéo par les agents est une leçon AI Agents gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Agents, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Agents comprend 4 leçons au total.

Compréhension vidéo pour les agents

La plupart des LLM ne peuvent pas traiter directement les fichiers vidéo, mais les agents peuvent analyser une vidéo en extrayant des images représentatives et en les envoyant comme images. L’agent raisonne ensuite sur la séquence visuelle afin de détecter les événements, les changements et les tendances au fil du temps.

Installer OpenCV pour extraire des images

OpenCV (cv2) est la bibliothèque standard de traitement vidéo en Python. Elle vous permet d’ouvrir des fichiers vidéo, de lire leurs métadonnées (fréquence d’images, résolution et nombre d’images) et d’extraire des images individuelles sous forme de tableaux 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)

Extraire une image toutes les N secondes

Pour la plupart des tâches de compréhension vidéo, vous n’avez pas besoin de chaque image. Échantillonner une image toutes les N secondes fournit un résumé représentatif du contenu vidéo. À raison d’une image par seconde, une vidéo de 60 secondes produit 60 images.

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_frames

Détection des changements de scène

Au lieu d’un échantillonnage uniforme, extrayez des images aux limites des scènes, c’est-à-dire aux moments où le contenu visuel change de manière significative. Vous obtenez ainsi des images plus informatives par appel d’API. Utilisez la différence entre les images : si la différence absolue moyenne entre deux images consécutives dépasse un seuil, un changement de scène s’est produit.

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 saved

Envoyer une séquence d’images à l’API de vision

Envoyez plusieurs images extraites à l’API de vision dans un seul message. Incluez l’horodatage de chaque image afin que le modèle puisse raisonner sur l’ordre temporel et la durée. Demandez explicitement un raisonnement temporel dans votre instruction.

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].text

Instructions pour le raisonnement temporel

Le raisonnement temporel nécessite une formulation précise de l’instruction. Demandez au modèle de comparer explicitement les images, de relever les changements, d’estimer la durée des activités et d’identifier les relations de cause à effet entre les images.

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)

Chaîne de traitement pour résumer une vidéo

Une chaîne complète de résumé vidéo suit les étapes suivantes : extraire les images → les envoyer au modèle de vision par lots → recueillir les résumés de chaque lot → synthétiser le résumé final. Le traitement par lots évite de dépasser la limite de la fenêtre de contexte.

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].text

Suivi des objets entre les images

Demandez au modèle de vision de suivre des objets précis dans une séquence d’images. Par exemple : « Dans chaque image, décrivez la position de la voiture rouge : en haut à gauche, en haut à droite, au centre, en bas à gauche ou en bas à droite. » Vous obtenez ainsi une trajectoire de mouvement approximative, sans algorithmes de suivi par vision par ordinateur.

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 trajectory

Gérer les limites du nombre d’images

Les fenêtres de contexte des API de vision limitent le nombre d’images pouvant être envoyées par requête (généralement 5 à 20 images). Pour les vidéos longues, utilisez une approche hiérarchique : analysez les segments indépendamment, puis fusionnez leurs résumés en un résumé final au moyen d’un second appel à un 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].text

Combiner l’analyse audio et vidéo

Pour obtenir la compréhension la plus riche possible, combinez l’analyse visuelle au niveau des images avec la transcription audio de Whisper. L’agent peut mettre en relation ce qui est vu avec ce qui est dit à chaque horodatage, ce qui permet des tâches avancées comme l’analyse de réunions ou l’indexation de tutoriels.

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)
    }

Nettoyage et gestion des images

Les images extraites peuvent rapidement s’accumuler. Supprimez toujours les fichiers d’images temporaires après le traitement et implémentez un cache d’images indexé par le hachage du chemin de la vidéo et de la fréquence d’images afin d’éviter de nouvelles extractions lors des analyses répétées de la même vidéo.

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')

Vérification des connaissances

Pourquoi la détection des changements de scène est-elle préférable à l’échantillonnage uniforme des images pour l’analyse vidéo ?

Récapitulatif : compréhension vidéo par les agents

Bravo ! Points essentiels de cette leçon :

  • OpenCV : extrayez les images avec cap.read() ; échantillonnez toutes les N secondes ou lors des changements de scène
  • Séquences d’images : envoyez-les dans l’ordre chronologique avec leurs horodatages pour conserver le contexte temporel
  • Analyse hiérarchique : diviser en lots → résumés des segments → synthèse finale
  • Analyse combinée : ffmpeg extrait l’audio ; Whisper le transcrit ; recoupez-le avec les images
  • Cache d’images : évitez les extractions redondantes avec un répertoire de cache indexé par hachage

Ensuite : le raisonnement multimodal — lorsque le texte dit une chose et que l’image en montre une autre.

Questions Fréquemment Posées

La leçon « Compréhension vidéo par les agents » est-elle gratuite ?

Oui — le texte complet de « Compréhension vidéo par les agents » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Agents, passe à CoddyKit PRO. Le cours AI Agents comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Compréhension vidéo par les agents » ?

Extraction d’images, résumé vidéo et raisonnement temporel sur des extraits. Tu pratiques AI Agents avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Agents ?

Aucune expérience préalable n'est requise. AI Agents sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Compréhension vidéo par les agents » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Agents ?

Oui. Chaque leçon AI Agents inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Agents image + texte avec Claude Vision et GPT-4V
  2. Flux de travail d’agents audio + texte
  3. Compréhension vidéo par les agents
  4. Schémas de raisonnement multimodal
← Retour à AI Agents