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, Incrustation | Non |
| 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 :
| Script | Utilisation |
|---|---|
scripts/porter.sh | Entrée principale Bash, transmet au CLI porter. |
scripts/porter.ps1 | Entrée principale Windows PowerShell, prend également en charge les sous-commandes inspect / plan / run / jobs. |
scripts/inspect.sh | Pré-vérification Bash, équivalent à porter.sh inspect. |
scripts/bootstrap.sh | Entré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) ouasr(passe par la reconnaissance vocale)translation.needed:falses'il existe déjà des sous-titres chinois, la traduction peut être entièrement sautéefeasible/blocking_issues: sifalse, arrêtez, ne lancez pas de tâchenotes: à 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) :
- Valeurs par défaut intégrées
- Variables d'environnement :
OPENAI_API_KEY,OPENAI_BASE_URL,OPENAI_MODEL,WHISPER_API_KEY,PORTER_ASR_ENGINE - Configuration utilisateur (
porter config listaffiche le chemin réel) - Configuration du projet :
porter.json/porter.toml/config.jsondans le répertoire courant --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_startretourne immédiatement +porter_job_statuspour 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 samplingutilise 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 addinstalle 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
| Fichier | Contenu |
|---|---|
references/ARCHITECTURE.md | Pipeline en quatre étapes, chaîne de repli plateforme/backend, contraintes de conception |
references/CONFIG.md | Toutes les clés de configuration, variables d'environnement, priorité |
references/MCP.md | Table de correspondance des outils MCP et méthodes de configuration |
references/HOSTS.md | Entrée native Windows et pré-vérification d'hôte restreint |
assets/config.example.json | Modèle de configuration |