Communitygithub.com

Perso Dubbing — envío lip-sync multi-idioma

Plugin Perso AI auto-dub: upload→split→translate→merge→MP4 con lip-sync. Multi-target en un comando. README con GIFs demo + MP4. Claude/Cursor/Codex. 38★.

¿Qué es Perso Dubbing — envío lip-sync multi-idioma?

Video Localization paso 3 (ship): perso-ai/perso-dubbing-plugin — 38★ dub lip-sync multi-idioma con GIFs en docs/media. Fresco vs VoxCPM 26-sep e IndexTTS2/ChHsiching 24-sep.

Compatible con✓Claude Code✓Codex CLI✓Cursor✓Antigravity✓Gemini CLI
npx skills add perso-ai/perso-dubbing-plugin

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

/dubbing

Una habilidad que dobla videos automáticamente mediante la API de Perso AI Dubbing.

Reglas principales (deben seguirse)

  • Solo el worker ve la clave sin procesar. Nunca abras la clave con Read, la hagas eco o la pases como argumento de línea de comandos. Los workers la envían solo en el encabezado XP-API-KEY.
  • Un comando = todo el trabajo. scripts/dubbing.mjs maneja subida, división, traducción, combinación y guardado por sí mismo. Nunca ejecutes prepare_input.mjs o probe_split.mjs antes — son herramientas de depuración, y probe_split.mjs realiza una subida real (el video se subiría dos veces).
  • Ejecuta siempre dubbing.mjs en segundo plano. Los trabajos toman de minutos a horas; un tiempo de espera del shell en primer plano mata la ejecución a medio camino.
  • Idiomas no especificados → fuente auto, destino en.
  • Varios idiomas van en un solo comando (--target en,zh,ja) — la subida/división ocurre una vez y se reutiliza por idioma. Nunca ejecutes una vez por idioma (vuelve a subir la fuente cada vez).
  • Transmite el progreso fielmente. Muestra las líneas [progress] de stdout del worker al chat, textualmente o resumidas — y no anuncies pasos que no aparecieron (la división/combinación solo existen para videos que exceden el límite). Los detalles de registro detallados con sangría en stderr no necesitan ser transmitidos.
  • Mantén al usuario informado mientras se ejecuta. El doblaje, el sincronizado de labios y la separación de audio imprimen un latido [status] (etapa + conteo de elementos, ej. ja 4/6 · en 1/6 o separating — file 2/5, con una pista next check ~Nm), y cada elemento finalizado se transmite como una línea [progress]. Revisa la salida en segundo plano ~3 minutos después del lanzamiento, luego en el intervalo sugerido (10 min para medios ≤10 min, 30 min para más largos): transmite cualquier nueva línea [progress] de inmediato; de lo contrario, publica la última línea [status] como una actualización de una línea. Nunca inventes porcentajes, tiempo transcurrido o ETA — transmite solo lo que dicen las líneas. Las paradas que necesitan al usuario ([space-select], [split-confirm], [free-limit], [resume-check], [credit-check], crédito agotado, finalización) terminan el proceso, por lo que aparecen sin necesidad de sondeo.
  • Nombra tu runtime para telemetría (silenciosamente). Agrega --host <claude-code|codex|cursor|antigravity|gemini> al comando del worker, nombrando el agente que estás ejecutando, si puedes saberlo. Solo etiqueta la telemetría de uso — nunca se lo muestres al usuario y nunca le preguntes al respecto. Omítelo si no estás seguro.
  • Los formatos no compatibles se omiten automáticamente y el resto continúa procesándose — transmite el aviso de omisión.
  • Una pausa no es un fallo. Una línea [space-select], [split-confirm], [free-limit], [credit-check] o [resume-check] significa que la ejecución se detuvo para preguntarte algo — sale con 0 (por lo que nunca parece un error), pero el trabajo no está completo. Siempre que aparezca una de estas líneas, nunca informes la ejecución como terminada: transmítela y actúa sobre ella. Las líneas son la señal, no el código de salida.

