Einladen & verdienen

So funktionieren Einladungsboni

Teile deinen Einladungslink. Registriert sich ein Freund darüber und lädt Guthaben auf, erhältst du die angezeigte Prämie für seine weiteren Aufladungen.

Indexierung langer Videos mit der Gemini API: Zeitstempel, visuelle Inhalte und Lücken-Audits

Ein technischer Workflow zur Indexierung langer Videoaufnahmen mit der Gemini API: Upload über die Files API, Erstellung agentischer Entwürfe in der Interactions API, programmatische Validierung strukturierter TSV-Zeilen und gezielte Überprüfung von Erfassungslücken.

Inhalt
Indexierung langer Videos mit der Gemini API: Zeitstempel, visuelle Inhalte und Lücken-Audits

Lange Videoaufnahmen – wie technische Vorträge, Workshops, Architektur-Reviews oder Screencasts – bieten eine enorme Informationsdichte über gesprochenes Audio und Bildschirminhalte hinweg. Standardmäßige Zusammenfassungen auf hoher Abstraktionsebene erfassen meist nur grobe Themen. Müssen Entwickler einen bestimmten Terminal-Befehl oder Konfigurationsparameter wiederfinden, bleibt ihnen oft nichts anderes übrig, als das Videomaterial mühsam manuell zu durchsuchen.

Multimodale Gemini-Modelle können Audio- und Videoströme simultan analysieren und strukturierte Ereignisindizes mit Zeitstempeln erstellen. Die Rohausgabe eines ersten Modell-Inferenzdurchlaufs ist jedoch nur ein Satz von Entwurfskandidaten und noch kein produktionsreifes Referenzverzeichnis. Der Aufbau eines verlässlichen Index erfordert eine disziplinierte Pipeline: einmaliger Upload über die Files API und Wiederverwendung der URI, Extrahieren von Entwurfsintervallen, strikte Validierung des Ausgabeschemas, Audit verdächtiger Erfassungslücken und eine gezielte manuelle Kalibrierung.


Architektur: Bereitstellungsmethoden und Verarbeitungsmodi

In der aktuellen Google Video Understanding-Dokumentation konzentrieren sich primäre Implementierungen auf die Interactions API und die Bibliothek google-genai. Während die traditionelle Methode generate_content zur Abwärtskompatibilität weiterhin unterstützt wird, bietet die Interactions API eine transparentere Steuerung multimodaler Verarbeitungsparameter.

1. Methoden zur Videobereitstellung

  • Files API (Empfohlen für lange Videos): Bestens geeignet für Aufnahmen mit einer Dauer von mehreren Minuten bis zu mehreren Stunden. Die Datei wird einmalig hochgeladen, serverseitig vorverarbeitet und indexiert und anschließend per URI über wiederholte Anfragen hinweg referenziert – ohne dass Rohdaten erneut übertragen werden müssen.
  • Google Cloud Storage (GCS): Ideal für bestehende Videoarchive, die bereits in der Google Cloud-Infrastruktur gehostet werden.
  • Inline-Daten (Inline Data): Direkte Übertragung von Rohbytes innerhalb der Request-Payload. Die Dokumentation beschreibt je nach Umgebung unterschiedliche Payload-Beschränkungen; für eine stabile Verarbeitung einstündiger Medien ist die Files API oder Cloud Storage eine praktische Wahl, um rohe Videostreams inline zu vermeiden.

