Communitygithub.com

Jamkris/everything-gemini-code

Voir, comprendre et agir sur la vidéo et l'audio. Ingestion, indexation, recherche, édition et génération d'alertes en temps réel.

Qu'est-ce que everything-gemini-code ?

Cette compétence permet à un agent IA d'interagir avec la vidéo et l'audio à un niveau avancé : perception de bureau (capture d'écran, micro, audio système), ingestion de fichiers/URL/flux RTSP, indexation visuelle, sémantique et temporelle, recherche par mots-clés ou scènes, édition de timeline (sous-titres, overlays, doublage), transcodage, reframing pour réseaux sociaux, et génération de médias (image, audio, vidéo). Elle exploite l'API VideoDB pour toutes ces opérations, en évitant les outils locaux comme ffmpeg. La compétence inclut une gestion d'erreurs détaillée et des exemples de code Python prêts à l'emploi. Elle est conçue pour les agents utilisant Gemini, Claude Code, Cursor ou Codex, et fonctionne sur macOS (capture de bureau) et Linux (autre).

Compatible avec✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/Jamkris/everything-gemini-code/tree/HEAD/skills/videodb

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Compétence VideoDB

Perception + mémoire + actions pour la vidéo, les flux en direct et les sessions de bureau.

Quand l'utiliser

Perception de bureau

  • Démarrer/arrêter une session de bureau capturant l'écran, le micro et l'audio système
  • Diffuser un contexte en direct et stocker une mémoire de session épisodique
  • Exécuter des alertes/déclencheurs en temps réel sur ce qui est dit et ce qui se passe à l'écran
  • Produire des résumés de session, une timeline consultable et des liens de preuve jouables

Ingestion vidéo + flux

  • Ingérer un fichier ou une URL et retourner un lien de flux web jouable
  • Transcoder/normaliser : codec, débit, fps, résolution, rapport hauteur/largeur

Indexation + recherche (horodatages + preuves)

  • Construire des index visuels, vocaux et par mots-clés
  • Rechercher et retourner des moments exacts avec horodatages et preuves jouables
  • Créer automatiquement des clips à partir des résultats de recherche

Édition de timeline + génération

  • Sous-titres : générer, traduire, incruster
  • Superpositions : texte/image/marque, légendes animées
  • Audio : musique de fond, voix off, doublage
  • Composition programmatique et exportations via opérations de timeline

Flux en direct (RTSP) + surveillance

  • Connecter des flux RTSP/en direct
  • Exécuter une compréhension visuelle et vocale en temps réel et émettre des événements/alertes pour les flux de surveillance

Comment ça fonctionne

Entrées courantes

  • Chemin de fichier local, URL publique ou URL RTSP
  • Demande de capture de bureau : démarrer / arrêter / résumer la session
  • Opérations souhaitées : obtenir le contexte pour la compréhension, spécification de transcodage, spécification d'indexation, requête de recherche, plages de clips, modifications de timeline, règles d'alerte

Sorties courantes

  • URL du flux
  • Résultats de recherche avec horodatages et liens de preuve
  • Actifs générés : sous-titres, audio, images, clips
  • Charges utiles d'événements/alertes pour les flux en direct
  • Résumés de session de bureau et entrées mémoire

Exécution de code Python

Avant d'exécuter tout code VideoDB, placez-vous dans le répertoire du projet et chargez les variables d'environnement :

from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()

Ceci lit VIDEO_DB_API_KEY depuis :

  1. L'environnement (si déjà exportée)
  2. Le fichier .env du projet dans le répertoire courant

Si la clé est manquante, videodb.connect() lève automatiquement AuthenticationError.

N'écrivez PAS de fichier script quand une courte commande en ligne suffit.

Quand vous écrivez du Python en ligne (python -c "..."), utilisez toujours du code correctement formaté — utilisez des points-virgules pour séparer les instructions et gardez-le lisible. Pour tout ce qui dépasse ~3 instructions, utilisez plutôt un heredoc :

python << 'EOF'
from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()
coll = conn.get_collection()
print(f"Videos: {len(coll.get_videos())}")
EOF

Configuration

Quand l'utilisateur demande "configurer videodb" ou similaire :

1. Installer le SDK

pip install "videodb[capture]" python-dotenv

Si videodb[capture] échoue sur Linux, installez sans l'option capture :

pip install videodb python-dotenv

2. Configurer la clé API

L'utilisateur doit définir VIDEO_DB_API_KEY en utilisant l'une ou l'autre des méthodes :

  • Exporter dans le terminal (avant de lancer Gemini) : export VIDEO_DB_API_KEY=votre-clé
  • Fichier .env du projet : Enregistrer VIDEO_DB_API_KEY=votre-clé dans le fichier .env du projet

Obtenez une clé API gratuite sur console.videodb.io (50 téléchargements gratuits, pas de carte de crédit).

Ne lisez, n'écrivez ni ne gérez la clé API vous-même. Laissez toujours l'utilisateur la définir.

Référence rapide

Télécharger un média

# URL
video = coll.upload(url="https://example.com/video.mp4")

# YouTube
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")

# Fichier local
video = coll.upload(file_path="/path/to/video.mp4")

Transcription + sous-titre

# force=True évite l'erreur si la vidéo est déjà indexée
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()

Rechercher dans les vidéos

from videodb.exceptions import InvalidRequestError

video.index_spoken_words(force=True)

# search() lève InvalidRequestError quand aucun résultat n'est trouvé.
# Toujours l'envelopper dans try/except et traiter "Aucun résultat trouvé" comme vide.
try:
    results = video.search("product demo")
    shots = results.get_shots()
    stream_url = results.compile()
except InvalidRequestError as e:
    if "No results found" in str(e):
        shots = []
    else:
        raise

Recherche par scène

import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestError

# index_scenes() n'a pas de paramètre force — il lève une erreur si un index
# de scène existe déjà. Extrayez l'ID d'index existant à partir de l'erreur.
try:
    scene_index_id = video.index_scenes(
        extraction_type=SceneExtractionType.shot_based,
        prompt="Décrivez le contenu visuel de cette scène.",
    )
except Exception as e:
    match = re.search(r"id\s+([a-f0-9]+)", str(e))
    if match:
        scene_index_id = match.group(1)
    else:
        raise

# Utilisez score_threshold pour filtrer le bruit à faible pertinence (recommandé : 0,3+)
try:
    results = video.search(
        query="personne écrivant sur un tableau blanc",
        search_type=SearchType.semantic,
        index_type=IndexType.scene,
        scene_index_id=scene_index_id,
        score_threshold=0.3,
    )
    shots = results.get_shots()
    stream_url = results.compile()
except InvalidRequestError as e:
    if "No results found" in str(e):
        shots = []
    else:
        raise

Édition de timeline

Important : Validez toujours les horodatages avant de construire une timeline :

  • start doit être >= 0 (les valeurs négatives sont acceptées silencieusement mais produisent une sortie cassée)
  • start doit être < end
  • end doit être <= video.length
from videodb.timeline import Timeline
from videodb.asset import VideoAsset, TextAsset, TextStyle

timeline = Timeline(conn)
timeline.add_inline(VideoAsset(asset_id=video.id, start=10, end=30))
timeline.add_overlay(0, TextAsset(text="La Fin", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()

Transcodage vidéo (changement de résolution/qualité)

from videodb import TranscodeMode, VideoConfig, AudioConfig

# Changement de résolution, qualité ou rapport hauteur/largeur côté serveur
job_id = conn.transcode(
    source="https://example.com/video.mp4",
    callback_url="https://example.com/webhook",
    mode=TranscodeMode.economy,
    video_config=VideoConfig(resolution=720, quality=23, aspect_ratio="16:9"),
    audio_config=AudioConfig(mute=False),
)

Recadrage du rapport hauteur/largeur (pour les réseaux sociaux)

Attention : reframe() est une opération serveur lente. Pour les vidéos longues, cela peut prendre plusieurs minutes et peut expirer. Meilleures pratiques :

  • Limitez toujours à un court segment avec start/end quand c'est possible
  • Pour les vidéos en longueur totale, utilisez callback_url pour un traitement asynchrone
  • Rognez d'abord la vidéo sur une Timeline, puis recadrez le résultat plus court
from videodb import ReframeMode

# Privilégiez toujours le recadrage d'un court segment :
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)

# Recadrage asynchrone pour les vidéos en longueur totale (retourne None, résultat via webhook) :
video.reframe(target="vertical", callback_url="https://example.com/webhook")

# Préréglages : "vertical" (9:16), "square" (1:1), "landscape" (16:9)
reframed = video.reframe(start=0, end=60, target="square")

# Dimensions personnalisées
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})