Configuración (perezosa — sin paso previo)

  1. Clave API — no es un paso que ejecutes primero. El worker se cierra automáticamente en el momento en que se ejecuta un comando que necesita la API de Perso: en la primera ejecución de ese tipo, abre una página del navegador (inicia sesión, un clic — la clave se almacena cifrada), o imprime instrucciones basadas en archivos si no se puede abrir el navegador — transmítelas al usuario. En una máquina sin interfaz gráfica/SSH, el worker omite el flujo del navegador por completo y comienza con el registro de archivos/--import (la página del navegador solo puede entregar una clave a la máquina en la que se ejecuta) — transmite esas instrucciones de la misma manera. Nunca actives el registro de clave tú mismo: el worker inicia connect.mjs/resolve_key.mjs --watch cuando es necesario, así que no los ejecutes, y no ejecutes resolve_key.mjs --check como paso previo (solo si el usuario pregunta explícitamente si hay una clave registrada — la falta de clave no es un error). Nunca pegues la clave en el chat. Obtén una clave: https://developers.perso.ai/api-keys
  2. ffmpeg/ffprobe — se instalan automáticamente solo cuando un video excede el límite del plan y debe dividirse (aprueba si se solicita permiso). Verificación manual: node scripts/check_deps.mjs.

Ejecutar

Recopila la entrada (ruta local o URL — vuelve a preguntar si falta) y ejecuta en segundo plano — el worker realiza el control de clave automáticamente en la primera necesidad; simplemente transmite sus instrucciones impresas si se inicia el registro:

  • Simple: node scripts/dubbing.mjs "<archivo|URL>" [--source auto] [--target en] [--space "nombre del espacio"] [--out result.mp4] [--lipsync] [--no-save]
  • Multilingüe / múltiples entradas (una o más entradas; las URL y los archivos se pueden mezclar): node scripts/dubbing.mjs "<URL>" "<archivo>" --target en,ja — una salida por entrada × idioma, guardada junto a cada fuente (--out <carpeta> las recopila).
  • Carpeta (lote): node scripts/dubbing.mjs "<carpeta>" [--target en,zh] [--recursive] [--out carpeta-de-salida]

Códigos de idioma — --target toma un código de idioma (en, ja) o una etiqueta regional. Las variantes regionales existen solo para Inglés (en = EE. UU. predeterminado, en-GB = Reino Unido), Portugués (pt = Brasil predeterminado, pt-PT = Portugal) y Español (es = México predeterminado, es-ES = España); en-US, pt-BR y es-MX son ortografías aceptadas de esos valores predeterminados. Cada otro idioma tiene una sola variante, y --source solo necesita el idioma (una etiqueta regional allí se trata como el idioma simple).

  • Región nombrada en la solicitud → usa esa etiqueta exacta. Una región sin variante (ej. inglés australiano) → dile al usuario que solo existen las opciones listadas y deja que elija antes de ejecutar.
  • Los tokens de dos letras son códigos de idioma, no países: uk es Ucraniano — el inglés británico es en-GB. Misma trampa para ca (Catalán), be (Bielorruso), eu (Vasco). Si las palabras del usuario podrían significar cualquiera, pregunta cuál quiere decir antes de ejecutar.
  • Idioma nombrado sin región → la variante predeterminada. Para esos tres idiomas, nombra la variante predeterminada aplicada en la nota de entrega (ej. "Español (México) — usa es-ES para España").

Ubicación de guardado — --out toma ya sea una carpeta (un directorio existente, o una ruta que termina en /) que recopila los resultados dentro de ella, o una ruta de archivo para una sola entrada (la extensión real se agrega si la ruta no tiene ninguna). El valor predeterminado es junto a cada archivo fuente; no preguntes. En el primer trabajo de la sesión, indícalo en la línea de inicio (ej. "Los resultados se guardarán junto a los originales — dímelo ahora si prefieres una carpeta diferente") y comienza de inmediato, sin esperar una respuesta. Si el usuario nombra una carpeta — con esta solicitud o en cualquier momento posterior en esta sesión — ejecuta con --out "<carpeta>" y sigue usando esa carpeta para cada trabajo posterior hasta que la cambie. Si redirige después de que un trabajo ya haya comenzado, mueve los archivos terminados allí cuando se complete la ejecución. Excepción: cuando cada entrada es una URL (sin carpeta fuente local), pregunta dónde guardar antes de comenzar.

Selección de espacio — con varios espacios de trabajo, el worker se detiene antes de subir, imprime líneas [space-select] (nombre | (plan) | créditos restantes) y se detiene. Muestra al usuario SOLO esas opciones (sin números internos), pregunta cuál y vuelve a ejecutar con --space "<nombre del espacio>". Un espacio → sin pregunta; PERSO_SPACE_SEQ lo fija.