2. Verarbeitungsmodi: Static vs. Agentic

  • Statisches Processing (Static Processing):
    Standardmäßig tastet das Modell Frames mit einer diskreten Rate von 1 Frame pro Sekunde (1 FPS) ab. Jede Sekunde wird in Token konvertiert, was über eine Dauer von 60 Minuten eine beträchtliche Kontextlast erzeugt. Zu beachten ist: Ein 1-FPS-Sampling kann kurze visuelle Ereignisse verpassen (wie Fensterwechsel im Subsekundenbereich oder flüchtige Tooltips) und garantiert nicht die Erfassung jeder Mikro-Interaktion.
  • Agentisches Video-Verständnis (Agentic Video Understanding):
    Das Modell navigiert dynamisch durch das Video und ruft gezielt Frames und Audioabschnitte nach Bedarf ab. Dies reduziert das Volumen der verarbeiteten Kontext-Token drastisch.
    Einschränkung: Die agentische Heuristik stützt sich auf akustische Hinweise und semantische Auslöser. Führt ein Sprecher Aktionen stumm auf dem Bildschirm aus (wie das Tippen eines Befehls oder das Prüfen eines Diagramms), ohne zu sprechen, stuft die Heuristik dieses Intervall möglicherweise als Leerlauf ein und überspringt die Anforderung detaillierter visueller Frames.

Schritt 1: Video-Upload und Status-Polling

Dateien, die an die Files API übermittelt werden, stehen nicht sofort für die Inferenz bereit; der Server muss den Container entpacken und die audiovisuellen Spuren indexieren. Die Anwendung muss die Ressource per Polling abfragen, bis ihr Status ACTIVE lautet.

import time
from google import genai

client = genai.Client()

video_path = "tech_workshop_60min.mp4"
video_file = client.files.upload(file=video_path)

while not video_file.state or video_file.state.name != "ACTIVE":
    if video_file.state and video_file.state.name == "FAILED":
        error_info = getattr(video_file, "error", None)
        raise RuntimeError(
            f"Файл перешел в статус FAILED. Детали: {error_info}. "
            "Проверьте кодеки, целостность контейнера или повторите попытку."
        )
    time.sleep(5)
    video_file = client.files.get(name=video_file.name)

print("Видео готово к обработке.")

Schritt 2: Entwurfsindex über die Interactions API anfordern

Rufe für lange Aufnahmen client.interactions.create mit dem Parameter "processing": "agentic" auf. Der Prompt erzwingt eine strikte tabellarische Ausgabe: Zeitstempelbereich MM:SS - MM:SS, Ereignistyp (visual, speech, hybrid), eine prägnante inhaltliche Aussage (CLAIM) und die Bildschirmaktion (ACTION).

index_prompt = """
Ты — инструмент технической индексации видеозаписей. 
Сформируй хронологический индекс событий для всей 60-минутной записи от 00:00 до 60:00.

Требования к структуре ответа:
1. Выведи результат построчно в формате TSV с разделителем |.
2. Каждая строка должна содержать ровно 5 полей:
   START_TIME (MM:SS) | END_TIME (MM:SS) | TYPE (visual/speech/hybrid) | CLAIM | ACTION
3. Не объединяй слишком длинные интервалы в одну запись; фиксируй смену слайдов, терминал, ошибки и выводы спикера.
4. Если речи не было, в поле CLAIM укажи NONE. Если на экране не было динамики, в ACTION укажи STATIC.
5. Выводи исключительно строки данных без вводных слов и пояснений.
"""

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "video",
            "uri": video_file.uri,
            "mime_type": video_file.mime_type,
            "processing": "agentic"
        },
        {
            "type": "text",
            "text": index_prompt
        }
    ]
)

raw_index_output = interaction.output_text

Zu agentischen Navigationsschritten:
Das Vorhandensein von processing_call-Einträgen innerhalb von interaction.steps bestätigt, dass das Modell dynamisch durch die Video-Timeline navigiert ist, anstatt einen kontinuierlichen Stream einzulesen. Das Vorhandensein dieser Aufrufe bestätigt jedoch lediglich die Navigationsaktivität – es garantiert keine Vollständigkeit der Ausgabe über alle relevanten Timeline-Ereignisse hinweg.


Schritt 3: Beispiel für die Ausgabestruktur (hypothetischer Entwurf)

Nachfolgend zeigt ein hypothetischer Auszug aus der Modellausgabe das erwartete Datenschema:

