Communitygithub.com

renky1025/agent-skills

Pipeline de doublage vidéo local : extraction 16 kHz → ASR → traduction IA → TTS segmenté → multiplexage → incrustation de sous-titres. Synchronisation verrouillée aux timestamps.

Qu'est-ce que agent-skills ?

Cette compétence permet de localiser entièrement une vidéo en une autre langue : elle reconnaît la parole originale, la traduit via IA, génère un doublage en TTS (Text-to-Speech) pour la langue cible, puis synthétise la piste audio tout en conservant les timestamps d'origine, et incruste les sous-titres traduits directement dans l'image. Le résultat est un fichier vidéo unique prêt à être publié, où le doublage et les sous-titres sont naturellement synchronisés, sans besoin de ré-étalonnage. Supportée sur des plateformes comme Claude Code, Cursor ou Codex, elle s'exécute via un script orchestrateur (`dub.py`) ou manuellement étape par étape. Le workflow inclut l'extraction audio (16 kHz mono), la transcription ASR (Whisper ou Qwen3-ASR), la traduction phrase par phrase, la génération TTS segmentée avec contrôle du timbre et du débit, le mixage audio, et l'incrustation des sous-titres. Des scripts auxiliaires gèrent les sous-tâches (segmentation TTS, incrustation de sous-titres, ASR alternatif). Les décisions clés (moteur ASR, langue cible, incrustation ou non) sont contrôlées par des paramètres en ligne de commande. La compétence vérifie rigoureusement que le nombre de lignes de traduction correspond au nombre de segments SRT, et utilise un mécanisme de changement de vitesse local (atempo) pour éviter la désynchronisation. En cas d'échec, des messages d'erreur clairs et des références de dépannage sont fournis.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/renky1025/agent-skills/tree/main/video-dubbing

Demander à votre IA préférée

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

Documentation

video-dubbing : Doublage vidéo, traduction et synchronisation des sous-titres

Objectif

Localiser entièrement une vidéo dans une autre langue : reconnaître la parole originale, la traduire, générer un doublage dans la langue cible via TTS, tout en conservant les timestamps d'origine, puis mixer la piste audio et incruster les sous-titres traduits directement dans l'image. Le résultat est un fichier vidéo unique prêt à être publié, où le doublage et les sous-titres sont naturellement synchronisés, sans besoin de ré-étalonnage.

Quand l'utiliser

  • L'utilisateur demande de traduire une vidéo dans une autre langue avec doublage (pas seulement des sous-titres).
  • Besoin d'ajouter un doublage dans la langue cible + des sous-titres synchronisés (bilingues ou traduction seule).
  • Mots-clés : traduction vidéo, doublage vidéo, sous-titres traduits, doublage en langue étrangère, sous-titres bilingues, dub a video, translate a video, foreign-language voiceover.
  • Tout flux de travail ASR -> traduction -> TTS -> composition vidéo.

Quand NE PAS l'utiliser

  • Seulement une transcription, sans traduction ni doublage -> utiliser video-minutes ou Whisper directement.
  • Seulement une synthèse vocale à partir de texte, sans vidéo -> utiliser mlx-tts.
  • Besoin de conserver la musique de fond / les effets sonores et de faire un mixage professionnel (séparation des voix) -> cette compétence ne fait pas de Demucs par défaut, nécessite un traitement séparé.
  • Vidéo sans piste audio ou qualité audio trop mauvaise pour être reconnue.

Flux de travail

