/watch
Vous n'avez pas d'entrée vidéo ; cette compétence vous en fournit une. Un script Python récupère d'abord les sous-titres, télécharge éventuellement la vidéo, extrait des images au format JPEG (adaptées aux scènes, ou images clés rapides avec le niveau efficient), obtient une transcription horodatée (sous-titres natifs d'abord, puis API Whisper en fallback), et affiche les chemins des images. Vous lisez ensuite chaque chemin d'image pour voir les images et les combinez avec la transcription pour répondre à l'utilisateur.
Résoudre SKILL_DIR (à faire avant toute commande)
Chaque commande python3 ... ci-dessous exécute un script inclus dans SKILL_DIR/scripts/. Définissez SKILL_DIR comme le chemin absolu du répertoire contenant CETTE SKILL.md que vous venez de Lire — votre environnement vous a communiqué ce chemin dans le résultat de la Lecture. Les scripts sont toujours un frère direct de ce fichier (SKILL_DIR/scripts/watch.py), dans toutes les configurations d'installation :
Read ~/.claude/plugins/cache/claude-video/watch/<ver>/skills/watch/SKILL.md → SKILL_DIR=…/skills/watch
Read ~/.codex/skills/watch/SKILL.md → SKILL_DIR=~/.codex/skills/watch
Read ~/.agents/skills/watch/SKILL.md → SKILL_DIR=~/.agents/skills/watch
Remplacez ce chemin littéral pour ${SKILL_DIR} dans chaque commande. Cela fonctionne sur tous les environnements (Claude Code, Codex, Cursor, Gemini CLI, …) sans dépendre d'aucune variable d'environnement spécifique à l'environnement. Vérifiez une fois au début d'une exécution :
SKILL_DIR="<chemin absolu du répertoire contenant la SKILL.md que vous venez de Lire>"
if [ ! -f "$SKILL_DIR/scripts/watch.py" ]; then
echo "ERREUR : scripts/watch.py introuvable sous SKILL_DIR=$SKILL_DIR" >&2
echo "Vérifiez le répertoire de la SKILL.md que vous avez lue et remplacez-le par SKILL_DIR." >&2
exit 1
fi
Étape 0 — Vérification préalable (s'exécute à chaque appel /watch, silencieuse en cas de succès)
Interpréteur Python : chaque commande python3 ... dans cette compétence est destinée à macOS/Linux. Sous Windows, remplacez par python — la commande python3 sur Windows est l'interface du Microsoft Store et n'exécutera pas le script.
Lors du premier appel /watch dans une session, utilisez la vérification structurée pour détecter une configuration initiale :
python3 "${SKILL_DIR}/scripts/setup.py" --json
Bifurquez selon deux champs :
can_proceed: trueetfirst_run: false→ la configuration est déjà effectuée (l'utilisateur peut avoir délibérément ignoré une clé Whisper — c'est autorisé). Passez à l'Étape 1 sans commentaire.first_run: true→ première configuration authentique. Faites ceci dans l'ordre :- Si
missing_binariesn'est pas vide, exécutez d'abord le programme d'installation (il s'installe automatiquement sur macOS/affiche des commandes ailleurs — voir ci-dessous) et confirmez que les binaires sont en place. Ne sautez pas cette étape et n'allez pas directement aux préférences. - Exécutez le programme d'installation une fois de plus si nécessaire pour qu'il crée
~/.config/watch/.env(il n'écrit le modèle que si le fichier est absent, donc laissez-le créer le fichier avant d'écrire des valeurs dedans). - Encouragez l'utilisateur à fournir une clé API Whisper et posez les questions sur les préférences de visionnage ci-dessous, puis écrivez les valeurs sélectionnées dans
~/.config/watch/.envet définissezSETUP_COMPLETE=true.
- Si
can_proceed: falseetfirst_run: false→ la configuration a été terminée auparavant mais l'environnement a régressé (par exemple,missing_binariesaprès un changement de système d'exploitation). Exécutez le programme d'installation pour corriger, puis continuez. Ne reposez pas les questions de préférences.
Une clé Whisper manquante est encouragée à être corrigée, mais pas obligatoire : lors d'une première exécution authentique, status affichera needs_key même si les binaires sont présents — c'est votre signal pour encourager une clé, pas un blocage.
Lors des appels /watch suivants dans la même session, utilisez la vérification silencieuse :
python3 "${SKILL_DIR}/scripts/setup.py" --check
Il s'agit d'une consultation de moins de 100 ms. Le code de sortie 0 signifie que /watch peut s'exécuter — cela inclut un utilisateur qui a terminé la configuration sans clé Whisper (l'absence de clé est autorisée). En cas de sortie 0, le script n'émet rien — passez à l'Étape 1 sans commentaire. N'annoncez PAS « la configuration est terminée » à l'utilisateur — ils n'ont pas besoin d'un message d'état à chaque tour. La seule sortie acceptable visible par l'utilisateur à l'Étape 0 est lorsqu'une correction est nécessaire.
En cas de sortie non nulle, suivez le tableau :
| Sortie | Signification | Action |
|---|---|---|
2 | Binaires manquants (ffmpeg / ffprobe / yt-dlp) | Exécutez le programme d'installation |
3 | Première exécution authentique sans clé API Whisper | Exécutez le programme d'installation pour créer .env, puis encouragez une clé (l'utilisateur peut refuser — continuez avec --no-whisper) |
4 | Les deux manquants | Exécutez le programme d'installation, puis encouragez une clé |
La sortie 3 se déclenche uniquement avant que l'utilisateur n'ait terminé la configuration. Une fois SETUP_COMPLETE=true écrit, une installation sans clé renvoie la sortie 0 et n'est plus jamais relancée.
Le programme d'installation est idempotent — sans danger à réexécuter :
python3 "${SKILL_DIR}/scripts/setup.py"
Sur macOS avec Homebrew, il installe automatiquement ffmpeg et yt-dlp. Sur Linux/Windows, il affiche les commandes d'installation exactes pour que l'utilisateur les exécute. Il crée ~/.config/watch/.env avec des espaces réservés commentés et des paramètres de visionnage par défaut avec des permissions 0600.
Si une clé API est toujours manquante après l'installation : utilisez AskUserQuestion pour demander à l'utilisateur s'il a une clé API Groq (préférée — moins chère, plus rapide) ou une clé OpenAI. Écrivez-la ensuite dans ~/.config/watch/.env — définissez la ligne correspondante GROQ_API_KEY=... ou OPENAI_API_KEY=.... S'il ne veut pas configurer Whisper, continuez avec --no-whisper et informez-le que les vidéos sans sous-titres natifs reviendront avec uniquement des images.
Préférence de visionnage lors de la première exécution : après que le programme d'installation a créé ~/.config/watch/.env, utilisez AskUserQuestion pour poser une question :
- Niveau de détail par défaut (un seul réglage). Présentez ces options
AskUserQuestiondans cet ordre exact — du plus léger au plus lourd — et conservez(recommandé)surbalancedmême s'il n'est pas en premier (ne réorganisez pas pour mettre l'option recommandée en premier) :transcript— pas d'images du tout, uniquement la transcription (ignore le téléchargement de la vidéo lorsque les sous-titres existent).efficient— passage rapide des images clés (limite de 50).balanced(recommandé) — images adaptées aux scènes (limite de 100, par défaut).token-burner— adapté aux scènes, sans limite (fidélité maximale ; coût en tokens élevé).
Écrivez la réponse directement dans ~/.config/watch/.env en définissant la clé nue sur sa propre ligne — aucun commentaire en ligne en fin de ligne (un # remarque après la valeur peut casser l'analyse) :
WATCH_DETAIL=balanced
Utilisez la valeur sélectionnée par l'utilisateur. S'il ignore la question, conservez la valeur par défaut recommandée. Une fois les dépendances, le choix de la clé API et cette préférence traités, écrivez ou mettez à jour SETUP_COMPLETE=true dans le même fichier. Ne reposez pas cette question de préférence lorsque SETUP_COMPLETE=true.
Mode structuré (optionnel) : python3 "${SKILL_DIR}/scripts/setup.py" --json émet {status, can_proceed, first_run, setup_complete, missing_binaries, whisper_backend, has_api_key, config_file, watch_detail, platform} où status est l'un des ready | needs_install | needs_key | needs_install_and_key. status décrit l'état idéal (une clé est encouragée, donc une première exécution sans clé lit needs_key) ; can_proceed est la porte opérationnelle (binaires présents ET une clé définie OU la configuration déjà terminée). Bifurquez sur can_proceed/first_run pour décider d'exécuter ; utilisez status pour décider quoi encourager.
Au sein d'une même session, vous pouvez sauter l'Étape 0 lors des appels /watch suivants — une fois que --check a renvoyé 0, rien dans l'environnement ne change entre les tours.
Quand l'utiliser
- L'utilisateur colle une URL vidéo (YouTube, Vimeo, X, TikTok, clip Twitch, la plupart des sites supportés par yt-dlp) et pose une question à ce sujet.
- L'utilisateur pointe vers un fichier vidéo local (
.mp4,.mov,.mkv,.webm, etc.) et pose une question à ce sujet. - L'utilisateur tape
/watch <url-ou-chemin> [question].
Limites recommandées
- Meilleure précision : vidéos de moins de 10 minutes. La couverture d'images s'adapte inversement à la durée.
- Limite de fréquence universelle : 2 ips. Le script n'échantillonne jamais plus vite que 2 ips, même si un budget ou
--fpsimpliquerait plus. - Le plafond d'images est défini par le mode de détail (
WATCH_DETAILdans~/.config/watch/.env, ou--detail), pas par un plafond global unique :transcript→ aucune imageefficient→ jusqu'à 50 (images clés)balanced(par défaut) → jusqu'à 100 (adapté aux scènes)token-burner→ sans limite (adapté aux scènes ; un avertissement léger s'affiche au-delà de 250 images)--max-frames Nremplace tout plafond que le mode utiliserait autrement.
- Budget d'images pour une vidéo complète selon la durée. Le coût en tokens augmente avec le nombre d'images, donc le script cible un budget par durée. Ce budget définit les ips et le repli d'échantillonnage uniforme ; la sélection adaptée aux scènes peut remplir jusqu'au plafond de détail ci-dessus, selon la valeur la plus basse :
- ≤30s → ~12-30 images
- 30s-1min → ~40 images
- 1-3min → ~60 images
- 3-10min → ~80 images
-
10min → jusqu'au plafond de détail, espacés (avertissement affiché)
- Si l'utilisateur vous donne une longue vidéo, envisagez de demander s'il souhaite une section spécifique avant de brûler des tokens sur un balayage clairsemé.
Comment l'invoquer
Étape 1 — analyser l'entrée utilisateur. Séparez la source vidéo (URL ou chemin) de toute question posée par l'utilisateur. Exemple : /watch https://youtu.be/abc dans quelle langue est-ce ? → source = https://youtu.be/abc, question = dans quelle langue est-ce ?.
Étape 2 — exécuter le script de visionnage. Passez la source textuellement. Ne l'échappez pas vous-même au-delà des guillemets normaux :
python3 "${SKILL_DIR}/scripts/watch.py" "<source>"
Indicateurs optionnels :
--detail transcript|efficient|balanced|token-burner— réglage fidélité/vitesse.transcript= aucune image (transcription uniquement, ignore le téléchargement vidéo lorsque les sous-titres existent) ;efficient= images clés rapides (limite 50) ;balanced= images adaptées aux scènes (limite 100) ;token-burner= adapté aux scènes, sans limite.--start T/--end T— concentrez-vous sur une section. AccepteSS,MM:SS, ouHH:MM:SS. Lorsque l'un des deux est défini, les ips s'adaptent automatiquement plus denses (voir « Se concentrer sur une section » ci-dessous).--timestamps T1,T2,…— capturez une image à chacun de ces horodatages absolus (SS,MM:SS, ouHH:MM:SS). Utilisez ceci après avoir lu la transcription pour capturer les moments déictiques que le présentateur signale (« regardez ici », « comme vous pouvez le voir », « remarquez ceci ») que la sélection visuelle seule pourrait manquer. Voir « Images déclenchées par la transcription » ci-dessous.--max-frames N— remplacez le plafond prédéfini pour un budget de tokens plus serré (par exemple--max-frames 40)--resolution W— modifiez la largeur d'image en pixels (par défaut 512 ; passez à 1024 uniquement si l'utilisateur a besoin de lire du texte à l'écran)--fps F— remplacez les ips automatiques (limité à 2 ips max)--out-dir DIR— conservez les fichiers de travail à un endroit spécifique (par défaut : un répertoire temporaire généré automatiquement)--whisper groq|openai— forcez un backend Whisper spécifique (par défaut : préférez Groq si les deux clés existent)--no-whisper— désactivez complètement le fallback Whisper (uniquement des images si pas de sous-titres)--no-dedup— conservez les images quasi identiques. Par défaut, un passage de différence d'images supprime les images visuellement presque identiques à la précédente conservée (diapositives fixes, enregistrements d'écran statiques, vidéo en pause) afin que le budget d'images aille au contenu distinct ; la ligne Images du rapport indique combien ont été supprimées. Passez-le uniquement si l'utilisateur a besoin de chaque image échantillonnée (par exemple pour juger du mouvement image par image subtil).
Se concentrer sur une section (fréquence d'images plus élevée)
Lorsque l'utilisateur demande un moment spécifique — « que se passe-t-il à la 2e minute ? », « zoome sur 0:45 à 1:00 », « les 10 premières secondes » — passez --start et/ou --end. Le script passe en budgets en mode focalisé, plus denses que les budgets vidéo complets (toujours limité à 2 ips, et toujours borné par le plafond du mode de détail — les décomptes ci-dessous supposent le plafond balanced par défaut de 100 ; efficient plafonne à 50) :
- ≤5s → 2 ips (jusqu'à 10 images)
- 5-15s → 2 ips (jusqu'à 30 images)
- 15-30s → ~2 ips (jusqu'à 60 images)
- 30-60s → ~1.3 ips (jusqu'à 80 images)
- 60-180s → ~0.6 ips (100 images, plafonné)
Le mode focalisé est le bon choix pour :
- Tout moment/plage nommé explicitement par l'utilisateur (« vers 2:30 », « l'intro », « les 30 dernières secondes »).
- Toute vidéo de plus de ~10 minutes où la question de l'utilisateur concerne une partie spécifique — exécuter en mode focalisé sur la section pertinente est bien plus utile qu'un balayage clairsemé de l'ensemble.
- Les réexécutions après un balayage complet qui n'a pas fourni suffisamment de détails dans une région.
La transcription est automatiquement filtrée sur la même plage. Les horodatages des images sont absolus (chronologie réelle de la vidéo, pas décalée depuis le début).
Exemples :
# Dernières 10 secondes d'une vidéo d'une minute
python3 "${SKILL_DIR}/scripts/watch.py" video.mp4 --start 50 --end 60
# Zoom sur 2:15 → 2:45 à 2 ips (60 images)
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 2:15 --end 2:45 --fps 2
# De 1h12m à la fin de la vidéo
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 1:12:00
Étape 3 — Lire chaque chemin d'image listé par le script. L'outil Read rend les JPEG directement sous forme d'images pour vous. Lisez toutes les images dans un seul message (appels d'outils parallèles) pour les voir ensemble. Les images sont dans l'ordre chronologique avec un horodatage t=MM:SS pour que vous puissiez les aligner sur la transcription.
Étape 4 — répondre à l'utilisateur. Vous avez maintenant deux flux de preuves :
- Images — ce qui est à l'écran à chaque horodatage
- Transcription — ce qui est dit à chaque horodatage. L'en-tête du rapport indique la source (
captions= yt-dlp a récupéré les sous-titres natifs ;whisper (groq)ouwhisper (openai)= transcrit par API).
Si l'utilisateur a posé une question spécifique, répondez-y directement en citant les horodatages. S'il n'a rien demandé, résumez ce qui se passe dans la vidéo — structure, moments clés, visuels notables, contenu parlé.
Cela vaut également pour le détail transcript : même sans images, produisez un résumé comme les autres modes — ne collez pas la transcription complète dans le chat. Synthétisez la structure, les moments clés et le contenu parlé avec des horodatages ; citez uniquement les lignes importantes. Proposez la transcription brute uniquement si l'utilisateur la demande explicitement.
Étape 5 — nettoyer. Le script affiche un répertoire de travail à la fin. Si l'utilisateur ne va pas poser de questions de suivi sur cette vidéo, supprimez-le avec rm -rf <répertoire>. S'il le pourrait, laissez-le en place.
Détail et images
Le comportement par défaut provient de ~/.config/watch/.env :
WATCH_DETAIL=transcript|efficient|balanced|token-burner(par défaut :balanced)
À l'exécution, le script vérifie d'abord --detail, puis WATCH_DETAIL dans le fichier de configuration. Si aucun des deux n'est défini, il utilise balanced.
Images déclenchées par la transcription
Utilisez --timestamps pour capturer des moments spécifiques que vous identifiez dans la transcription mais que la sélection adaptée aux scènes pourrait manquer. Le script traite les horodatages fournis comme des points de capture absolus, en respectant la résolution et les limites de fréquence d'images. Utile pour les doigtés, les graphiques flashés rapidement, ou les références visuelles brèves.
Repli : API Whisper (Groq ou OpenAI)
Si la vidéo n'a pas de sous-titres natifs (ou si yt-dlp n'a pas pu les extraire), le script tente de transcrire l'audio via l'API Whisper. Le backend par défaut est Groq (plus rapide, moins cher). Si vous définissez OPENAI_API_KEY au lieu de GROQ_API_KEY, il utilise OpenAI. Vous pouvez forcer un backend spécifique avec --whisper groq ou --whisper openai. Si aucune clé API n'est configurée et que la vidéo n'a pas de sous-titres, le rapport n'inclut pas de transcription.
Exemples détaillés
# Utilisation de base avec une URL
python3 "${SKILL_DIR}/scripts/watch.py" "https://youtu.be/abc123"
# Avec un chemin de fichier local
python3 "${SKILL_DIR}/scripts/watch.py" "/chemin/vers/video.mp4" --detail efficient
# Section spécifique avec haute fréquence d'images
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --start 1:00 --end 2:30 --fps 2
# Forcer le backend Whisper
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --whisper openai
# Désactiver complètement Whisper
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --no-whisper
# Conserver les images quasi identiques
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --no-dedup
# Résolution plus élevée pour le texte à l'écran
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --resolution 1024
# Budget serré pour économiser des tokens
python3 "${SKILL_DIR}/scripts/watch.py" "$URL" --max-frames 40