00:00 | 02:15 | hybrid | Вводное слово, обзор повестки миграции на шардированный кластер | Титульный слайд доклада, окно спикера
02:16 | 05:40 | visual | NONE | Переключение на схему архитектуры сервиса заказов в Miro
05:41 | 09:12 | speech | Пояснение причин отказа от распределенных транзакций в пользу Saga | Статичная схема Miro, курсор неподвижен
27:30 | 29:10 | visual | NONE | Открытие консоли, запуск сценария развертывания реплик БД
29:11 | 32:45 | hybrid | Разбор сценария split-brain при потере сетевой связности | Вывод логов etcd в терминале, подсветка таймаутов
54:10 | 57:25 | speech | Ответ на вопрос о допустимой задержке репликации данных | Финальный слайд с контактами спикера
57:26 | 60:00 | hybrid | Подведение итогов и демонстрация ссылки на репозиторий | Показ QR-кода на экране, завершение созвона

Schritt 4: Markup-Validierung und lokale Suche

Rohe LLM-Antworten dürfen ohne Verifizierung nicht als strukturierte Datensätze übernommen werden. Ein robuster Parser darf fehlerhafte Datensätze nicht stillschweigend verwerfen, sondern muss sie für eine manuelle Bearbeitung isolieren. Der Validator erzwingt: genau fünf Felder, gültige Ereignistypen (visual, speech, hybrid) und wohlgeformte MM:SS-Zeitstempel innerhalb der Videogrenzen.

import csv
import re
from typing import List, Dict, Tuple

TIME_PATTERN = re.compile(r"^(\d{2}):([0-5]\d)$")
ALLOWED_TYPES = {"visual", "speech", "hybrid"}

def time_to_seconds(t_str: str) -> int:
    match = TIME_PATTERN.match(t_str)
    if not match:
        raise ValueError(f"Некорректный формат времени: {t_str}")
    m, s = map(int, match.groups())
    return m * 60 + s

def parse_and_validate_tsv(
    raw_text: str, 
    max_duration_sec: int = 3600
) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]:
    valid_rows = []
    malformed_rows = []
    
    lines = [line.strip() for line in raw_text.strip().splitlines() if line.strip()]
    
    for idx, line in enumerate(lines, start=1):
        cols = [c.strip() for c in line.split("|")]
        
        if len(cols) != 5:
            malformed_rows.append({
                "line": idx,
                "content": line,
                "error": f"Ожидалось 5 полей, получено {len(cols)}"
            })
            continue
            
        start_str, end_str, event_type, claim, action = cols
        
        if event_type.lower() not in ALLOWED_TYPES:
            malformed_rows.append({
                "line": idx,
                "content": line,
                "error": f"Недопустимый тип события: {event_type}"
            })
            continue
            
        try:
            s_sec = time_to_seconds(start_str)
            e_sec = time_to_seconds(end_str)
        except ValueError as err:
            malformed_rows.append({
                "line": idx,
                "content": line,
                "error": str(err)
            })
            continue
            
        if s_sec > e_sec:
            malformed_rows.append({
                "line": idx,
                "content": line,
                "error": f"Время начала ({start_str}) больше времени окончания ({end_str})"
            })
            continue
            
        if e_sec > max_duration_sec:
            malformed_rows.append({
                "line": idx,
                "content": line,
                "error": f"Таймкод {end_str} выходит за хронометраж ({max_duration_sec} сек)"
            })
            continue
            
        valid_rows.append({
            "start": start_str,
            "end": end_str,
            "start_sec": s_sec,
            "end_sec": e_sec,
            "type": event_type.lower(),
            "claim": claim,
            "action": action
        })
        
    return valid_rows, malformed_rows

def search_index(
    rows: List[Dict[str, str]], 
    keyword: str = None, 
    event_type: str = None
) -> List[Dict[str, str]]:
    results = []
    for r in rows:
        if event_type and r["type"] != event_type.lower():
            continue
        if keyword:
            kw = keyword.lower()
            if kw not in r["claim"].lower() and kw not in r["action"].lower():
                continue
        results.append(r)
    return results

