Communitygithub.com

Localisation vidéo : du lien à la version sous-titrée

Transformez un lien YouTube, X, Instagram, TikTok ou Bilibili en version localisée avec Porter : récupération, transcription, traduction et incrustation FFmpeg de sous-titres bilingues ou chinois, chaque étape enregistrée sur disque.

Qu'est-ce que Localisation vidéo : du lien à la version sous-titrée ?

Recette Localisation vidéo, étape 1 (le pipeline de bout en bout), issue de RolinShmily/porter-workflow. Porter enchaîne quatre étapes reprenables — récupération → transcription → traduction → incrustation — et écrit chaque résultat sur disque, pour qu'un échec ne perde jamais le travail déjà fait. L'agent lance d'abord `plan` pour savoir si la vidéo a une piste de sous-titres native (sans ASR ni clé) ou s'il faut une transcription compatible Whisper, puis produit des SRT bilingues et chinois et des MP4 sous-titrés en dur via libass. Un seul moteur : CLI, serveur MCP, atelier web et cette Agent Skill.

Compatible avec~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/RolinShmily/porter-workflow/tree/HEAD/skills/porter-skill

Demander à votre IA préférée

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

Documentation

Porter Skill (Streaming Porter)

Transforme un lien vidéo en un produit fini avec sous-titres chinois incrustés. Quatre étapes exécutées séquentiellement : Acquisition → Transcription → Traduction → Incrustation, chaque étape écrit ses artefacts sur le disque, donc en cas d'échec en cours de route, les parties déjà terminées ne sont pas perdues.


⚠️ Condition préalable : La transcription nécessite une clé

Cette condition doit être vérifiée en premier, sinon la tâche échouera lors de l'étape de transcription.

CapacitéNécessite une clé
Téléchargement, Traduction, IncrustationNon
Transcription vocale (ASR)Nécessite OPENAI_API_KEY (ou WHISPER_API_KEY), ou avoir installé VideoCaptioner CLI
Pistes de sous-titres natives de la plateforme (YouTube / Bilibili, etc.)Non — si une piste native existe, pas d'ASR

La promesse de v0.1 "boucle fermée en Python pur sans clé" n'est plus valable : tous les points de terminaison de reconnaissance vocale sans clé sont arrêtés (testé le 2026-09-22 ; ou utilisez l'extra [asr-local] pour une reconnaissance locale sans clé). Sans clé, si la vidéo n'a pas non plus de piste de sous-titres de la plateforme, la tâche se terminera à l'étape transcribe avec every speech-to-text backend failed.

Donc : exécutez d'abord plan, il vous indiquera directement si cette vidéo utilise une piste de sous-titres native ou l'ASR, et si c'est réalisable.


Point d'entrée

L'entrée CLI s'utilise via uvx. Windows PowerShell utilisez le .ps1 natif, ne supposez pas que Git Bash / WSL est disponible :

ScriptUtilisation
scripts/porter.shEntrée principale Bash, transmet au CLI porter.
scripts/porter.ps1Entrée principale Windows PowerShell, prend également en charge les sous-commandes inspect / plan / run / jobs.
scripts/inspect.shPré-vérification Bash, équivalent à porter.sh inspect.
scripts/bootstrap.shEntrée alternative pour créer .venv à partir de l'extraction du dépôt ; n'installe pas le code source Python avec la compétence.
# Pré-vérification
<SKILL_DIR>/scripts/inspect.sh "https://youtu.be/dQw4w9WgXcQ"
# Planification
<SKILL_DIR>/scripts/porter.sh plan "https://youtu.be/dQw4w9WgXcQ"
# Exécution
<SKILL_DIR>/scripts/porter.sh run "https://youtu.be/dQw4w9WgXcQ" -o ./porter_output

Windows PowerShell utilisez & '<SKILL_DIR>\scripts\porter.ps1' inspect '<URL>' --json, plan / run / jobs appellent également la même entrée. inspect.sh et les commandes nohup, grep ci-dessous sont des exemples Bash, ne peuvent pas être collés tels quels dans PowerShell.

uvx nécessite une connexion réseau pour résoudre les dépendances lors de la première exécution. Par défaut, seul porter-workflow[llm] est installé (le package de base inclut déjà yt-dlp) ; pour l'ASR local, après accord de l'utilisateur, définissez PORTER_SKILL_SPEC=porter-workflow[llm,asr-local]. Pour une installation hors ligne, préparez les dépendances locales dans le dépôt extrait, n'espérez pas que le répertoire de compétence fournisse le code source.