Média génératif

image = coll.generate_image(
    prompt="un coucher de soleil sur des montagnes",
    aspect_ratio="16:9",
)

Gestion des erreurs

from videodb.exceptions import AuthenticationError, InvalidRequestError

try:
    conn = videodb.connect()
except AuthenticationError:
    print("Vérifiez votre VIDEO_DB_API_KEY")

try:
    video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
    print(f"Le téléchargement a échoué : {e}")

Pièges courants

ScénarioMessage d'erreurSolution
Indexer une vidéo déjà indexéeIndex de mots parlés pour la vidéo existe déjàUtilisez video.index_spoken_words(force=True) pour ignorer si déjà indexée
Index de scène existe déjàIndex de scène avec l'id XXXX existe déjàExtrayez le scene_index_id existant de l'erreur avec re.search(r"id\s+([a-f0-9]+)", str(e))
La recherche ne trouve aucune correspondanceInvalidRequestError: Aucun résultat trouvéAttrapez l'exception et traitez comme résultats vides (shots = [])
Recadrage expireBloque indéfiniment sur les vidéos longuesUtilisez start/end pour limiter le segment, ou passez callback_url pour asynchrone
Horodatages négatifs sur la TimelineProduit silencieusement un flux casséValidez toujours start >= 0 avant de créer VideoAsset
generate_video() / create_collection() échoueOpération non autorisée ou limite maximaleFonctionnalités limitées par forfait — informez l'utilisateur des limites du forfait