De bout en bout, la méthode recommandée est d'utiliser le script d'orchestration <skill>/scripts/dub.py (voir ## Scripts), qui exécute automatiquement les étapes suivantes et s'arrête à la traduction pour attendre l'IA. En exécution manuelle, suivez ces étapes :

  1. Extraction audio (16 kHz mono) : ffmpeg -y -i input.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio16k.wav

  2. Transcription ASR (avec timestamps précis par segment) : whisper audio16k.wav --model large-v3-turbo --language <langue_source> --output_format srt --output_dir . Produit audio16k.srt, les timestamps sont naturellement alignés avec la vidéo originale. Pour une meilleure reconnaissance du chinois, on peut utiliser Qwen3-ASR (pip install qwen-asr) avec <skill>/scripts/qwen3_asr.py.

  3. Traduction des sous-titres (par l'IA) : lire le SRT, traduire segment par segment. Chaque segment SRT donne une ligne de traduction, en respectant strictement l'ordre. Compter d'abord le nombre de segments (ex. 27 segments -> 27 lignes), sauvegarder dans translated.txt, vérifier la correspondance du nombre de lignes avant de continuer.

  4. Génération du doublage : python3 <skill>/scripts/dub_segments.py audio16k.srt translated.txt dubbing.wav subtitle_synced.srt --lang <langue_cible> Le script : utilise le premier segment comme référence de timbre pour garantir un timbre cohérent ; conserve les timestamps d'origine pour synchroniser sous-titres et image ; applique un changement de vitesse (atempo 0.88–1.20) uniquement aux segments qui dépassent le créneau ; relie les intervalles de moins de 1 seconde pour un rendu naturel.

  5. Fusion de la piste de doublage avec la vidéo :

    ffmpeg -y -i input.mp4 -i dubbing.wav \
      -map 0:v:0 -map 1:a:0 \
      -c:v copy -c:a aac -b:a 192k -shortest output_temp.mp4
    

    Puis vérifier que la piste audio a bien été remplacée : ffprobe -v error -show_entries stream=codec_type -of csv=p=0 output_temp.mp4 (doit afficher video, audio).

  6. Incrustation des sous-titres durs : python3 <skill>/scripts/burn_subtitles.py output_temp.mp4 subtitle_synced.srt output_final.mp4 Rend les sous-titres traduits en permanence dans l'image.

  7. Nettoyage (optionnel) : supprimer audio16k.wav, audio16k.srt, translated.txt, dubbing.wav, subtitle_synced.srt, output_temp.mp4, etc.

Règles de décision

  • Pour une exécution en un clic -> utiliser dub.py ; pour ne refaire qu'une étape (ex. SRT déjà existant) -> dub.py --srt existing.srt saute l'étape.
  • Moteur ASR : par défaut --asr whisper (large-v3-turbo) ; si reconnaissance chinoise exigeante -> --asr qwen3.
  • Pas besoin de sous-titres durs -> dub.py --no-burn (s'arrête après la fusion audio).
  • La langue cible est définie par --target-lang (défaut zh) ; la langue TTS de dub_segments.py est définie par --lang.
  • La traduction doit être faite par l'IA et strictement 1:1 avec les segments SRT ; si le nombre de lignes ne correspond pas, le script échoue immédiatement ; ne pas contourner.
  • Si les sous-titres n'apparaissent pas ou que le chinois devient des carrés -> utiliser burn_subtitles.py (rendu avec moviepy, détection automatique de la police chinoise) ; ne pas dépendre de subtitles= de ffmpeg (qui échoue silencieusement si libass manque).
  • Si la durée du doublage dépasse le créneau -> s'appuyer sur l'atempo segmenté du script, ne pas appliquer de changement de vitesse global sur toute la piste.

Contraintes

  • Les timestamps doivent réutiliser les résultats ASR originaux, interdiction de refaire un ASR sur le doublage pour obtenir les timestamps.
  • Le nombre de lignes de traduction doit être égal au nombre de segments SRT (1:1), sinon arrêt.
  • La fusion audio doit explicitement utiliser -map 0:v:0 -map 1:a:0, sinon la piste audio originale est conservée.
  • L'ASR doit utiliser large-v3-turbo (ou turbo), ne pas revenir à base/tiny.
  • Le changement de vitesse se fait uniquement au niveau des segments, dans la plage 0.88–1.20x ; interdiction de l'atempo global.
  • Par défaut, pas de séparation des voix de la musique de fond ; si l'utilisateur le demande, il faut explicitement indiquer qu'un traitement supplémentaire est nécessaire.

Vérification

Avant la livraison, vérifier chaque point :

  • Le nombre de lignes dans translated.txt correspond exactement au nombre de segments SRT.
  • dubbing.wav et subtitle_synced.srt ont été générés.
  • ffprobe montre que la vidéo finale contient à la fois un flux vidéo et un flux audio, et que l'audio a bien été remplacé.
  • Les sous-titres sont bien incrustés dans l'image (pas de sous-titres externes mous), le chinois n'a pas de carrés.
  • Le doublage et l'image sont synchronisés à plusieurs points aléatoires vérifiés.
  • Les fichiers sources fournis par l'utilisateur n'ont pas été supprimés.

Résultat

  • Sortie : un fichier vidéo localisé (par défaut output_final.mp4, avec dub.py il s'agit de <nom_de_la_video>_<langue_cible>.mp4), contenant le doublage et les sous-titres durs dans la langue cible ; subtitle_synced.srt peut être conservé en option.
  • Terminé quand : la piste audio a été remplacée, les sous-titres incrustés, l'audio et l'image synchronisés aux points de vérification, et ffprobe valide.
  • Preuve : chemin du fichier final ; nombre de segments SRT et nombre de lignes de traduction ; liste des flux ffprobe ; points de synchronisation vérifiés.

Références

Charger à la demande, ne pas tout lire à l'avance :

  • references/pipeline-design.md — à lire lorsqu'il faut expliquer ou ajuster le comportement du pipeline (pourquoi conserver les timestamps, changement de vitesse segmenté, pas de séparation des voix par défaut, liste des artefacts et dépendances).
  • references/troubleshooting.md — à lire en cas d'erreur réelle, de désynchronisation audio/vidéo, de sous-titres absents ou de carrés chinois.

Scripts

  • <skill>/scripts/dub.py — orchestration de bout en bout. Utilisation : python3 <skill>/scripts/dub.py input.mp4 --source-lang en --target-lang zh [--asr whisper|qwen3] [--srt existing.srt] [-o out.mp4] [--font-size 28] [--no-burn] [--keep-temp]. Lors de l'étape de traduction, il génère to_translate.txt et demande à l'IA de produire translated.txt, puis continue ; il retourne le chemin de la vidéo finale et celui des sous-titres.
  • <skill>/scripts/dub_segments.py — TTS segmenté + alignement des timestamps. Utilisation : python3 <skill>/scripts/dub_segments.py original.srt translated.txt out_dub.wav out_synced.srt [--lang zh] [--min-atempo 0.88] [--max-atempo 1.20] [--gap-bridge 1.0] [--keep-temp]. Retourne dubbing.wav et subtitle_synced.srt alignés ; si le nombre de lignes de traduction ne correspond pas, il s'arrête avec le code de sortie 1.
  • <skill>/scripts/burn_subtitles.py — incrustation des sous-titres durs avec moviepy. Utilisation : python3 <skill>/scripts/burn_subtitles.py input.mp4 subtitles.srt output.mp4 [--font <chemin>] [--font-size 28]. Retourne la vidéo avec sous-titres incrustés ; si --font est omis, détection automatique de la police chinoise.
  • <skill>/scripts/qwen3_asr.py — CLI Qwen3-ASR compatible avec Whisper, meilleure reconnaissance du chinois. Utilisation : python3 <skill>/scripts/qwen3_asr.py audio.wav [--model 0.6B|1.7B] [--language zh] [-f srt|vtt|txt|json|tsv|all] [-o répertoire_sortie] [--device cuda:0|mps|cpu] [--dtype float16|bfloat16|float32]. Retourne les fichiers de sous-titres/texte dans le format spécifié. Alias de modèles : turbo/tiny/base/small -> Qwen3-ASR-0.6B, medium/large -> Qwen3-ASR-1.7B.

Dépannage

  • Le doublage n'est pas remplacé / le son original est toujours présent -> la fusion ffmpeg a oublié -map 0:v:0 -map 1:a:0.
  • Les sous-titres n'apparaissent pas ou le chinois devient des carrés -> utiliser burn_subtitles.py avec --font pour spécifier une police chinoise.
  • Le nombre de lignes de traduction ne correspond pas au nombre de segments SRT -> le script échoue et s'arrête ; compléter d'abord pour obtenir un ratio 1:1.
  • Liste complète des erreurs dans references/troubleshooting.md.

Compétences associées

  • mlx-tts — fournit la fonction sous-jacente mlx_audio.tts.generate, dont dépend cette compétence pour le doublage.
  • video-minutes — transformation d'une vidéo en résumé structuré ; à utiliser en remplacement si seule la transcription/résumé est nécessaire.

Skills associés