0Pricing
AI Agents · Lektion

Videoverständnis in Agenten

Frames extrahieren, Videos zusammenfassen und Clips zeitlich analysieren.

Videoverständnis in Agenten ist eine kostenlose AI Agents-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Agents-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.

Videoverständnis für Agenten

Die meisten LLMs können Videodateien nicht direkt verarbeiten. Agenten können Videos jedoch analysieren, indem sie repräsentative Frames extrahieren und als Bilder senden. Anschließend schließt der Agent aus der visuellen Abfolge auf Ereignisse, Veränderungen und Muster im Zeitverlauf.

OpenCV zur Frame-Extraktion installieren

OpenCV (cv2) ist die Standardbibliothek für die Videoverarbeitung in Python. Damit können Sie Videodateien öffnen, ihre Metadaten auslesen (Bildrate, Auflösung, Frame-Anzahl) und einzelne Frames als NumPy-Arrays extrahieren.

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

Frames alle N Sekunden extrahieren

Für die meisten Aufgaben zum Videoverständnis benötigen Sie nicht jeden Frame. Die Entnahme eines Frames alle N Sekunden liefert eine repräsentative Zusammenfassung des Videoinhalts. Bei 1 Frame pro Sekunde erzeugt ein 60 Sekunden langes Video 60 Frames.

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

Erkennung von Szenenwechseln

Statt gleichmäßig zu sampeln, extrahieren Sie Frames an Szenengrenzen – also an Zeitpunkten, an denen sich der visuelle Inhalt deutlich verändert. Dadurch erhalten Sie pro API-Aufruf informativere Frames. Verwenden Sie die Frame-Differenzbildung: Überschreitet die mittlere absolute Differenz zwischen aufeinanderfolgenden Frames einen Schwellenwert, ist ein Szenenwechsel aufgetreten.

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

Eine Frame-Sequenz an die Vision API senden

Senden Sie mehrere extrahierte Frames in einer einzigen Nachricht an die Vision API. Geben Sie den Zeitstempel jedes Frames an, damit das Modell zeitliche Reihenfolge und Dauer berücksichtigen kann. Fordern Sie in Ihrem Prompt ausdrücklich zeitliches Schlussfolgern an.

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

Prompts für zeitliches Schlussfolgern

Zeitliches Schlussfolgern erfordert eine gezielte Gestaltung des Prompts. Fordern Sie das Modell auf, Frames ausdrücklich zu vergleichen, Veränderungen zu benennen, die Dauer von Aktivitäten zu schätzen und kausale Zusammenhänge zwischen den Frames zu erkennen.

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)

Pipeline zur Videozusammenfassung

Eine vollständige Pipeline zur Videozusammenfassung besteht aus folgenden Schritten: Frames extrahieren → in Batches an das Vision-Modell senden → Zusammenfassungen pro Batch sammeln → eine abschließende Zusammenfassung erstellen. Durch Batching wird verhindert, dass das Kontextfenster überschritten wird.

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

Objektverfolgung über mehrere Frames

Bitten Sie das Vision-Modell, bestimmte Objekte über eine Frame-Sequenz hinweg zu verfolgen. Zum Beispiel: 'Beschreiben Sie in jedem Frame die Position des roten Autos: oben links, oben rechts, Mitte, unten links, unten rechts.' Dadurch entsteht eine grobe Bewegungsbahn, ohne dass Computer-Vision-Algorithmen zur Verfolgung erforderlich sind.

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

Umgang mit Frame-Anzahllimits

Die Kontextfenster von Vision-APIs begrenzen die Anzahl der Bilder, die pro Anfrage gesendet werden können (typischerweise 5–20 Bilder). Verwenden Sie bei langen Videos einen hierarchischen Ansatz: Analysieren Sie Segmente unabhängig voneinander und fügen Sie anschließend die Segmentzusammenfassungen in einem zweiten LLM-Aufruf zu einer abschließenden Zusammenfassung zusammen.

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

Audio- und Videoanalyse kombinieren

Für ein möglichst umfassendes Verständnis kombinieren Sie die visuelle Analyse auf Frame-Ebene mit der Audiotranskription durch Whisper. Der Agent kann zu jedem Zeitstempel das Gesehene mit dem Gesagten abgleichen und so leistungsfähige Aufgaben wie Besprechungsanalysen oder die Indexierung von Tutorials ermöglichen.

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

Aufräumen und Frame-Verwaltung

Extrahierte Frames können sich schnell ansammeln. Löschen Sie temporäre Frame-Dateien nach der Verarbeitung immer und implementieren Sie einen Frame-Cache, dessen Schlüssel aus einem Hash von (video_path, frame_rate) besteht, um bei wiederholten Analysen desselben Videos eine erneute Extraktion zu vermeiden.

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

Wissensüberprüfung

Warum ist die Erkennung von Szenenwechseln bei der Videoanalyse dem gleichmäßigen Sampling von Frames vorzuziehen?

Zusammenfassung: Videoverständnis in Agenten

Gut gemacht! Die wichtigsten Erkenntnisse aus dieser Lektion:

  • OpenCV: Frames mit cap.read() extrahieren; alle N Sekunden oder bei Szenenwechseln samplen
  • Frame-Sequenzen: für den zeitlichen Kontext in chronologischer Reihenfolge mit Zeitstempeln senden
  • Hierarchische Analyse: in Batches aufteilen → Segmentzusammenfassungen → abschließende Synthese
  • Kombinierte Analyse: ffmpeg extrahiert Audio; Whisper transkribiert; mit visuellen Frames abgleichen
  • Frame-Cache: redundante Extraktion mit einem hashbasierten Cache-Verzeichnis vermeiden

Als Nächstes: modalitätsübergreifendes Schlussfolgern – wenn der Text etwas anderes sagt als das Bild zeigt.

Häufig gestellte Fragen

Ist die Lektion „Videoverständnis in Agenten“ kostenlos?

Ja — der vollständige Text von „Videoverständnis in Agenten“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Agents-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Videoverständnis in Agenten“?

Frames extrahieren, Videos zusammenfassen und Clips zeitlich analysieren. Du übst AI Agents mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Agents zu starten?

Keine Vorkenntnisse erforderlich. AI Agents auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Videoverständnis in Agenten“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Agents-Lektion Code schreiben und ausführen?

Ja. Jede AI Agents-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Bild- und Textagenten mit Claude Vision und GPT-4V
  2. Agenten-Workflows für Audio und Text
  3. Videoverständnis in Agenten
  4. Muster für multimodales Reasoning
← Zurück zu AI Agents