Exemples

Invites canoniques

  • "Démarre la capture de bureau et alerte quand un champ de mot de passe apparaît."
  • "Enregistre ma session et produit un résumé exploitable quand elle se termine."
  • "Ingère ce fichier et retourne un lien de flux jouable."
  • "Indexe ce dossier et trouve chaque scène avec des personnes, retourne les horodatages."
  • "Génère des sous-titres, incruste-les et ajoute une musique de fond légère."
  • "Connecte cette URL RTSP et alerte quand une personne entre dans la zone."

Enregistrement d'écran (capture de bureau)

Utilisez ws_listener.py pour capturer les événements WebSocket pendant les sessions d'enregistrement. La capture de bureau prend en charge macOS uniquement.

Démarrage rapide

  1. Choisissez le répertoire d'état : STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}"
  2. Démarrez l'écouteur : VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" &
  3. Obtenez l'ID WebSocket : cat "$STATE_DIR/videodb_ws_id"
  4. Exécutez le code de capture (voir reference/capture.md pour le workflow complet)
  5. Événements écrits dans : $STATE_DIR/videodb_events.jsonl

Utilisez --clear chaque fois que vous démarrez une nouvelle session de capture pour que les événements de transcription et visuels obsolètes ne s'infiltrent pas dans la nouvelle session.

Interroger les événements

import json
import os
import time
from pathlib import Path

events_dir = Path(os.environ.get("VIDEODB_EVENTS_DIR", Path.home() / ".local" / "state" / "videodb"))
events_file = events_dir / "videodb_events.jsonl"
events = []

if events_file.exists():
    with events_file.open(encoding="utf-8") as handle:
        for line in handle:
            try:
                events.append(json.loads(line))
            except json.JSONDecodeError:
                continue

transcripts = [e["data"]["text"] for e in events if e.get("channel") == "transcript"]
cutoff = time.time() - 300
recent_visual = [
    e for e in events
    if e.get("channel") == "visual_index" and e["unix_ts"] > cutoff
]

Documentation supplémentaire

La documentation de référence se trouve dans le répertoire reference/ adjacent à ce fichier SKILL.md. Utilisez l'outil Glob pour le localiser si nécessaire.

N'utilisez pas ffmpeg, moviepy, ou d'outils d'encodage locaux quand VideoDB prend en charge l'opération. Tout ce qui suit est géré côté serveur par VideoDB : rognage, combinaison de clips, superposition audio ou musicale, ajout de sous-titres, superpositions texte/image, transcodage, changements de résolution, conversion de rapport hauteur/largeur, redimensionnement pour les exigences de plateforme, transcription et génération de médias. Ne recourez aux outils locaux que pour les opérations listées sous Limitations dans reference/editor.md (transitions, changements de vitesse, recadrage/zoom, étalonnage des couleurs, mixage de volume).

Quand utiliser quoi

ProblèmeSolution VideoDB
La plateforme rejette le rapport hauteur/largeur ou la résolution de la vidéovideo.reframe() ou conn.transcode() avec VideoConfig
Besoin de redimensionner la vidéo pour Twitter/Instagram/TikTokvideo.reframe(target="vertical") ou target="square"
Besoin de changer la résolution (ex. 1080p → 720p)conn.transcode() avec VideoConfig(resolution=720)
Besoin de superposer de l'audio/de la musique sur une vidéoAudioAsset sur une Timeline
Besoin d'ajouter des sous-titresvideo.add_subtitle() ou CaptionAsset
Besoin de combiner/rogner des clipsVideoAsset sur une Timeline
Besoin de générer voix off, musique ou effets sonorescoll.generate_voice(), generate_music(), generate_sound_effect()

Provenance

Les documents de référence pour cette compétence sont stockés localement sous skills/videodb/reference/. Utilisez les copies locales ci-dessus plutôt que de suivre des liens vers des dépôts externes à l'exécution.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills associés