Porter Skill (Transportista de Streaming)
Convierte un enlace de video en un producto final con subtítulos duros en chino. Cuatro etapas se ejecutan secuencialmente: Obtener → Transcribir → Traducir → Incrustar. Cada etapa escribe los resultados en disco, por lo que si se interrumpe a mitad de camino, no se pierde el trabajo ya completado.
⚠️ Requisito Previo: La Transcripción Requiere una Clave
Esto debe confirmarse primero; de lo contrario, la tarea fallará en la etapa de transcripción.
| Capacidad | ¿Necesita Clave? |
|---|---|
| Descarga, Traducción, Incrustación | No necesita |
| Transcripción de Voz (ASR) | Necesita OPENAI_API_KEY (o WHISPER_API_KEY), o tener instalado VideoCaptioner CLI |
| Pistas de subtítulos nativas de la plataforma (YouTube / Bilibili, etc.) | No necesita — si hay pista nativa, no se ejecuta ASR |
El "cierre de Python sin clave" que se afirmaba en v0.1 ya no es válido: todos los endpoints de reconocimiento de voz sin clave han sido desactivados (verificado el 2026-09-22; o use el extra [asr-local] para reconocimiento local sin clave). Sin una clave, si el video tampoco tiene pista de subtítulos de la plataforma, la tarea terminará en la etapa transcribe con every speech-to-text backend failed.
Por lo tanto: primero ejecute plan, que le dirá directamente si este video usará la pista de subtítulos nativa o ASR, y si es factible.
Punto de Entrada de Llamada
El punto de entrada CLI se ejecuta a través de uvx. En Windows PowerShell, use el .ps1 nativo, no asuma que Git Bash / WSL está disponible:
| Script | Propósito |
|---|---|
scripts/porter.sh | Entrada principal Bash, reenvía al CLI porter. |
scripts/porter.ps1 | Entrada principal de Windows PowerShell, también admite subcomandos inspect / plan / run / jobs. |
scripts/inspect.sh | Verificación previa Bash, equivalente a porter.sh inspect. |
scripts/bootstrap.sh | Punto de entrada alternativo para crear .venv desde el repositorio; no instala el código fuente de Python con la skill. |
# Verificación previa
<SKILL_DIR>/scripts/inspect.sh "https://youtu.be/dQw4w9WgXcQ"
# Planificación
<SKILL_DIR>/scripts/porter.sh plan "https://youtu.be/dQw4w9WgXcQ"
# Ejecución
<SKILL_DIR>/scripts/porter.sh run "https://youtu.be/dQw4w9WgXcQ" -o ./porter_output
Windows PowerShell usa & '<SKILL_DIR>\scripts\porter.ps1' inspect '<URL>' --json; plan / run / jobs también llaman al mismo punto de entrada. inspect.sh y los comandos nohup y grep a continuación son ejemplos de Bash, no se pueden pegar directamente en PowerShell.
uvx necesita conexión a internet para resolver dependencias la primera vez que se ejecuta. Por defecto, solo instala porter-workflow[llm] (el paquete base ya incluye yt-dlp); cuando se necesita ASR local, con el consentimiento del usuario se establece PORTER_SKILL_SPEC=porter-workflow[llm,asr-local]. Para instalación sin conexión, prepare las dependencias locales en el repositorio, no espere que el directorio de la skill tenga el código fuente.
En un anfitrión donde solo se puede escribir en el área de trabajo, primero confirme el directorio absoluto permitido, establezca PORTER_SKILL_STATE_DIR en un .state dentro de él, ejecute porter.sh --host-check o porter.ps1 --host-check; esto redirigirá uv, yt-dlp y el caché del registro de trabajos (anulando las rutas de caché ya configuradas por el anfitrión). El directorio de salida -o también debe estar en el directorio permitido. Si no se establece, se conservan las rutas predeterminadas del anfitrión. Consulte references/HOSTS.md para comandos, limitaciones y ejemplos de Windows.
Ciclo Cerrado del Flujo de Trabajo
Ejecutar en orden. Cada paso es más barato que el siguiente, con el objetivo de rechazar entradas incorrectas antes de gastar mucho tiempo de cómputo.
1. Verificación Previa — inspect
<SKILL_DIR>/scripts/inspect.sh "<URL>" --json
Devuelve plataforma, título, duración, resolución, relación de aspecto, si tiene pista de subtítulos. Se completa antes de descargar cualquier medio, en segundos.
Interpretación: is_valid significa "el enlace es utilizable", ok solo significa "la llamada fue exitosa". Si el enlace está roto, is_valid=false; en ese caso, no reintente — no tiene sentido reintentar un enlace muerto.
Código de salida 1 significa que el enlace no está disponible.
2. Planificación — plan
<SKILL_DIR>/scripts/porter.sh plan "<URL>" --json
Este es el paso que ahorra más tiempo, responde "cómo se procesará este video y si es factible":
subtitles.route:platform(usa pistas de subtítulos nativas de la plataforma) oasr(ejecuta reconocimiento de voz)translation.needed:falsesi ya hay una pista en chino; se puede saltar toda la traducciónfeasible/blocking_issues: si esfalse, deténgase, no inicie un trabajonotes: lectura obligatoria. Las dos más importantes:- La pista de subtítulos de la plataforma es "solicitada, no garantizada" — la descarga puede fallar (limitación de la plataforma, HTTP 429) y se recurre al reconocimiento de voz
- Si los backends de reconocimiento disponibles son todos puntos finales invertidos no probados, la nota lo dirá claramente
Código de salida 1 significa que no es factible.
3. Confirmación con el Usuario
Un trabajo puede descargar cientos de MB y ejecutarse durante minutos. Informe al usuario de las conclusiones de plan y obtenga su consentimiento antes de comenzar (qué ruta se tomará, qué etapas se ejecutarán, si se incrustarán subtítulos). Si feasible=false, informe el problema bloqueante, no inicie un trabajo.
4. Ejecución — run
<SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output
No use una llamada en primer plano para esperar a que termine un video largo. Inícielo en segundo plano y luego consulte el registro de trabajos:
nohup <SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output > run.log 2>&1 &
# Consulta (los registros de trabajos se escriben en un archivo de registro compartido, visible entre procesos)
<SKILL_DIR>/scripts/porter.sh jobs list
<SKILL_DIR>/scripts/porter.sh jobs status <job_id>
En PowerShell, use la herramienta de trabajos en segundo plano proporcionada por el anfitrión para iniciar asincrónicamente & '<SKILL_DIR>\scripts\porter.ps1' run ..., y continúe usando el mismo PORTER_SKILL_STATE_DIR para llamar a jobs status. No use Out-String para acumular el progreso de un comando largo hasta que termine.
No use "establecer el tiempo de espera de la herramienta en 1200 segundos" para soportar tareas largas (el enfoque de v0.1). Eso aún falla con videos más largos y no obtiene ningún progreso cuando falla. El registro de trabajos está diseñado para esto.
5. Control de Calidad (Obligatorio)
No se limite a mirar el código de salida y decir que está completo. Al menos confirme:
# 1. Los subtítulos en chino realmente existen y contienen CJK (para evitar "subtítulos falsos sin traducir")
grep -qP '[\x{4e00}-\x{9fff}]' ./porter_output/<task>/cooked/subtitle_zh.srt \
&& echo "OK: Contiene chino" || echo "FAIL: Sin chino"
# 2. El producto final se puede decodificar y el átomo moov está intacto (para evitar archivos truncados al publicar)
ffprobe -v error -show_entries format=duration -of csv=p=0 ./porter_output/<task>/cooked/video_zh.mp4
Un tamaño de archivo final anormalmente pequeño generalmente significa que la incrustación falló, no que el video sea corto.
6. Cuando Reporte Errores
<SKILL_DIR>/scripts/porter.sh doctor # Esta máquina puede funcionar: ffmpeg/libass, tiempo de ejecución JS, fuentes, codificador
<SKILL_DIR>/scripts/porter.sh config list # Configuración analizada (claves enmascaradas)
Parámetros Comunes
# Solo subtítulos, sin incrustar
run "<URL>" --burn skip
# Solo producto final en chino puro (sin bilingüe)
run "<URL>" --burn zh_only
# Especificar directorio de salida / idioma de destino
run "<URL>" -o /path/to/out --target-lang zh-Hans
# Forzar el uso de un backend específico primero (el resto aún son alternativas, no "usar solo ese")
run "<URL>" --translator google
run "<URL>" --asr-engine whisper-api
# Cambiar el modelo LLM para este trabajo (sin cambiar la configuración)
run "<URL>" --llm-model deepseek-reasoner
# Ya tiene subtítulos de origen existentes: úselos directamente, no ejecute reconocimiento (.srt / .vtt)
run "<URL>" --subtitle-file ./my_subtitles.srt
# Video que requiere inicio de sesión para verlo
run "<URL>" --cookies-from-browser chrome
run "<URL>" --cookies ./cookies.txt
# Volver a ejecutar (ignorar resultados de etapas en caché)
run "<URL>" --force
# Para consumo por script
run "<URL>" --json
La semántica de --only-phase es "hasta esta etapa", no "solo ejecutar esta etapa" — cada etapa consume la salida de la etapa anterior, por lo que las etapas anteriores aún se ejecutarán.
Estructura de los Productos
<task_dir>/
├── raw/ # Master y productos intermedios
│ ├── video.mp4 # Master estandarizado (copia de flujo sin pérdida, sin recodificación)
│ ├── audio.wav # Pista de audio de referencia
│ ├── audio_enhanced.wav # Pista de audio mejorada para ASR (reducción de ruido + ecualización de voz), no se usa para el producto final
│ ├── subtitle.srt # Subtítulos en el idioma de origen (pista de plataforma o resultado de ASR)
│ ├── transcript.json/.txt # Guión estructurado
│ ├── cover.jpg
│ └── metadata.json
└── cooked/ # Productos finales
├── subtitle.srt / .ass # Bilingüe
├── subtitle_zh.srt / .ass # Solo chino
├── video_bilingual.mp4 # Producto final con subtítulos duros bilingües
└── video_zh.mp4 # Producto final con subtítulos duros solo en chino
El audio del producto final es una copia directa (-c:a copy) del master original; la pista de audio mejorada solo se usa para el reconocimiento, logrando tanto precisión en el reconocimiento como calidad de audio en el producto final.
Configuración
Orden de búsqueda de configuración (el posterior anula al anterior):
- Valores predeterminados integrados
- Variables de entorno:
OPENAI_API_KEY,OPENAI_BASE_URL,OPENAI_MODEL,WHISPER_API_KEY,PORTER_ASR_ENGINE - Configuración del usuario (
porter config listimprimirá la ruta real) - Configuración del proyecto:
porter.json/porter.toml/config.jsonen el directorio actual --config <ruta>
Consulte la tabla de claves completa en references/CONFIG.md y la plantilla en assets/config.example.json.
Uso a través de MCP (Opcional, pero Mejor)
Si el anfitrión ya tiene configurado un servidor MCP de porter, utilícelo en lugar del shell:
- Resultados estructurados, sin necesidad de analizar stdout (evitando problemas de escape y codificación del shell)
porter_job_startdevuelve inmediatamente +porter_job_statuspara sondeo, las tareas largas no chocan con el tiempo de espera de la herramienta- Única forma de obtener "traducción de nivel LLM sin clave":
§8.3 samplingusa el modelo del anfitrión para traducir; el proceso CLI no puede acceder al modelo del anfitrión
Consulte la tabla de herramientas y el método de configuración en references/MCP.md.
Nota:
npx skills addsolo instala el directorio de esta skill, no instala el servidor MCP. En una instalación nueva, la ruta CLI es la referencia.
Archivos de Referencia
| Archivo | Contenido |
|---|---|
references/ARCHITECTURE.md | Tubería de cuatro etapas, cadena de respaldo de plataforma y backend, restricciones de diseño |
references/CONFIG.md | Todas las claves de configuración, variables de entorno, prioridad |
references/MCP.md | Tabla de herramientas MCP y método de configuración |
references/HOSTS.md | Entrada nativa de Windows y verificación previa de anfitrión restringido |
assets/config.example.json | Plantilla de configuración |