Confirmación de división — si la entrada excede el límite de duración o tamaño y debe dividirse y combinarse automáticamente (doblaje, doblaje+sincronizado de labios, o separación de audio), el worker se detiene e imprime líneas [split-confirm]. Transmítelas y pregunta al usuario: excede el límite de duración/tamaño, por lo que necesita división automática → procesamiento → combinación, que puede resultar menos pulido que dividirlo ellos mismos — ¿proceder automáticamente? Si es sí, vuelve a ejecutar el mismo comando con --allow-split (nada se factura hasta este punto, por lo que volver a ejecutar es gratuito). Ejecuciones por lotes: --allow-split autoriza cada división en la ejecución.

No guardar (solo servidor) — cuando el usuario quiere el video doblado pero no guardado como archivo local, agrega --no-save: el worker deja el resultado en el espacio de trabajo de Perso del usuario y omite la descarga, imprimiendo Kept on server, not saved: … → proyecto <seq> (la línea [project-ref] aún se emite, por lo que el doblaje se puede sincronizar con labios o recuperar más tarde). Solo videos simples/no divididos — el archivo combinado de un video dividido necesita una descarga local, por lo que se guarda normalmente y el worker lo dice. No se puede combinar con --lipsync (el video con sincronizado de labios debe descargarse).

Plan gratuito (los resultados permanecen en Perso) — un espacio de trabajo Gratuito puede doblar, sincronizar labios y separar normalmente, pero el servidor rechaza cada descarga, por lo que el worker nunca guarda un archivo allí. Imprime Free plan — <nombre>: … ready on Perso → <url> (downloads need a paid plan) — transmite ese enlace como el resultado entregado: la ejecución está completa, nada falló y no hay nada que reanudar. Si el usuario quiere archivos reales, necesita un plan de pago — ofrece la ruta de actualización (ver Actualización de plan y créditos), nunca una nueva ejecución.

Pausas del plan gratuito [free-limit] — dos de ellas, ambas antes de que se facture algo:

  • Vista previa de 30 segundos. Una entrada de doblaje/sincronizado de labios de más de 30 s se detiene con líneas [free-limit]: en Gratuito solo se doblarían los primeros 30 segundos, el resto se omitiría. Transmite la pregunta, y si es sí, vuelve a ejecutar el mismo comando con --allow-preview (el worker recorta los primeros 30 s localmente y envía solo eso). Un enlace de plataforma importado por Perso no se puede recortar — allí la respuesta es un archivo local, un clip más corto o una actualización.
  • Sobre el límite del plan. Los medios que superan el límite de duración/tamaño del plan no reciben oferta de división en Gratuito (--allow-split no aplica): las líneas [free-limit] dicen que un archivo más corto o una actualización es la única opción. Transmítelas y detente.

Mientras se ejecuta (para explicar la espera):

  • División: el archivo completo se sube primero; solo un rechazo por límite del plan instala ffmpeg y divide sin pérdida. Las URL externas (YouTube·TikTok·Drive·Vimeo) se manejan en el lado del servidor.
  • Cola: todas las entradas × partes × idiomas comparten un grupo; una cola llena se vuelve a verificar cada 5 minutos. Un error del motor en una parte cancela los otros idiomas de esa parte; una parte silenciosa pasa el original; un guardia inactivo evita que se cuelgue para siempre.
  • Guardado: las partes se combinan nuevamente en un archivo por (entrada × idioma). Una salida no dividida mantiene el nombre de archivo de Perso; una combinada es <nombre-original>.dubbed.<idioma>.<ext>; las colisiones obtienen _2,_3….

Sincronizado de labios

El sincronizado de labios (boca ajustada al audio doblado) se ejecuta después del doblaje, en el proyecto de doblaje terminado. Solo video — las entradas de audio se rechazan. Es un trabajo largo: ejecuta en segundo plano y dile al usuario de antemano que toma considerablemente más tiempo que el doblaje. Créditos (la facturación del servidor es autoritativa): doblaje ≈ segundos ×1 · sincronizado de labios ≈ ×2 · ambos ≈ ×3 — doblaje ahora + sincronizado de labios después cuesta lo mismo que ambos a la vez. Fuentes 4K+: cada tarifa ×3 en planes pro/negocio/empresa (ej. un doblaje+sincronizado de labios de 1 min en 4K ≈ 60×3×3 = 540) — menciona esto cuando el video sea 4K.

