CaptionPipe
Una llamada incrusta subtítulos en tu video. Alojado, prepagado, sin suscripción. MP4 más SRT y VTT.
Servidor MCP alojado
npx add-mcp 'https://api.captionpipe.com/mcp'Se instala en Claude Code, Codex, Cursor y más
Documentación
Conecta y luego subtitula.
Elige la herramienta en la que estás trabajando. Los clientes interactivos inician sesión a través del navegador; las herramientas de automatización usan una clave del panel de control. De cualquier manera, son las mismas cuatro herramientas, y un video en una URL es una sola llamada.
MCP
https://api.captionpipe.com/mcp
REST
https://api.captionpipe.com/v1
Claude Code
Inicia sesión, o usa una clave
Un solo comando añade el servidor. Inicia sesión una vez y estará disponible en todos tus proyectos.
- 1
Añade el servidor e inicia sesión
claude mcp add --transport http captionpipe https://api.captionpipe.com/mcp claude > /mcp # choose captionpipe, finish sign-in in the browser - 2
Pregunta
Caption https://cdn.acme.com/clip.mp4 with the highlight preset. Get "Acme" and "SK-7" spelled right, and give me the MP4 and the SRT.
Un archivo en tu máquina
Proporciona la ruta. Claude Code llama a create_upload, envía los bytes y luego caption_video. Tú no haces nada de eso manualmente.
Otras formas de acceso
En lugar del comando del paso 1
O haz commit en el repositorio
Claude Code omite una entrada remota sin tipo y advierte que necesita uno. La mayoría de los fragmentos en línea lo omiten.
{
"mcpServers": {
"captionpipe": { "type": "http", "url": "https://api.captionpipe.com/mcp" }
}
}
En lugar de iniciar sesión
Con una clave API en su lugar
Crea una clave en el panel de control en la sección Conectar. Se muestra una sola vez.
claude mcp add --transport http captionpipe https://api.captionpipe.com/mcp \
--header "Authorization: Bearer $CAPTIONPIPE_API_KEY"
Verificado con Claude Code 2.1.263 el 8 de septiembre de 2026.
Herramientas
Las cuatro herramientas
Las rutas REST son /v1/create_upload, /v1/caption_video, /v1/jobs/{id} y /v1/render_captions. Las herramientas MCP aceptan el mismo JSON como argumentos.
create_upload{ contentLength?, sha256?, idempotencyKey? }
→ { jobId, uploadUrl, expiresAt }
Solo para un archivo en tu lado. Devuelve una URL de solo PUT para un objeto, válida por una hora. Declara contentLength si conoces el tamaño en bytes y la URL está vinculada a él; si lo omites, el límite de 2 GB se verifica cuando se ejecuta caption_video. El objeto se sella cuando se ejecuta caption_video. Si tu video ya está en una URL, omite esta herramienta por completo.
caption_video{ jobId | inputUrl, preset, highlightColor?, dictionary?, language?, idempotencyKey? }
→ { jobId, status: "probing" }
Exactamente una fuente: el jobId de create_upload, o un enlace directo a un archivo de video. Las páginas de plataformas como YouTube o TikTok son rechazadas. preset es highlight, clean o boxed. dictionary admite hasta 1,000 términos de hasta seis palabras cada uno, retenidos para este trabajo y eliminados con sus archivos. language es auto o una etiqueta BCP-47. highlightColor es un RGB hexadecimal para la palabra hablada y se aplica solo al preset highlight; el valor predeterminado es el acento de CaptionPipe.
get_caption_job{ jobId }
→ el trabajo, con artefactos una vez completado
Haz polling. retryAfterSeconds te indica cuándo volver mientras el trabajo está en ejecución. Una vez completado, los artefactos son enlaces firmados válidos hasta expiresAt, 24 horas después de la finalización; después de eso, el trabajo responde job_not_found. Después de una llamada a render_captions, render indica qué versión se solicitó y si aún se está renderizando, está completada o falló; los enlaces siempre pertenecen a la versión finalizada más reciente. Cada respuesta incluye tu saldo, para que un agente nunca descubra un saldo vacío al encontrar un error.
render_captions{ jobId, words, preset?, highlightColor?, idempotencyKey? }
→ el trabajo, con render.status accepted
Envía el words.json editado y volvemos a grabar el video exactamente con esas palabras. No se ejecuta ningún modelo de voz. Opcionalmente cambia el preset o el color de resaltado. Gratis, 3 veces por trabajo en una cuenta de pago y 1 en la de prueba, dentro de las 24 horas posteriores a la finalización; la ventana y los archivos expiran juntos. Haz polling a get_caption_job hasta que render.status sea completed, cuando los enlaces cambien a la nueva versión. Sin idempotencyKey, cada llamada usa un re-render del cupo.
Estado
Estado del trabajo
Una sola forma de respuesta en todas partes: MCP, REST y el panel de control leen el mismo objeto.
upload_pending
create_upload emitió una URL; los bytes aún no han llegado.
probing
Estamos verificando que sea un video dentro de los límites. Aún no se cobra nada.
reserved
Duración conocida; los segundos están retenidos en tu saldo y el habla está a punto de comenzar.
processing
Habla y grabación. retryAfterSeconds indica cuándo hacer polling nuevamente.
completed
Los artefactos están listos. chargedSeconds es definitivo y nunca supera la retención.
failed
Un error tipificado. La retención se libera y no se cobra nada.
{
"jobId": "job_9f2",
"status": "completed",
"preset": "highlight",
"durationSeconds": 42,
"chargedSeconds": 42,
"retryAfterSeconds": null,
"balance": {
"remainingSeconds": 258,
"trialRemainingSeconds": 0,
"paidRemainingSeconds": 258,
"reservedSeconds": 0,
"topUpUrl": null
},
"balanceWarning": null,
"rerendersRemaining": 3,
"dictionaryCapacityApplied": 1000,
"artifacts": {
"mp4": { "url": "https://...", "expiresAt": "2026-09-04T12:00:00Z" },
"srt": { "url": "https://...", "expiresAt": "..." },
"vtt": { "url": "https://...", "expiresAt": "..." },
"ass": { "url": "https://...", "expiresAt": "..." },
"wordsJson": { "url": "https://...", "expiresAt": "..." }
},
"expiresAt": "2026-09-04T12:00:00Z",
"error": null,
"render": null
}
Errores
Errores
Un solo formato, un código legible por máquina y un mensaje escrito para ser la solución. Ningún error se cobra: la retención, si la hubo, se devuelve.
{
"ok": false,
"error": {
"code": "insufficient_balance",
"message": "This video needs 0:42 and 0:18 is available. No job was started.",
"retryable": false,
"details": { "requiredSeconds": 42, "remainingSeconds": 18 }
},
"balance": { "remainingSeconds": 18, "reservedSeconds": 0, "topUpUrl": "https://..." }
}
| Código | Cuándo | Reintentar | Haz esto |
|---|---|---|---|
| unauthenticated | Falta la clave o el token, o son inválidos. HTTP 401. | No | Verifica el encabezado Authorization, o inicia sesión nuevamente en tu cliente. |
| job_not_found | jobId desconocido, o uno que pertenece a otra cuenta. | No | Usa el jobId de la respuesta que lo creó. |
| invalid_source | Ambos o ninguno de jobId e inputUrl. | No | Envía exactamente uno. |
| invalid_request | Argumentos mal formados, o un diccionario o lista de palabras con la forma incorrecta. | No | El mensaje indica el campo. |
| upload_incomplete | Se llamó a caption_video antes de que el PUT terminara. | Sí | Termina la subida y vuelve a llamar con el mismo jobId. |
| upload_url_expired | PUT intentado después de la ventana de una hora. | No | Llama a create_upload nuevamente para obtener una URL nueva. |
| checksum_mismatch | Enviaste un sha256 y los bytes subidos no coinciden. | No | Sube el archivo nuevamente u omite el hash. |
| file_size_limit_exceeded | Más de 2 GB, en create_upload o a mitad de transmisión. | No | Comprime o divide el archivo. |
| invalid_media | El archivo no pudo leerse como video con audio utilizable. | No | Verifica que se reproduzca y tenga audio, luego envíalo nuevamente. |
| probe_failed | El archivo no pudo inspeccionarse. | No | Re-codifica a H.264 en MP4 e inténtalo de nuevo. |
| unsupported_ratio | Cuadrado o una relación de aspecto inusual. | No | Usa un video 9:16 o 16:9. Los detalles incluyen ancho y alto. |
| unsupported_input | Códec no compatible, o velocidad de fotogramas por encima del límite. | No | Re-codifica a H.264 a 60 fps o menos. |
| duration_limit_exceeded | Más de 30 minutos. | No | Recorta el video. |
| trial_duration_limit_exceeded | Más de 3 minutos en una cuenta de prueba. | No | Usa un video más corto, o compra minutos para subtitular hasta 30:00. |
| insufficient_balance | El video cuesta más segundos de los que tienes. Se verifica después de la prueba, antes de cualquier habla. | Después de recargar | topUpUrl en la respuesta va directo al pago. |
| trial_concurrency_limit | Un segundo trabajo mientras un trabajo de prueba está en ejecución. | Sí | Espera al trabajo en ejecución. |
| concurrency_limit | Más de 3 de tus trabajos en ejecución, o el servicio está a plena capacidad. | Sí | Espera a que un trabajo termine y reintenta. |
| unsupported_source_url | Una página de plataforma en lugar de un archivo de video, contenido que no es video, o una dirección a la que nunca nos conectamos (privada, local, metadatos). | No | Pasa una URL https pública directa al archivo multimedia, o sube el archivo. |
| url_fetch_failed | El host no resolvió, no conectó o no respondió 200; demasiado lento para comenzar o terminar; demasiadas redirecciones. | Cuando sea transitorio | Verifica que la URL sirva el archivo directamente, o súbelo. |
| rerenders_exhausted | render_captions más allá del cupo. | No | Inicia un nuevo trabajo. |
| rerender_window_expired | render_captions más de 24 horas después de la finalización. | No | Inicia un nuevo trabajo. |
| processing_unavailable | Ambos proveedores de voz están caídos, o un trabajo no pudo enviarse. | Sí | Si la llamada fue rechazada, reinténtala con el mismo idempotencyKey después de retryAfterSeconds. Si un trabajo volvió como fallido, envíalo nuevamente con uno nuevo. |
Límites
Límites
Cada uno de estos se verifica antes de que se te cobre, así que un archivo que no podemos aceptar no te cuesta nada.
Duración
Hasta 30 minutos
Tamaño
Hasta 2 GB de entrada
Salida
1080p H.264, máximo 60 fps
Formato
Vertical primero. 16:9 compatible. El cuadrado se rechaza antes de que se te cobre
Archivos
Disponibles durante 24 horas después de que un trabajo termina
Por llamada
Un video
Facturación
Facturación y reembolsos
- Cada trabajo se cobra por el segundo completo de la duración del video, redondeado hacia arriba, contra un saldo prepagado.
- Los segundos de prueba se consumen antes que los de pago. Un trabajo puede abarcar ambos.
- Cuando un trabajo comienza, retenemos los segundos probados; el panel muestra la retención como reservado. Al completarse, la retención se convierte en el cargo, nunca más. Si falla, la retención se devuelve.
- $10 compran 250 minutos, de 1 a 10 bloques por pago. Sin suscripción, nada se renueva, los minutos pagados nunca expiran.
- Cada respuesta incluye balance.topUpUrl. Es null hasta que estés bajo o bloqueado, luego es un enlace de pago que un agente puede entregarte.
- Los minutos pagados no utilizados son reembolsables a solicitud, netos de la comisión de tarjeta que Stripe retiene. La prueba no lo es.
Solución de problemas
Solución de problemas
El trabajo permanece en probing o processing
Haz polling a get_caption_job y respeta retryAfterSeconds. Un trabajo que no puede completarse falla en minutos con la retención devuelta; nunca queda atascado para siempre.
El enlace del artefacto devuelve 403
Los enlaces expiran 24 horas después de la finalización, y también los archivos. Inicia un nuevo trabajo.
Mi cliente no lista herramientas
Recarga o reinicia el cliente después de editar su configuración, y verifica la forma de configuración para ese cliente arriba. Los bloques de Cursor y VS Code no son intercambiables.
El inicio de sesión se abre pero el cliente nunca conecta
Completa el paso del navegador en la misma máquina donde se ejecuta el cliente. Si aún falla, crea una clave API en el panel y usa la forma de clave de la configuración.
Un nombre está mal escrito
Envíalo en dictionary la próxima vez. Para este trabajo, edita words.json y llama a render_captions; el re-render es gratuito.
La respuesta dice dictionaryCapacityApplied: 0
Nuestro proveedor de voz principal no estaba disponible y la alternativa se ejecutó sin el diccionario. Re-renderiza con las palabras corregidas, o vuelve a ejecutar el trabajo más tarde.