CaptionPipe
Uma chamada grava legendas no seu vídeo. Hospedado, pré-pago, sem assinatura. MP4 mais SRT e VTT.
Servidor MCP hospedado
npx add-mcp 'https://api.captionpipe.com/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
Conecte-se e depois legendas.
Escolha a ferramenta em que você está. Clientes interativos entram pelo navegador; ferramentas de automação usam uma chave do painel. De qualquer forma, são as mesmas quatro ferramentas, e um vídeo em uma URL é uma única chamada.
MCP
https://api.captionpipe.com/mcp
REST
https://api.captionpipe.com/v1
Claude Code
Entre, ou use uma chave
Um comando adiciona o servidor. Entre uma vez e ele estará disponível em todos os seus projetos.
- 1
Adicione o servidor e entre
claude mcp add --transport http captionpipe https://api.captionpipe.com/mcp claude > /mcp # choose captionpipe, finish sign-in in the browser - 2
Pergunte
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.
Um arquivo na sua máquina
Forneça o caminho. O Claude Code chama create_upload, envia os bytes e depois caption_video. Você não faz nada disso manualmente.
Outras formas de acesso
Em vez do comando no passo 1
Ou adicione-o ao repositório
O Claude Code ignora uma entrada remota sem tipo e avisa que ela precisa de um. A maioria dos trechos online omite isso.
{
"mcpServers": {
"captionpipe": { "type": "http", "url": "https://api.captionpipe.com/mcp" }
}
}
Em vez de entrar
Com uma chave de API
Crie uma chave no painel em Conectar. Ela é exibida apenas uma vez.
claude mcp add --transport http captionpipe https://api.captionpipe.com/mcp \
--header "Authorization: Bearer $CAPTIONPIPE_API_KEY"
Verificado com Claude Code 2.1.263 em 8 de setembro de 2026.
Ferramentas
As quatro ferramentas
Os caminhos REST são /v1/create_upload, /v1/caption_video, /v1/jobs/{id} e /v1/render_captions. As ferramentas MCP aceitam o mesmo JSON como argumentos.
create_upload{ contentLength?, sha256?, idempotencyKey? }
→ { jobId, uploadUrl, expiresAt }
Apenas para um arquivo do seu lado. Retorna uma URL somente-PUT para um objeto, válida por uma hora. Declare contentLength se você souber o tamanho em bytes e a URL estiver vinculada a ele; omita-o e o limite de 2 GB será verificado quando caption_video for executado. O objeto é selado quando caption_video é executado. Se o seu vídeo já estiver em uma URL, pule esta ferramenta completamente.
caption_video{ jobId | inputUrl, preset, highlightColor?, dictionary?, language?, idempotencyKey? }
→ { jobId, status: "probing" }
Exatamente uma fonte: o jobId de create_upload ou um link direto para um arquivo de vídeo. Páginas de plataformas como YouTube ou TikTok são recusadas. preset é highlight, clean ou boxed. dictionary tem até 1.000 termos de até seis palavras cada, mantidos para este job e excluídos com seus arquivos. language é auto ou uma tag BCP-47. highlightColor é um RGB hexadecimal para a palavra falada e se aplica apenas ao preset highlight; o padrão é o accent do CaptionPipe.
get_caption_job{ jobId }
→ o job, com artefatos uma vez concluído
Faça polling. retryAfterSeconds informa quando voltar enquanto o job está em execução. Uma vez concluído, os artefatos são links assinados válidos até expiresAt, 24 horas após a conclusão; depois disso, o job responde job_not_found. Após uma chamada render_captions, render informa qual versão foi solicitada e se ainda está renderizando, concluída ou falhou; os links sempre pertencem à versão finalizada mais recente. Cada resposta carrega seu saldo, para que um agente nunca descubra um saldo vazio ao encontrar um erro.
render_captions{ jobId, words, preset?, highlightColor?, idempotencyKey? }
→ o job, com render.status aceito
Envie o words.json editado e queimamos o vídeo novamente exatamente com essas palavras. Nenhum modelo de fala é executado. Opcionalmente, altere o preset ou a cor de destaque. Grátis, 3 vezes por job em conta paga e 1 na conta de teste, dentro de 24 horas após a conclusão; a janela e os arquivos expiram juntos. Faça polling de get_caption_job até render.status ser completed, quando os links mudam para a nova versão. Sem um idempotencyKey, cada chamada usa um re-render da cota.
Status
Status do job
Um formato de resposta em todos os lugares: MCP, REST e o painel leem o mesmo objeto.
upload_pending
create_upload emitiu uma URL; os bytes ainda não chegaram.
probing
Estamos verificando se é um vídeo dentro dos limites. Nada é cobrado ainda.
reserved
Duração conhecida; os segundos são retidos no seu saldo e a fala está prestes a começar.
processing
Fala e queima. retryAfterSeconds informa quando fazer polling novamente.
completed
Artefatos prontos. chargedSeconds é final e nunca excede a retenção.
failed
Um erro tipado. A retenção é liberada e nada é cobrado.
{
"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
}
Erros
Erros
Um envelope, um código legível por máquina e uma mensagem escrita para ser a solução. Nenhum erro é cobrado: a retenção, se houve, é devolvida.
{
"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 | Quando | Repetir | O que fazer |
|---|---|---|---|
| unauthenticated | Chave ou token ausente ou inválido. HTTP 401. | Não | Verifique o cabeçalho Authorization ou entre novamente no seu cliente. |
| job_not_found | jobId desconhecido ou pertencente a outra conta. | Não | Use o jobId da resposta que o criou. |
| invalid_source | Ambos ou nenhum de jobId e inputUrl. | Não | Envie exatamente um. |
| invalid_request | Argumentos malformados, ou um dicionário ou lista de palavras com formato incorreto. | Não | A mensagem nomeia o campo. |
| upload_incomplete | caption_video chamado antes do PUT terminar. | Sim | Conclua o upload e chame novamente com o mesmo jobId. |
| upload_url_expired | PUT tentado após a janela de uma hora. | Não | Chame create_upload novamente para uma URL nova. |
| checksum_mismatch | Você enviou um sha256 e os bytes enviados não correspondem. | Não | Envie o arquivo novamente ou omita o hash. |
| file_size_limit_exceeded | Acima de 2 GB, em create_upload ou no meio do fluxo. | Não | Comprima ou divida o arquivo. |
| invalid_media | O arquivo não pôde ser lido como vídeo com áudio utilizável. | Não | Verifique se ele reproduz e tem áudio e envie novamente. |
| probe_failed | O arquivo não pôde ser inspecionado. | Não | Reencode para H.264 em MP4 e tente novamente. |
| unsupported_ratio | Quadrado ou proporção incomum. | Não | Use um vídeo 9:16 ou 16:9. Os detalhes trazem largura e altura. |
| unsupported_input | Codec não suportado ou taxa de quadros acima do limite. | Não | Reencode para H.264 a 60 fps ou menos. |
| duration_limit_exceeded | Acima de 30 minutos. | Não | Corte o vídeo. |
| trial_duration_limit_exceeded | Acima de 3 minutos em conta de teste. | Não | Use um vídeo mais curto ou compre minutos para legendar até 30:00. |
| insufficient_balance | O vídeo custa mais segundos do que você tem. Verificado após a sondagem, antes de qualquer fala. | Após recarga | topUpUrl na resposta leva direto ao checkout. |
| trial_concurrency_limit | Um segundo job enquanto um job de teste está em execução. | Sim | Aguarde o job em execução. |
| concurrency_limit | Mais de 3 dos seus jobs em execução, ou o serviço está na capacidade máxima. | Sim | Aguarde um job terminar e repita. |
| unsupported_source_url | Uma página de plataforma em vez de um arquivo de vídeo, conteúdo que não é vídeo, ou um endereço ao qual nunca nos conectamos (privado, local, metadados). | Não | Passe uma URL https pública direta para o arquivo de mídia ou envie o arquivo. |
| url_fetch_failed | O host não resolveu, conectou ou respondeu 200; muito lento para iniciar ou terminar; muitos redirecionamentos. | Quando transitório | Verifique se a URL serve o arquivo diretamente ou envie-o. |
| rerenders_exhausted | render_captions além da cota. | Não | Inicie um novo job. |
| rerender_window_expired | render_captions mais de 24 horas após a conclusão. | Não | Inicie um novo job. |
| processing_unavailable | Ambos os fornecedores de fala estão fora do ar, ou um job não pôde ser despachado. | Sim | Se a chamada foi recusada, repita-a com o mesmo idempotencyKey após retryAfterSeconds. Se um job retornou failed, envie-o novamente com um novo. |
Limites
Limites
Cada um destes é verificado antes de você ser cobrado, então um arquivo que não podemos aceitar não custa nada.
Duração
Até 30 minutos
Tamanho
Até 2 GB
Saída
1080p H.264, teto de 60 fps
Formato
Retrato primeiro. 16:9 suportado. Quadrado é recusado antes de você ser cobrado
Arquivos
Disponíveis por 24 horas após o job terminar
Por chamada
Um vídeo
Cobrança
Cobrança e reembolsos
- Cada job é cobrado pelo segundo inteiro da duração do vídeo, arredondado para cima, contra um saldo pré-pago.
- Segundos de teste são usados antes dos segundos pagos. Um job pode abranger ambos.
- Quando um job começa, retemos os segundos sondados; o painel mostra a retenção como reservado. Na conclusão, a retenção vira a cobrança, nunca mais. Na falha, a retenção é devolvida.
- $10 compram 250 minutos, blocos de 1 a 10 por checkout. Sem assinatura, nada renova, minutos pagos nunca expiram.
- Cada resposta carrega balance.topUpUrl. É null até você estar com saldo baixo ou bloqueado; então é um link de checkout que um agente pode entregar a você.
- Minutos pagos não utilizados são reembolsáveis mediante solicitação, líquidos da taxa de cartão que a Stripe retém. O teste não é.
Solução de problemas
Solução de problemas
O job fica em probing ou processing
Faça polling de get_caption_job e respeite retryAfterSeconds. Um job que não pode ser concluído falha em minutos com a retenção devolvida; ele nunca fica preso para sempre.
O link do artefato retorna 403
Os links expiram 24 horas após a conclusão, e os arquivos também. Inicie um novo job.
Meu cliente não lista ferramentas
Recarregue ou reinicie o cliente após editar sua configuração e verifique o formato da configuração para esse cliente acima. Blocos do Cursor e do VS Code não são intercambiáveis.
O login abre, mas o cliente nunca conecta
Conclua a etapa do navegador na mesma máquina em que o cliente roda. Se ainda falhar, crie uma chave de API no painel e use o formato de chave da configuração.
Um nome está escrito errado
Envie-o no dicionário da próxima vez. Para este job, edite words.json e chame render_captions; o re-render é grátis.
A resposta diz dictionaryCapacityApplied: 0
Nosso fornecedor principal de fala estava indisponível e o fallback rodou sem o dicionário. Re-renderize com as palavras corrigidas ou execute o job novamente mais tarde.