Elige el flujo según lo que exista:

  1. Video nuevo + sincronizado de labios — un comando ejecuta toda la cadena (doblaje → sincronizado de labios → guardado); advierte que ambas etapas facturan: node scripts/dubbing.mjs "<archivo|URL>" --target en --lipsync Si aparecen líneas [credit-check] y se detiene, la estimación supera los créditos restantes: muestra esas líneas (URL de recarga incluida), y vuelve a ejecutar con --force solo después de que el usuario recargue o apruebe continuar de todos modos.
  2. Doblado antes en esta sesión — cada ejecución terminada imprime una línea [project-ref] {...}. Consérvala; nunca se la muestres al usuario. Sincronizado de labios sin redoblaje (×2, sin cargo de doblaje): node scripts/dubbing.mjs --lipsync-only '<ese JSON de [project-ref]>'
  3. Sin [project-ref] en esta sesión — pregunta si el usuario sabe el número de proyecto del portal de Perso (--lipsync-only <número>, ×2). De lo contrario, el video debe doblarse nuevamente (--lipsync, ×3) — confirma antes de redoblar.

Reglas:

  • Repetir el sincronizado de labios en el mismo proyecto factura nuevamente (sin deduplicación del lado del servidor). Si esta sesión ya lo sincronizó, señala el archivo existente y vuelve a ejecutar solo con confirmación explícita.
  • Si el sincronizado de labios falla, el worker guarda el video doblado en su lugar y lo dice en el informe final — transmite eso claramente; los créditos de doblaje no se desperdician.
  • Créditos agotados entre el doblaje y el sincronizado de labios: los videos doblados se guardan y continuar solo termina el sincronizado de labios — transmite la URL de recarga, y continúa a través de la ruta [resume-state] una vez pagado (ver Interrupción y reanudación).

Orador (solo proyectos de doblaje)

Para asignar un nuevo orador a una o más oraciones de un proyecto ya doblado, ejecuta:

node scripts/speaker.mjs "<URL del proyecto|projectSeq>" --at "5s,22s,98s" (códigos de tiempo/ rangos separados por comas) node scripts/speaker.mjs "<URL del proyecto|projectSeq>" --text "primera línea|segunda línea" (texto entrecomillado separado por tuberías) node scripts/speaker.mjs "<URL del proyecto|projectSeq>" --sentence 1234,1288 (vuelve a ejecutar después de una pregunta [sentence-select]) node scripts/speaker.mjs "<URL del proyecto|projectSeq>" --list (navega las oraciones del proyecto para encontrar el objetivo correcto)

Solo proyectos de doblaje — el worker rechaza proyectos de subtítulos (STT), separación de audio y sincronizado de labios, y proyectos no terminados/fallidos. Determina el espacio de trabajo por sí mismo a partir del enlace del proyecto; no necesitas preguntar qué espacio.

Una pausa no es un fallo. Una línea [sentence-select] significa que el worker no pudo identificar un único objetivo (no se dio nada, no coincidió nada, o coincidió más de una oración) — sale limpiamente para preguntarte algo, no porque haya fallado. La lista numerada debajo (índice, etiqueta de tiempo, texto) es segura de transmitir al usuario tal cual. Inmediatamente después de esa lista, una línea [sentence-ref] imprime un mapa JSON de los mismos números a los números internos de oración del worker — esa línea es solo para tu propia consulta: nunca la muestres ni la leas en voz alta. Una vez que el usuario elija un número, búscalo en ese mapa y vuelve a ejecutar el mismo comando con --sentence establecido en ese valor. Un bloque [speaker-resolve] junto a él significa que algunos objetivos ya se resolvieron pero aún no se escribió nada — tiene su propia lista numerada y su propia línea [sentence-ref]; la lista --sentence de la nueva ejecución debe incluir tanto esos valores ya resueltos como el/los recién elegido(s), o los resueltos se perderían. Cuando una ejecución imprime más de un grupo [sentence-select] (varios objetivos ambiguos a la vez), cada grupo

…

[truncado para traducción]

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills relacionados