Dans un hôte où seul l'espace de travail est accessible en écriture, vérifiez d'abord le répertoire absolu autorisé, définissez PORTER_SKILL_STATE_DIR sur un .state dans celui-ci, exécutez porter.sh --host-check ou porter.ps1 --host-check ; il redirigera uv, yt-dlp et le cache du registre des tâches vers ce répertoire (remplaçant les chemins de cache définis par l'hôte). La sortie -o doit également se trouver dans un répertoire autorisé. S'il n'est pas défini, les chemins par défaut de l'hôte sont conservés. Commandes, limitations et exemple Windows dans references/HOSTS.md.


Boucle fermée du flux de travail

Exécutez dans l'ordre. Chaque étape est moins coûteuse que la suivante, le but est d'éliminer les mauvaises entrées avant d'investir du temps de calcul long.

1. Pré-vérification — inspect

<SKILL_DIR>/scripts/inspect.sh "<URL>" --json

Retourne la plateforme, le titre, la durée, la résolution, le format d'image, la présence de pistes de sous-titres. Terminé avant tout téléchargement, en quelques secondes.

Interprétation : is_valid signifie "le lien est utilisable", ok signifie seulement "l'appel a réussi". Si le lien est invalide, is_valid=false, ne réessayez pas — réessayer un lien mort n'a pas de sens.

Code de sortie 1 signifie que le lien n'est pas utilisable.

2. Planification — plan

<SKILL_DIR>/scripts/porter.sh plan "<URL>" --json

C'est l'étape la plus économique : elle répond à "comment cette vidéo va être traitée et si c'est possible" :

  • subtitles.route : platform (utilise les sous-titres natifs de la plateforme) ou asr (passe par la reconnaissance vocale)
  • translation.needed : false s'il existe déjà des sous-titres chinois, la traduction peut être entièrement sautée
  • feasible / blocking_issues : si false, arrêtez, ne lancez pas de tâche
  • notes : à lire impérativement. Les deux plus importantes :
    • Les pistes de sous-titres de la plateforme sont "demandées, non garanties" — la récupération peut échouer (limitation de débit de la plateforme, HTTP 429) et on basculera vers la reconnaissance vocale
    • Si tous les backends de reconnaissance disponibles sont des endpoints inverses non testés, la note le spécifiera clairement

Code de sortie 1 signifie que ce n'est pas réalisable.

3. Confirmation avec l'utilisateur

Une tâche peut télécharger plusieurs centaines de Mo et prendre quelques minutes. Rapportez les conclusions du plan à l'utilisateur et obtenez son accord avant de lancer (quelle piste, quelles étapes, si incrustation). Si feasible=false, rapportez le blocage, ne lancez pas de tâche.

4. Exécution — run

<SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output

Pour les vidéos longues, n'utilisez pas un appel en avant-plan pour attendre la fin. Lancez en arrière-plan, puis interrogez le registre des tâches :

nohup <SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output > run.log 2>&1 &
# Interrogation (les enregistrements de tâches sont écrits dans un fichier de registre partagé, visible d'un processus à l'autre)
<SKILL_DIR>/scripts/porter.sh jobs list
<SKILL_DIR>/scripts/porter.sh jobs status <job_id>

PowerShell utilisez l'outil de tâches en arrière-plan fourni par l'hôte pour lancer de manière asynchrone & '<SKILL_DIR>\scripts\porter.ps1' run ..., et continuez à appeler jobs status avec le même PORTER_SKILL_STATE_DIR. N'utilisez pas Out-String pour accumuler la progression des commandes longues jusqu'à la fin avant de les afficher.

N'utilisez pas la méthode "mettre le délai d'attente de l'outil à 1200 secondes" pour supporter les tâches longues (comme v0.1). Cela échouerait encore pour des vidéos plus longues, et vous n'obtiendriez aucune progression en cas d'échec. Le registre des tâches est conçu pour cela.

5. Contrôle qualité (obligatoire)

Ne vous contentez pas de vérifier le code de sortie pour dire que c'est terminé. Vérifiez au moins :

# 1. Les sous-titres chinois existent et contiennent du CJK (pour éviter les "faux sous-titres non traduits")
grep -qP '[\x{4e00}-\x{9fff}]' ./porter_output/<task>/cooked/subtitle_zh.srt \
  && echo "OK: Contient du chinois" || echo "ÉCHEC: Pas de chinois"

# 2. Le produit fini est décodable et le moov atom est intact (pour éviter les fichiers tronqués publiés)
ffprobe -v error -show_entries format=duration -of csv=p=0 ./porter_output/<task>/cooked/video_zh.mp4

Une taille de fichier anormalement petite indique généralement un échec de l'incrustation, pas une vidéo courte.

6. En cas d'erreur

<SKILL_DIR>/scripts/porter.sh doctor     # Cette machine peut-elle fonctionner : ffmpeg/libass, runtime JS, polices, encodeurs
<SKILL_DIR>/scripts/porter.sh config list # Configuration analysée (clés masquées)

Paramètres courants

# Sous-titres uniquement, pas d'incrustation
run "<URL>" --burn skip

# Produit fini chinois uniquement (pas de bilingue)
run "<URL>" --burn zh_only

# Spécifier le répertoire de sortie / la langue cible
run "<URL>" -o /path/to/out --target-lang zh-Hans

# Faire passer un backend en priorité (les autres restent des replis, pas "utiliser uniquement celui-ci")
run "<URL>" --translator google
run "<URL>" --asr-engine whisper-api

# Pour cette tâche, utiliser un modèle LLM différent (sans modifier la configuration)
run "<URL>" --llm-model deepseek-reasoner

# Avoir déjà des sous-titres sources : les utiliser directement, pas de reconnaissance (.srt / .vtt)
run "<URL>" --subtitle-file ./my_subtitles.srt

# Vidéo nécessitant une connexion pour être vue
run "<URL>" --cookies-from-browser chrome
run "<URL>" --cookies ./cookies.txt

# Relancer (ignorer les résultats d'étape mis en cache)
run "<URL>" --force

# Pour consommation par script
run "<URL>" --json

La sémantique de --only-phase est "jusqu'à cette étape", pas "exécuter seulement cette étape" — chaque étape consomme la sortie de l'étape précédente, donc les étapes antérieures seront toujours exécutées.


Structure des artefacts

<task_dir>/
├── raw/                       # Masters et artefacts intermédiaires
│   ├── video.mp4              # Master normalisé (copie de flux sans perte, pas de second encodage)
│   ├── audio.wav              # Piste audio de référence
│   ├── audio_enhanced.wav     # Piste audio améliorée dédiée à l'ASR (débruitage + égalisation vocale), pas utilisée dans le produit fini
│   ├── subtitle.srt           # Sous-titres dans la langue source (piste plateforme ou résultat ASR)
│   ├── transcript.json/.txt   # Script structuré
│   ├── cover.jpg
│   └── metadata.json
└── cooked/                    # Produits finis
    ├── subtitle.srt / .ass    # Bilingue
    ├── subtitle_zh.srt / .ass # Chinois uniquement
    ├── video_bilingual.mp4    # Produit fini avec incrustation bilingue
    └── video_zh.mp4           # Produit fini avec incrustation chinoise uniquement

L'audio du produit fini est copié directement (-c:a copy) depuis le master d'origine ; la piste améliorée est utilisée uniquement pour la reconnaissance — qualité de reconnaissance et qualité sonore du produit fini sont toutes deux garanties.


Configuration

Ordre de recherche de la configuration (la suivante remplace la précédente) :

  1. Valeurs par défaut intégrées
  2. Variables d'environnement : OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL, WHISPER_API_KEY, PORTER_ASR_ENGINE
  3. Configuration utilisateur (porter config list affiche le chemin réel)
  4. Configuration du projet : porter.json / porter.toml / config.json dans le répertoire courant
  5. --config <chemin>

Table complète des clés dans references/CONFIG.md, modèle dans assets/config.example.json.


Utilisation via MCP (optionnel, mais recommandé)

Si l'hôte a déjà configuré un serveur MCP porter, privilégiez-le plutôt que le shell :

  • Résultats structurés, pas besoin de parser stdout (évite aussi les problèmes d'échappement shell et d'encodage)
  • porter_job_start retourne immédiatement + porter_job_status pour interroger, les tâches longues n'atteignent pas le délai d'attente de l'outil
  • Seul moyen d'obtenir une "traduction de niveau LLM sans clé" : le §8.3 sampling utilise le modèle de l'hôte pour traduire, les processus CLI n'ont pas accès au modèle de l'hôte

Table de correspondance des noms d'outils et méthodes de configuration dans references/MCP.md.

Note : npx skills add installe uniquement le répertoire de cette compétence, n'installe pas le serveur MCP. Pour une nouvelle installation, suivez les chemins CLI.


Fichiers de référence

FichierContenu
references/ARCHITECTURE.mdPipeline en quatre étapes, chaîne de repli plateforme/backend, contraintes de conception
references/CONFIG.mdToutes les clés de configuration, variables d'environnement, priorité
references/MCP.mdTable de correspondance des outils MCP et méthodes de configuration
references/HOSTS.mdEntrée native Windows et pré-vérification d'hôte restreint
assets/config.example.jsonModèle de configuration

Skills associés