valid_index, errors = parse_and_validate_tsv(raw_index_output, max_duration_sec=3600)

if errors:
    print(f"Обнаружено некорректных строк: {len(errors)}. Требуется ручная правка:")
    for err in errors:
        print(f"Строка {err['line']}: {err['error']} -> {err['content']}")
else:
    print(f"Все строки валидны. Записей в индексе: {len(valid_index)}")

Schritt 5: Audit der Abdeckung und Erkennung von Lücken

Vor der Veröffentlichung des Index sollte die Timeline auf blinde Flecken auditiert werden:

  1. Benchmark-Zonen stichprobenartig prüfen:
    Prüfe manuell den Beginn des Videos (Einleitung und Titelfolien), die Mitte (wo Live-Demos oder Architekturdebatten typischerweise ihren Höhepunkt erreichen) und den Schluss (Fragerunde und Abschlussnotizen).
  2. Zeitstempelintervalle analysieren:
    Es gibt keinen universellen Schwellenwert für akzeptable Abstände zwischen Indexeinträgen; die Toleranz hängt vom jeweiligen Anwendungsfall ab. In einem dichten Screencast kann eine Lücke von 90 Sekunden einen fehlenden Konfigurationsschritt bedeuten. In einer Einführungsvorlesung kann eine einzelne, fünf Minuten dauernde These vollkommen plausibel sein. Wenn ein Intervall nicht zum Tempo des Vortrags passt, sollte es als verdächtig markiert werden.
  3. Stumme visuelle Ereignisse prüfen:
    Wenn ein Sprecher Aktionen auf dem Bildschirm ohne sprachlichen Kommentar gezeigt hat, hat der agentische Modus dieses Segment möglicherweise übergangen. Leite solche Abschnitte an eine gezielte statische Überprüfung weiter.

Schritt 6: Gezielte Inspektion verdächtiger Abschnitte via Static Clip

Die erneute Auswertung eines verdächtigen Segments erfordert keinen erneuten Durchlauf des gesamten 60-minütigen Videos. Das Schneiden von Clips beschränkt die Analyse im statischen Modus auf präzise Sekundengrenzen (start_offset und end_offset).

Einschränkung der Methode:
Der statische Modus mit 1 FPS bietet ein festes Abtastraster, das dabei hilft, Aktionen aufzudecken, die während des groben agentischen Durchlaufs übersehen wurden. Er garantiert jedoch keine absolute Vollständigkeit: Visuelle Änderungen, die schneller als eine Sekunde ablaufen, können immer noch zwischen die abgetasteten Frames fallen.

start_sec = 1200
end_sec = 1380

targeted_inspection = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "video",
            "uri": video_file.uri,
            "mime_type": video_file.mime_type,
            "processing": {
                "type": "static",
                "start_offset": start_sec,
                "end_offset": end_sec,
                "fps": 1.0
            }
        },
        {
            "type": "text",
            "text": (
                "Хронологически опиши изменения на экране. "
                "Зафиксируй команды в терминале, смену окон и системные сообщения."
            )
        }
    ]
)

print("Результат точечного досмотра отрезка:")
print(targeted_inspection.output_text)

Integriere die neu extrahierten Einträge entweder manuell oder über einen halbautomatischen Prüfschritt in den validierten Index.

Sobald alle Einträge in errors behoben und die Zeitstempel anhand der Originalaufnahme verifiziert sind, kann der finale Index exportiert werden. Der folgende Code-Ausschnitt bricht bewusst ab, wenn der Parser noch verbleibende Fehler meldet; stelle sicher, dass valid_index deine verifizierten Korrekturen enthält, bevor du ihn ausführst.

if errors:
    raise ValueError("Исправьте строки из errors и повторите проверку перед экспортом")

