Transcription YouTube
Télécharge les transcriptions (sous-titres/légendes) à partir de vidéos YouTube. Fonctionne avec les transcriptions créées manuellement et celles générées automatiquement. Aucune clé API ni navigateur requis — utilise directement l'API InnerTube de YouTube et bascule automatiquement sur yt-dlp lorsque YouTube bloque le chemin API direct.
Récupère les métadonnées de la vidéo et l'image de couverture lors de la première exécution, met en cache les données brutes pour une reformatation rapide.
Répertoire des scripts
Scripts dans le sous-répertoire scripts/. {baseDir} = chemin du répertoire de ce SKILL.md. Résoudre l'exécution ${BUN_X} : si bun est installé → bun ; si npx est disponible → npx -y bun ; sinon suggérer d'installer bun. Remplacer {baseDir} et ${BUN_X} par les valeurs réelles.
| Script | Objectif |
|---|---|
scripts/main.ts | CLI de téléchargement de transcription |
Utilisation
# Par défaut : markdown avec horodatages (anglais)
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>
# Spécifier les langues (ordre de priorité)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja
# Sans horodatages
${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps
# Avec segmentation par chapitres
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters
# Avec identification des locuteurs (nécessite un post-traitement IA)
${BUN_X} {baseDir}/scripts/main.ts <url> --speakers
# Fichier de sous-titres SRT
${BUN_X} {baseDir}/scripts/main.ts <url> --format srt
# Traduire la transcription
${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans
# Lister les transcriptions disponibles
${BUN_X} {baseDir}/scripts/main.ts <url> --list
# Forcer une nouvelle récupération (ignorer le cache)
${BUN_X} {baseDir}/scripts/main.ts <url> --refresh
Options
| Option | Description | Par défaut |
|---|---|---|
<url-or-id> | URL YouTube ou ID de la vidéo (plusieurs autorisés) | Requis |
--languages <codes> | Codes de langue, séparés par des virgules, dans l'ordre de priorité | en |
--format <fmt> | Format de sortie : text, srt | text |
--translate <code> | Traduire dans le code de langue spécifié | |
--list | Lister les transcriptions disponibles au lieu de les récupérer | |
--timestamps | Inclure les horodatages [HH:MM:SS → HH:MM:SS] par paragraphe | activé |
--no-timestamps | Désactiver les horodatages | |
--chapters | Segmentation par chapitres à partir de la description de la vidéo | |
--speakers | Transcription brute avec métadonnées pour l'identification des locuteurs | |
--exclude-generated | Ignorer les transcriptions générées automatiquement | |
--exclude-manually-created | Ignorer les transcriptions créées manuellement | |
--refresh | Forcer une nouvelle récupération, ignorer les données en cache | |
-o, --output <path> | Enregistrer dans un chemin de fichier spécifique | généré automatiquement |
--output-dir <dir> | Répertoire de sortie de base | youtube-transcript |
Variables d'environnement optionnelles
| Variable | Description |
|---|---|
YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER | Passé à yt-dlp --cookies-from-browser lors du repli, par ex. chrome, safari, firefox, ou chrome:Profile 1 |
Formats d'entrée
Accepte l'un des formats suivants en entrée vidéo :
- URL complète :
https://www.youtube.com/watch?v=dQw4w9WgXcQ - URL courte :
https://youtu.be/dQw4w9WgXcQ - URL d'intégration :
https://www.youtube.com/embed/dQw4w9WgXcQ - URL Shorts :
https://www.youtube.com/shorts/dQw4w9WgXcQ - ID de la vidéo :
dQw4w9WgXcQ
Formats de sortie
| Format | Extension | Description |
|---|---|---|
text | .md | Markdown avec frontmatter (incl. description), titre, résumé, table des matières/image de couverture/horodatages/chapitres/locuteurs optionnels |
srt | .srt | Format de sous-titres SubRip pour lecteurs vidéo |
Répertoire de sortie
youtube-transcript/
├── .index.json # Correspondance ID vidéo → chemin du répertoire (pour la recherche en cache)
└── {channel-slug}/{title-full-slug}/
├── meta.json # Métadonnées de la vidéo (titre, chaîne, description, durée, chapitres, etc.)
├── transcript-raw.json # Fragments de transcription bruts de l'API YouTube (en cache)
├── transcript-sentences.json # Transcription segmentée par phrases (découpée par ponctuation, fusionnée entre les fragments)
├── imgs/
│ └── cover.jpg # Vignette de la vidéo
├── transcript.md # Transcription Markdown (générée à partir des phrases)
└── transcript.srt # Sous-titres SRT (générés à partir des fragments bruts, si --format srt)
{channel-slug}: Nom de la chaîne en kebab-case{title-full-slug}: Titre complet de la vidéo en kebab-case
Le mode --list génère une sortie uniquement sur stdout (aucun fichier enregistré).
Mise en cache
Lors de la première récupération, le script enregistre :
meta.json— métadonnées de la vidéo, chapitres, chemin de l'image de couverture, informations de languetranscript-raw.json— fragments de transcription bruts de l'API YouTube ({ text, start, duration }[])transcript-sentences.json— transcription segmentée en phrases ({ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]), découpée par la ponctuation de fin de phrase (.?!…。?!etc.), horodatages alloués proportionnellement à la longueur des caractères, fusion de texte sensible aux caractères CJKimgs/cover.jpg— vignette de la vidéo
Les exécutions suivantes pour la même vidéo utilisent les données en cache (aucun appel réseau). Utilisez --refresh pour forcer une nouvelle récupération. Si une langue différente est demandée, le cache est automatiquement actualisé.
Lorsque YouTube renvoie des réponses anti-bot / bloquées sur le chemin InnerTube direct, le script réessaie avec des identités de client alternatives, puis bascule sur yt-dlp si disponible. Si le repli est nécessaire mais que yt-dlp n'est pas disponible, l'agent doit décider comment rendre yt-dlp disponible et continuer plutôt que de repousser la décision d'installation à l'utilisateur.
La sortie SRT (--format srt) est générée à partir de transcript-raw.json. La sortie texte/markdown utilise transcript-sentences.json pour des limites de phrases naturelles.
Flux de travail
Lorsque l'utilisateur fournit une URL YouTube et souhaite la transcription :
- Exécutez d'abord avec
--listsi l'utilisateur n'a pas spécifié de langue, pour afficher les options disponibles - Toujours mettre l'URL entre guillemets simples lors de l'exécution du script — zsh traite
?comme un caractère générique, donc une URL YouTube non entre guillemets provoque une erreur "aucune correspondance trouvée" : utilisez'https://www.youtube.com/watch?v=ID' - Par défaut : exécutez avec
--chapters --speakerspour la sortie la plus riche (chapitres + identification des locuteurs) - Le script enregistre automatiquement les données en cache + le fichier de sortie et affiche le chemin du fichier
- Pour le mode
--speakers: après que le script a enregistré le fichier brut, suivez le flux de travail d'identification des locuteurs ci-dessous pour post-traiter avec des étiquettes de locuteurs
Lorsque l'utilisateur ne souhaite qu'une image de couverture ou des métadonnées, l'exécution du script avec n'importe quelle option mettra également en cache meta.json et imgs/cover.jpg.
Lors du reformatage de la même vidéo (par exemple, d'abord en texte puis en SRT), les données en cache sont réutilisées — aucune nouvelle récupération nécessaire.
Flux de travail des chapitres et des locuteurs
Chapitres (--chapters)
Le script analyse les horodatages des chapitres à partir de la description de la vidéo (par ex., 0:00 Introduction), segmente la transcription selon les limites des chapitres, regroupe les fragments en paragraphes lisibles et enregistre en .md avec une table des matières. Aucun traitement supplémentaire nécessaire.
S'il n'y a pas d'horodatages de chapitres dans la description, la transcription est sortie sous forme de paragraphes groupés sans titres de chapitres.
Identification des locuteurs (--speakers)
L'identification des locuteurs nécessite un traitement par IA. Le script génère un fichier .md brut contenant :
- Frontmatter YAML avec les métadonnées de la vidéo (titre, chaîne, date, couverture, description, langue)
- Description de la vidéo (pour l'extraction des noms des locuteurs)
- Liste des chapitres de la description (si disponible)
- Transcription brute au format SRT (horodatages de début/fin pré-calculés, efficace en tokens)
Après que le script a enregistré le fichier brut, lancez un sous-agent (utilisez un modèle moins cher comme Sonnet pour l'efficacité des coûts) pour traiter l'identification des locuteurs :
- Lire le fichier
.mdenregistré - Lire le modèle de consigne dans
{baseDir}/prompts/speaker-transcript.md - Traiter la transcription brute en suivant la consigne :
- Identifier les locuteurs en utilisant les métadonnées de la vidéo (titre → invité, chaîne → hôte, description → noms)
- Détecter les tours de parole à partir du flux de conversation, des schémas question-réponse et des indices contextuels
- Segmenter en chapitres (utiliser les chapitres de la description si disponibles, sinon créer à partir des changements de sujet)
- Formater avec les étiquettes
**Nom du locuteur :**, le regroupement en paragraphes (2-4 phrases) et les horodatages[HH:MM:SS → HH:MM:SS]
- Écraser le fichier
.mdavec la transcription traitée (conserver le frontmatter YAML)
Lorsque --speakers est utilisé, --chapters est implicite — la sortie traitée inclut toujours la segmentation en chapitres.
Cas d'erreur
| Erreur | Signification |
|---|---|
| Transcriptions désactivées | La vidéo n'a aucun sous-titre |
| Aucune transcription trouvée | La langue demandée n'est pas disponible |
| Vidéo indisponible | Vidéo supprimée, privée ou verrouillée par région |
| IP bloquée | Trop de requêtes, réessayez plus tard |
| Restriction d'âge | La vidéo nécessite une connexion pour la vérification de l'âge |
| bot détecté | Le script réessaie avec des clients alternatifs puis yt-dlp ; si l'outillage de repli est manquant, l'agent doit résoudre cela lui-même, sinon si cela échoue toujours essayez YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari (ou votre navigateur) |