with open("video_index.csv", "w", newline="", encoding="utf-8") as output_file:
    writer = csv.DictWriter(
        output_file,
        fieldnames=["start", "end", "type", "claim", "action"],
        extrasaction="ignore",
    )
    writer.writeheader()
    writer.writerows(valid_index)

Die resultierende CSV-Datei ermöglicht es Benutzern, nach bestimmten Aussagen oder Bildschirmaktionen zu suchen und direkt zu den relevanten Abschnitten in der Originalaufnahme zu springen. Sie bleibt ein Entwurf, bis ein menschlicher Redakteur sowohl die Auswahl der Ereignisse als auch deren Ereignisgrenzen – und nicht lediglich Sampling-Grenzen – anhand der Quellaufnahme bestätigt hat.


Fehlerbehebung und Randfälle

  • FAILED-Status beim Upload über die Files API:
    Vermeide es, das Problem ohne API-Diagnose einzuordnen. Fehler können auf nicht unterstützte Containerformate, fehlerhafte Datei-Header oder vorübergehende Infrastrukturfehler zurückzuführen sein. Untersuche das Attribut file.error über das SDK, überprüfe die lokale Wiedergabe mit ffprobe, standardisiere Streams bei Bedarf mit ffmpeg (-c:v libx264 -c:a aac) und versuche es erneut.
  • 401 Unauthorized oder Netzwerkabbrüche:
    Ein 401-Fehler weist explizit auf einen Authentifizierungsfehler hin (ein ungültiger oder fehlender Schlüssel oder eine nicht konfigurierte Umgebungsvariable GEMINI_API_KEY), nicht auf eine abgelaufene Verarbeitungssitzung. Um Timeouts von Client-HTTP-Verbindungen bei längeren Aufrufen zu vermeiden, aktiviere Streaming über stream=True.
  • Zeitstempel überschreiten die Gesamtdauer:
    Diese Abweichung kann auftreten, wenn die Kontextkomplexität zunimmt. Steuere dem mit präzisen Prompt-Anweisungen und programmatischer Validierung (e_sec > max_duration_sec) in deinem Parser entgegen.
  • Struktureller TSV-Drift:
    Wenn die Formatierung fehlschlägt, leite fehlerhafte Zeilen an malformed_rows weiter und gib 1–2 Few-Shot-Referenzzeilen im System-Prompt vor.

Verifizierungs-Workflow vor der Veröffentlichung

  1. Asset-Bereitschaft überprüfen: Sicherstellen, dass die Datei in der Files API den Status ACTIVE erreicht hat.
  2. Ersten Entwurf generieren: Den Basis-Index mithilfe der agentic-Verarbeitung über die Interactions API erstellen.
  3. Programmatische Validierung ausführen: Sicherstellen, dass alle Zeilen fünf erforderliche Felder, gültige Typen und das Format MM:SS enthalten. Ungültige Zeilen zur Korrektur isolieren.
  4. Abdeckung auditieren: Benchmark-Zonen (Anfang, Mitte, Ende) untersuchen und die Zeitstempeldichte mit dem Tempo des Vortrags abgleichen.
  5. Gezielte Inspektion durchführen: Verdächtige Lücken oder stumme Bildschirmabschnitte mithilfe statischer Clips (start_offset/end_offset) erneut prüfen.
  6. Manuelle Stichproben-Kalibrierung vornehmen: Die tatsächliche Startzeit jedes Ereignisses anhand des relevanten Quell-Audios oder -Videos überprüfen, wie es der Anwendungsfall erfordert; dabei keine übereinstimmende visuelle Änderung verlangen, da auch reine Audio-Ereignisse auftreten können.

Zu Anfrageschemata, Verarbeitungsmodi und Sampling-Beschränkungen siehe die offizielle Gemini Video Understanding-Dokumentation.

Bereit, Ihren LLM-Workflow zu optimieren?

Verbinden Sie Modelle über eine API, verwalten Sie Schlüssel und behalten Sie KI-Kosten im Blick.

Kostenlos starten