RapidVideoMaker
Criar uma conta

API RapidVideoMaker

A API REST permite processar arquivos de vídeo de qualquer cliente HTTP — scripts Python, fluxos n8n, ferramentas de terceiros. Cinco modos disponíveis: Mesclar vídeos (vários MP4/MOV), Editar áudio (1 MP4/MOV + 1 MP3), Criar um vídeo (1 JPG/PNG + 1 MP3), Sobreposição de vídeo (2 MP4/MOV picture-in-picture). O processamento é assíncrono: envie os arquivos e consulte o resultado.

Obtenha seu token de API gratuitamente
Crie uma conta para obter seu token de API — 20 solicitações incluídas por dia, utilizáveis pela interface ou API.
Criar uma conta gratuita Já tem conta? Entrar

Fluxo de trabalho completo

Toda integração segue a mesma sequência de 4 etapas:

1
Criar o job — POST /api/v1/render.php
Envie os arquivos como multipart/form-data com seu token Bearer. 1 JPG/PNG + 1 MP3 + mode=image_to_video → geração de vídeo. 1 MP4/MOV + 1 MP3 → edição de áudio (mode=mix_audio para sobrepor). Vários MP4/MOV → mesclar. O servidor retorna um job_id único. Ou 1 imagem + options.text + options.voice: a voz é gerada a partir do texto, sem MP3.
2
Aguardar o job — GET /api/v1/jobs.php?job_id=…
Consulte este endpoint periodicamente (a cada 5–10 seg.). O job avança de queued → processing → ready (ou error). A resposta inclui a posição na fila e o tempo estimado restante.
3
Obter a URL de download
Quando o status é ready, a resposta contém um campo download_url pronto para uso.
4
Baixar o arquivo — GET /api/download.php?job_id=…
Baixe o arquivo MP4/MOV final. O arquivo fica disponível por 2 horas após a conclusão, depois é excluído automaticamente. Após o prazo, a API responde 410 Gone.

Autenticação

Toda requisição deve incluir seu token de API. Dois formatos são aceitos:

# Autenticação — Toda requisição deve incluir seu token de API. Dois formatos são aceitos: Authorization: Bearer rvm_your_token_here # Alternative X-API-Key: rvm_your_token_here

Seu token está disponível em seu espaço de membro — um token por conta, criado automaticamente no cadastro. É mostrado em texto claro apenas uma vez — guarde-o com segurança. Se perdido, pode ser regerado no espaço de membro.

Cota

Cada conta tem 20 requisições por dia, compartilhadas entre interface web e API. Jobs com falha não consomem cota. O contador reinicia à meia-noite UTC.

As respostas POST incluem quota_used e quota_remaining. Quando o limite é excedido, o servidor responde 429.

Interface + API = mesmo contador. Um vídeo criado pela interface e uma requisição de API consomem 1 crédito cada um da mesma cota diária.

Fila

Um job é processado por vez. Se vários jobs forem enviados simultaneamente, são enfileirados em ordem de chegada. Enquanto aguarda, a resposta de status inclui:

Rate limit aplicado: o endpoint /api/v1/jobs.php aceita no máximo 12 chamadas por minuto por token. Além disso, responde 429 com Retry-After: 5. Recomendação: 10 segundos entre chamadas.

Transições disponíveis

Passe transition_type=none (padrão) para mesclagem direta, ou um dos tipos abaixo para uma transição entre clipes:

none fade fadeblack dissolve wipeleft wiperight slideleft slideright zoomin circleclose

A duração (transition_duration) é entre 0,2 e 2,0 segundos. Se um clipe é muito curto, a transição é ignorada.

Endpoints

POST /api/v1/render.php Cria um job de processamento de vídeo

Cinco modos, acessíveis pelo campo mode (omita mode com vários MP4 para detectar automaticamente fusion):

UsoModo APIArquivos necessáriosDescrição
Mesclar vídeos fusion 2–20 arquivos MP4/MOV Os clipes são montados em sequência na ordem fornecida. Transições opcionais entre clipes.
Editar áudio add_audio ou mix_audio 1 MP4/MOV + 1 MP3 Substitui ou enriquece a faixa de áudio de um vídeo. A faixa de vídeo nunca é recodificada (-c:v copy).

add_audio — o áudio original é excluído e substituído pelo MP3.
mix_audio — o áudio original é mantido e o MP3 é sobreposto (amix). options={"mp3_volume":…} para ajustar o volume.
Criar um vídeo image_to_video 1 JPG/PNG + 1 MP3 — ou 1 JPG/PNG + um texto (options.text + options.voice): a voz é gerada Gera um vídeo a partir de uma imagem fixa e do seu MP3 — ou de um simples texto (options.text) cuja voz é gerada (options.voice). Texto sobreposto (fixo, palavra por palavra ou karaokê), fades, resolução e fps configuráveis pelo campo options.
Sobreposição de vídeo overlay_video 2 MP4/MOV Sobrepõe um segundo vídeo ao vídeo principal. Posição, tamanho, opacidade e áudio configuráveis via o campo options.
Adicionar texto add_text 1 MP4/MOV Sobrepõe texto a um vídeo existente (resolução, taxa de quadros e áudio são preservados). Mesmas configurações de texto do image_to_video, mais o momento em que o texto aparece. options.text é obrigatório.
Texto para MP3 text_to_mp3 (somente texto) Converte texto em fala e retorna um arquivo MP3. Nenhum upload de arquivo necessário — envie mode=text_to_mp3, text e lang como campos de formulário. Suporta todos os 20 idiomas do site.
Validação estrita: cada modo requer um número e tipos exatos de arquivos. add_audio e mix_audio aceitam apenas 1 MP4/MOV + 1 MP3. image_to_video apenas 1 JPG/PNG + 1 MP3. Os tipos MIME são verificados por magic bytes. Exceção: com options.text + options.voice, image_to_video aceita 1 imagem sozinha — a voz é gerada a partir do texto (sem MP3).
Regra de duração: nos modos de áudio e image_to_video, a duração do resultado é igual à duração do MP3. A faixa de vídeo nunca é recodificada (-c:v copy). Com options.voice, image_to_video dura o tempo da voz gerada a partir do texto (+0,6 s).

Parâmetros comuns (multipart/form-data)

CampoTipoObr.Descrição
videos[]File[]SIMArquivos a processar. Dependendo do modo: 2–20 MP4/MOV, ou 1 MP4/MOV + 1 MP3, ou 1 imagem (JPG/PNG) + 1 MP3. Máx. 500 MB por arquivo.
modestring*image_to_video | add_audio | mix_audio | overlay_video | text_to_mp3. Obrigatório para esses modos não-fusion. Omitir mode com apenas arquivos MP4/MOV sempre aciona fusion (concatenação por cópia de stream) — nunca overlay_video, mesmo com exatamente 2 MP4/MOV. Para edição de áudio: add_audio remove o original, mix_audio o mantém e sobrepõe. Se o campo mode for fornecido, os arquivos enviados devem corresponder exatamente — caso contrário a requisição é rejeitada. add_text também é aceito: é o único modo que recebe um único arquivo MP4/MOV e exige options.text.
orderJSONApenas modo fusion — array JSON de índices para a ordem dos clipes.
transition_typestringApenas modo fusion. Padrão: none. Veja lista de transições disponíveis.
transition_durationfloatApenas modo fusion. Duração 0,2–2,0 seg. Padrão: 0.5.
optionsJSONObjeto JSON de parâmetros de renderização para image_to_video, add_text, mix_audio e overlay_video (veja as tabelas abaixo).
timingsFile / stringimage_to_video / add_text: arquivo de tempos do karaokê (SRT ou LRC, 200 KB máx.) — campo de arquivo ou texto puro. O texto exibido vem do arquivo; impõe text_mode=karaoke; não é compatível com voice.
callback_urlstringURL pública (http/https) chamada ao concluir o job. A resposta inclui um webhook_secret.

Parâmetros options — modo image_to_video

Todos opcionais. Valores não fornecidos → padrões do worker.

ChaveTipoPadrãoDescrição
textstring""Texto exibido como sobreposição. Vazio = sem texto. Máx. 500 caracteres.
fontstring"default"Fonte do texto, por identificador. Valores aceitos: default, dejavu-sans-bold, dejavu-serif, liberation-serif, dejavu-mono, amiri, noto-sans-sc (简体中文), noto-sans-tc (繁體中文), noto-sans-jp (日本語), noto-sans-kr (한국어), noto-sans-hebrew (עברית), noto-sans-thai (ไทย). default = fonte padrão (com suporte a emoji); amiri = fonte Naskh, ideal para texto em árabe. Qualquer outro valor retorna o erro invalid_option. Os emoji só são exibidos com default.
font_sizeint60Tamanho da fonte em pixels. Intervalo: 10–300. Recomendados: 36, 48, 60, 72, 96.
text_colorstring"white"Cor do texto (ex. white, yellow, #ffffff, 0xffffff).
text_positionstring"center"Posição do texto: center, top, bottom.
boxbooltrueFundo semi-transparente atrás do texto.
box_colorstring"black@0.4"Cor + opacidade no formato FFmpeg: cor@opacidade. Opacidade: 0,0–1,0 (ex. black@0.4 = preto a 40%).
fade_durationfloat0.5Duração do fade in/out em segundos (0–2). 0 = sem fade.
widthint1080Largura do vídeo em pixels (64–3840, par forçado). Padrão: 1080/1920/720/1280.
heightint1920Altura do vídeo em pixels (64–3840, par forçado).
fpsint24Frame rate (1–60).
image_fitstring"contain"contain: Mostra a imagem ou o vídeo inteiro e preenche as áreas vazias com o fundo escolhido. solid (padrão) ou blur. O desfoque exige image_fit=contain. O texto permanece nítido. cover: A imagem é ampliada para preencher o quadro, centralizada — as bordas são cortadas.
bg_colorstring"black"background_mode=solid: Cor de fundo se a imagem não preencher a resolução — apenas com image_fit=contain (ex. black, white, #1a1a2e).
background_modestring"solid"solid (padrão) ou blur. O desfoque exige image_fit=contain. O texto permanece nítido.
blur_strengthnumber20Número de 1 a 50; padrão 20. Intensidade do desfoque gaussiano apenas no fundo.
enable_image_motionboolfalseAtiva a animação de foto. Se false, a imagem fica estática. Se true, aplica o efeito de image_motion_effect via FFmpeg zoompan.
image_motion_effectstring"ken_burns"Efeito de animação. Valores: zoom_in, zoom_out, pan_left_to_right, pan_right_to_left, pan_top_to_bottom, pan_bottom_to_top, zoom_pan_soft, ken_burns. Padrão: ken_burns.
motion_intensityfloat1.0Intensidade da animação de foto (0,25–2,0). Multiplica amplitude do zoom e velocidade do pan.
text_effectstring"none"Animação do texto. Valores: none, fade_in, slide_up, slide_down, slide_left, bounce.
text_effect_intensityfloat1.0Intensidade da animação de texto (0,25–2,0).
text_border_widthint0Espessura do contorno preto em pixels (0 = desativado, 1–10). Melhora a legibilidade.
text_border_colorstring"black"Cor do contorno dos caracteres (mesmo formato de text_color, padrão "black"). Usada se text_border_width > 0.
text_modestring"static"Modo de revelação do texto. static (padrão): texto completo visível desde o primeiro quadro. word_by_word: palavras aparecem uma por uma no ritmo de word_reveal_speed. Exclusivo com text_effect: se text_mode=word_by_word, text_effect é ignorado. "karaoke": o texto muda de cor no ritmo do áudio, página por página (até 1.000 caracteres). Sincronizado palavra por palavra com voice; caso contrário, distribuído sobre o áudio conforme o tamanho das palavras.
word_reveal_speedfloat1.5Velocidade de revelação em palavras por segundo (0.3–5.0, padrão 1.5). Somente com text_mode=word_by_word. Valor recomendado para sincronização com voz OpenAI TTS: 2.0.
word_animstring"none"Animação de aparição de cada palavra. none (padrão): revelação instantânea. fade: cada nova palavra aparece com um fade de 0.2s e crossfade com o bloco anterior. Usado apenas com text_mode=word_by_word.
karaoke_stylestring"fill"Estilo do karaokê: fill (as palavras faladas recebem a cor de destaque), sweep (cada palavra é preenchida progressivamente; palavras inteiras em escritas da direita para a esquerda) ou highlight (somente a palavra atual é colorida).
highlight_colorstring"#FFD200"Cor das palavras faladas / da palavra atual no modo karaokê (mesmo formato de text_color).
karaoke_linesint2Linhas exibidas por página no modo karaokê (1–4).
voicestring""ID da voz (mesma lista de text_to_mp3, ex.: pt-BR-FranciscaNeural): a voz é gerada a partir de text no mesmo job. image_to_video passa a precisar apenas da imagem (um MP3 enviado junto é recusado). No modo karaokê, cada palavra é sincronizada com a voz.
voice_rateint0Velocidade da voz gerada, em % (−50 a +50).

Karaokê com seus próprios tempos (SRT / LRC)

Envie um arquivo SRT ou LRC no campo timings: cada linha aparece no seu momento e forma uma página do karaokê (até 500 linhas, 5.000 caracteres). SRT: a linha some no horário final. LRC: a linha fica até a próxima (uma linha vazia a encerra); [offset:] e os tempos por palavra do LRC «enhanced» <mm:ss.xx> são suportados — caso contrário, cada linha é distribuída pela sua duração. Em add_text, os tempos são relativos ao início do vídeo, deslocados por text_start.

# lyrics.srt 1 00:00:01,000 --> 00:00:03,500 First line of the song 2 00:00:04,000 --> 00:00:07,200 Second line, on its own page # lyrics.lrc — enhanced LRC: optional per-word times <mm:ss.xx> [00:01.00]<00:01.00>First <00:01.60>line <00:02.10>here [00:04.00]Second line [00:07.50]

Parâmetros options — modo overlay_video

Todos opcionais. A ordem de envio importa: o primeiro arquivo é o vídeo principal (fundo), o segundo arquivo é o overlay (primeiro plano). Use chroma_key para remover um fundo verde do overlay.

ChaveTipoPadrãoDescrição
positionstring"bottom-right"Canto onde o overlay é posicionado: top-left, top-right, bottom-left, bottom-right, ou center.
scalefloat0.30Tamanho do overlay como fração da largura do vídeo principal. 0.25 = 25% da largura. Intervalo: 0.05–1.0.
opacityfloat1.0Transparência do overlay. 1.0 = totalmente opaco, 0.0 = invisível.
marginint10Espaço em pixels entre o overlay e a borda. Ignorado se position=center. Intervalo: 0–200.
audiostring"main"Qual áudio manter. main: só o áudio principal. overlay: só o áudio do overlay. mix: ambas as faixas misturadas.
chroma_keyboolfalseDefina como true para remover o fundo verde puro (#00FF00) do overlay — útil para webcam ou animações filmadas em chroma key.
chroma_similarityfloat0.20Tolerância do chroma key. Baixo = correspondência estrita. Alto = remoção mais ampla. Recomendado: 0.10–0.20 para verde digital, 0.25–0.45 para tela física. Intervalo: 0.01–0.60.

Parâmetros de options — modo add_text

O texto é obrigatório. Por padrão, o formato, a taxa de quadros e o áudio são mantidos. output_format ativa o reenquadramento com image_fit, bg_color e background_mode. width, height, fps e o movimento da foto continuam ignorados. Duração máxima: 15 minutos.

{"text":"Hello","output_format":"portrait","image_fit":"contain","background_mode":"blur","blur_strength":20}
ChaveTipoPadrãoDescrição
textstringSIMTexto a sobrepor. Obrigatório, de 1 a 200 caracteres.
text_startfloat0Segundo em que o texto aparece (≥ 0). Deve ser anterior ao final do vídeo.
text_durationfloat0Por quanto tempo o texto fica visível, em segundos (0,1–3600). 0 = até o final do vídeo.
fontstring"default"Fonte do texto, por identificador. Valores aceitos: default, dejavu-sans-bold, dejavu-serif, liberation-serif, dejavu-mono, amiri, noto-sans-sc (简体中文), noto-sans-tc (繁體中文), noto-sans-jp (日本語), noto-sans-kr (한국어), noto-sans-hebrew (עברית), noto-sans-thai (ไทย). default = fonte padrão (com suporte a emoji); amiri = fonte Naskh, ideal para texto em árabe. Qualquer outro valor retorna o erro invalid_option. Os emoji só são exibidos com default.
font_sizeint60Tamanho da fonte, expresso para um vídeo cujo lado menor mede 1080 px e ajustado automaticamente à resolução real — o mesmo valor tem a mesma aparência em 720p e 4K. Faixa: 10–300.
fade_durationfloat0.5Duração do fade de entrada/saída do texto (não do vídeo), em segundos. Faixa: 0–2.
text_color, box, box_color, text_position, text_border_width, text_border_color, text_effect, text_effect_intensity, text_mode, word_reveal_speed, word_anim, karaoke_style, highlight_color, karaoke_lines, voice, voice_rate——Idênticas às do image_to_video (veja a tabela acima).
original_volumefloat0.3Com voice: volume do som original do vídeo sob a voz (0–2, padrão 0.3; 0 = substituído). A voz começa em text_start; o texto permanece na tela até ela terminar e, se ultrapassar o fim do vídeo, a última imagem é mantida.
background_modestring"solid"solid (padrão) ou blur. O desfoque exige image_fit=contain. O texto permanece nítido.
blur_strengthnumber20Número de 1 a 50; padrão 20. Intensidade do desfoque gaussiano apenas no fundo.
output_formatstring"original"Somente add_text: original (padrão), portrait (1080×1920), square (1080×1080), landscape (1920×1080). O desfoque exige um formato diferente de original.
image_fitstring"contain"contain: Mostra a imagem ou o vídeo inteiro e preenche as áreas vazias com o fundo escolhido. solid (padrão) ou blur. O desfoque exige image_fit=contain. O texto permanece nítido. cover: A imagem é ampliada para preencher o quadro, centralizada — as bordas são cortadas.
bg_colorstring"black"background_mode=solid: Cor de fundo se a imagem não preencher a resolução — apenas com image_fit=contain (ex. black, white, #1a1a2e).

Parâmetros options — Editar áudio (mix_audio)

Disponível apenas com mode=mix_audio. Ignorado para add_audio.

ChaveTipoPadrãoDescrição
mp3_volumefloat1.0Volume do MP3 sobreposto (0,0 = mudo, 1,0 = original, 2,0 = dobro). Valores acima de 1,0 podem saturar.

Modo text_to_mp3 — parâmetros diretos (sem JSON options)

Ao contrário dos outros modos, esses campos são enviados diretamente como campos de formulário, não dentro do objeto JSON options. Apenas text é obrigatório.

ChaveTipoPadrãoDescrição
textstring—Texto a converter em voz. Obrigatório. Máximo de 5.000 caracteres.
langstring"en"Código de idioma usado para escolher a voz padrão quando voice é omitido ou inválido. Um dos 20 idiomas do site (ver tabela abaixo). Usa en se desconhecido.
voicestringautomáticoID de voz edge-tts (ver tabela abaixo). Se omitido ou inválido, a primeira voz de lang é usada automaticamente.
slowboolfalseDefina como true (ou 1) para reduzir a velocidade da fala em 25%. Qualquer outro valor é tratado como false.
Não requer upload de arquivo: ao contrário dos outros modos, text_to_mp3 não precisa de videos[]. Envie mode=text_to_mp3 junto com text / lang / voice / slow como campos de formulário normais.

Vozes disponíveis (edge-tts, Microsoft Neural), agrupadas por código de idioma:

IdiomaVozes disponíveis
en en-US-AvaNeural, en-US-AndrewNeural, en-GB-LibbyNeural, en-AU-NatashaNeural, en-AU-WilliamMultilingualNeural
fr fr-FR-DeniseNeural, fr-FR-HenriNeural, fr-FR-EloiseNeural, fr-CA-SylvieNeural, fr-CA-ThierryNeural
es es-ES-ElviraNeural, es-ES-AlvaroNeural, es-MX-DaliaNeural, es-AR-ElenaNeural, es-AR-TomasNeural
ar ar-SA-ZariyahNeural, ar-SA-HamedNeural, ar-EG-SalmaNeural, ar-MA-MounaNeural, ar-MA-JamalNeural
pt pt-BR-FranciscaNeural, pt-BR-AntonioNeural, pt-PT-RaquelNeural
de de-DE-KatjaNeural, de-DE-ConradNeural, de-DE-AmalaNeural, de-AT-IngridNeural, de-AT-JonasNeural
it it-IT-ElsaNeural, it-IT-DiegoNeural, it-IT-IsabellaNeural
nl nl-NL-ColetteNeural, nl-NL-MaartenNeural, nl-BE-DenaNeural, nl-BE-ArnaudNeural
ru ru-RU-SvetlanaNeural, ru-RU-DmitryNeural
tr tr-TR-EmelNeural, tr-TR-AhmetNeural
hi hi-IN-SwaraNeural, hi-IN-MadhurNeural
bn bn-IN-TanishaaNeural, bn-IN-BashkarNeural, bn-BD-NabanitaNeural, bn-BD-PradeepNeural
ur ur-PK-UzmaNeural, ur-PK-AsadNeural, ur-IN-GulNeural, ur-IN-SalmanNeural
id id-ID-GadisNeural, id-ID-ArdiNeural
ja ja-JP-NanamiNeural, ja-JP-KeitaNeural
ko ko-KR-SunHiNeural, ko-KR-InJoonNeural
zh-CN zh-CN-XiaoxiaoNeural, zh-CN-YunxiNeural, zh-CN-XiaoyiNeural
zh-TW zh-TW-HsiaoChenNeural, zh-TW-YunJheNeural
vi vi-VN-HoaiMyNeural, vi-VN-NamMinhNeural
pl pl-PL-ZofiaNeural, pl-PL-MarekNeural

Resposta de sucesso (HTTP 200)

{ "success": true, "job_id": "a3f1c8d2e5b09471...", "mode": "fusion", // "fusion" | "add_audio" | "mix_audio" | "image_to_video" | "overlay_video" | "add_text" | "text_to_mp3" "file_count": 2, "transition": null, "quota_used": 1, "quota_remaining": 9, "status_url": "https://rapidvideomaker.com/api/v1/jobs.php?job_id=a3f1c8..." }
Para text_to_mp3, a resposta não tem os campos file_count nem transition (nenhum arquivo foi enviado) — o resto é idêntico: job_id, quota_used, quota_remaining, status_url, webhook_secret.

Exemplo curl — modo image_to_video

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@scene.jpg" \ -F "videos[]=@narration.mp3" \ -F "mode=image_to_video" \ -F 'options={"text":"Chapter 1","font_size":72,"text_color":"white","text_position":"bottom","box":true,"box_color":"black@0.4","fade_duration":0.5,"width":1080,"height":1920,"image_fit":"contain","bg_color":"black","enable_image_motion":true,"image_motion_effect":"ken_burns","motion_intensity":1.0,"text_effect":"slide_up","text_effect_intensity":1.0}' # image_fit : "contain" | "cover" # background_mode : "solid" | "blur" (blur requires contain) # blur_strength : 1–50, default 20 # bg_color : ignored if image_fit="cover" # enable_image_motion : true = animation on, false (default) = static image # image_motion_effect : zoom_in | zoom_out | pan_left_to_right | pan_right_to_left | pan_top_to_bottom | pan_bottom_to_top | zoom_pan_soft | ken_burns # motion_intensity : 0.25–2.0 — photo animation amplitude (default 1.0) # text_effect : none | fade_in | slide_up | slide_down | slide_left | bounce (ignored if text_mode=word_by_word) # text_effect_intensity : 0.25–2.0 — text animation intensity (default 1.0) # text_border_width : 0–10 px — outline around characters (0 = disabled) # text_border_color : outline color, default "black" (e.g. "#FF3366", "white@0.8") # text_mode : "static" (default) | "word_by_word" — reveal words one by one # word_reveal_speed : 0.3–5.0 w/s — speed for word_by_word mode (default 1.5, ~2.0 for OpenAI TTS) # word_anim : "none" (default) | "fade" — fade-in crossfade on each word (word_by_word only)

Texto karaokê com voz gerada (image_to_video, sem MP3)

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@scene.jpg" \ -F "mode=image_to_video" \ -F 'options={"text":"Every word lights up as the voice reads it.","voice":"en-US-AvaNeural","text_mode":"karaoke","karaoke_style":"sweep","highlight_color":"#FFD200","karaoke_lines":2,"text_position":"bottom","font_size":72}' # no MP3: the voice is generated from "text" and gives the timing of every word # text_mode="karaoke" : text up to 1000 characters, shown page by page (karaoke_lines: 1–4) # karaoke_style : "fill" (default) | "sweep" | "highlight" # voice_rate : -50…+50 (%), default 0 # with your own MP3 (no "voice"): karaoke timing is spread over the audio by word length # add_text: same options + "original_volume" (0–2, default 0.3) = original sound under the voice

Karaokê com um arquivo SRT (image_to_video + seu MP3)

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@cover.jpg" \ -F "videos[]=@song.mp3" \ -F "timings=@lyrics.srt" \ -F "mode=image_to_video" \ -F 'options={"karaoke_style":"sweep","karaoke_lines":2,"text_position":"bottom","font_size":72}' # timings : SRT or LRC file (200 KB max), or its content as a plain text field: -F "timings=<lyrics.lrc" # the displayed text comes from the file ("text" is ignored), text_mode is forced to "karaoke" # not compatible with "voice" (the timings follow your own audio) # add_text: times are relative to the video start, shifted by "text_start"

Exemplo curl — Editar áudio

# Replace audio (deletes original) curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@my_video.mp4" \ -F "videos[]=@my_music.mp3" \ -F "mode=add_audio" # Keep original audio + overlay MP3 curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@my_video.mp4" \ -F "videos[]=@my_music.mp3" \ -F "mode=mix_audio" \ -F 'options={"mp3_volume":0.7}' # mp3_volume : 0.0 (muted) → 1.0 (original volume, default) → 2.0 (amplified)

Exemplo curl — modo overlay_video

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@main_video.mp4" \ -F "videos[]=@overlay_video.mp4" \ -F "mode=overlay_video" \ -F 'options={"position":"bottom-right","scale":0.25,"opacity":1.0,"margin":20,"audio":"main"}' # Green screen overlay curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@main_video.mp4" \ -F "videos[]=@webcam_greenscreen.mp4" \ -F "mode=overlay_video" \ -F 'options={"position":"bottom-left","scale":0.35,"chroma_key":true,"chroma_similarity":0.15,"audio":"mix"}' # position : top-left | top-right | bottom-left | bottom-right | center (default: bottom-right) # scale : 0.05–1.0 — overlay width as fraction of main video (default 0.30) # opacity : 0.0–1.0 — overlay transparency (default 1.0) # margin : 0–200 px — gap from frame edge, ignored if center (default 10) # audio : main | overlay | mix — audio to keep (default: main) # chroma_key : true | false — remove green (#00FF00) background from overlay (default false) # chroma_similarity : 0.01–0.60 — green screen tolerance (default 0.20)

Exemplo curl — modo add_text

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@my_video.mp4" \ -F "mode=add_text" \ -F 'options={"text":"Hello world","text_position":"bottom","font_size":72,"text_color":"#ffd700","text_start":2,"text_duration":5,"text_effect":"slide_up"}' # text : required, 1–200 characters # text_start : second at which the text appears (default 0) # text_duration : seconds the text stays visible, 0 = until the end (default 0) # the video keeps its resolution, frame rate and audio track

Exemplo curl — Mesclar vídeos

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@clip1.mp4" \ -F "videos[]=@clip2.mp4" \ -F "transition_type=fade" \ -F "transition_duration=0.5"

Exemplo curl — modo text_to_mp3

# No file upload — text + lang + voice as plain form fields curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "mode=text_to_mp3" \ -F "text=Welcome to Rapid Video Maker." \ -F "lang=en" \ -F "voice=en-US-AvaNeural" \ -F "slow=false" # voice omitted or invalid -> falls back to the first voice of "lang" curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "mode=text_to_mp3" \ -F "text=Bienvenue sur Rapid Video Maker." \ -F "lang=fr"
GET /api/v1/jobs.php?job_id=<hex32> Status do job

O status inclui a etapa real e o tempo decorrido. As estimativas são aproximadas; um tempo limite do cliente não significa falha. Retome a consulta do mesmo ID. Os arquivos expiram duas horas após a conclusão.

Status possíveis

StatusSignificadoCampos adicionais
queued Na fila, ainda não processado queue_position, queue_total, eta_minutes
processing Processamento FFmpeg em andamento processing_stage, processing_elapsed_seconds, stage_elapsed_seconds, last_activity_at, processed_media_seconds, eta_overrun
ready Concluído — arquivo disponível download_url, media_available, created_at, expires_at
error Processamento falhou error (message), quota_refund_status: pending | confirmed | not_required
cancelled Cancelado quota_refund_status: pending | confirmed | not_required

Respostas por status

{ "job_id": "a3f1c8...", "status": "queued", "queue_position": 2, "queue_total": 3, "eta_minutes": 7 }
{ "job_id": "a3f1c8...", "status": "ready", "download_url": "https://rapidvideomaker.com/api/download.php?job_id=a3f1c8...", "created_at": "2026-06-02T10:00:00+00:00", "expires_at": "2026-06-02T12:00:00+00:00" }

Exemplo curl

curl -H "Authorization: Bearer rvm_your_token" \ "https://rapidvideomaker.com/api/v1/jobs.php?job_id=a3f1c8..."
GET /api/v1/jobs.php Lista todos os jobs criados com este token (paginado, ordenado por data decrescente)

Parâmetros comuns (multipart/form-data)

ParâmetroTipoPadrãoDescrição
pageinteger1Número da página (começa em 1)
limitinteger20Resultados por página (máx. 50, padrão 20)

Respostas por status

{ "success": true, "jobs": [ { "job_id": "a3f1c8...", "status": "ready", "mode": "fusion", "created_at": "2026-06-02T10:00:00+00:00", "expires_at": "2026-06-02T12:00:00+00:00", "download_url": "https://..." }, ... ], "total": 12, "page": 1, "limit": 20 }
GET /api/download.php?job_id=<hex32> Baixar o arquivo final

Transmite o arquivo final. O Content-Type é video/mp4 para os modos de vídeo, ou audio/mpeg para text_to_mp3. Não requer token. Disponível apenas quando o status é ready.

O arquivo é mantido por 2 horas após a conclusão, depois excluído. Baixe assim que o status se tornar ready.

Parâmetros opcionais

ParâmetroDescrição
filenameNome sugerido para o arquivo baixado (ex. meu-video.mp4)
previewDefina como 1 para reprodução inline (omite Content-Disposition: attachment) em vez de iniciar um download — usado para pré-visualização no navegador.

Exemplo curl

curl -o "output.mp4" \ "https://rapidvideomaker.com/api/download.php?job_id=a3f1c8...&filename=output.mp4"

Webhooks

Webhooks são uma alternativa ao polling: em vez de verificar o status a cada X segundos, você fornece uma URL e o servidor te chama automaticamente quando o job é concluído.

Como funciona

  1. Passe callback_url no POST para /api/v1/render.php
  2. A resposta contém um webhook_secret — guarde-o para verificar assinaturas
  3. Quando o job atinge ready ou error, o servidor envia um POST JSON assinado para sua URL
  4. Verifique a assinatura com HMAC-SHA256(webhook_secret, raw_body)
Restrições: callback_url deve ser uma URL publicamente acessível. IPs privados e de loopback são bloqueados. Timeout: 10 segundos.

Payload recebido

{ "job_id": "a3f1c8...", "status": "ready", "download_url": "https://rapidvideomaker.com /api/download.php?job_id=a3f1c8...", "timestamp": "2026-04-04T12:00:00+00:00" }
{ "job_id": "a3f1c8...", "status": "error", "error": "FFmpeg xfade failed:...", "timestamp": "2026-04-04T12:00:00+00:00" }

Headers enviados pelo servidor

HeaderValor
Content-Typeapplication/json
X-RVM-Signaturesha256=<hmac_hex> — assinatura HMAC-SHA256 do body bruto
X-RVM-Job-IdO job_id relevante

Verificação de assinatura

# Python import hmac, hashlib def verify_webhook(secret: str, body: bytes, signature_header: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature_header) # Flask/FastAPI endpoint: sig = request.headers.get("X-RVM-Signature", "") if not verify_webhook(WEBHOOK_SECRET, request.data, sig): return "Invalid signature", 403 data = request.get_json()

Códigos de erro

HTTPCódigo JSONCausa
401unauthorizedToken ausente, inválido ou revogado
400missing_filesNenhum arquivo recebido
400too_few_filesMenos de 2 arquivos enviados
400too_many_filesMais de 20 arquivos enviados
400invalid_mimeArquivo não suportado — apenas MP4, MP3 e JPG/PNG aceitos (MIME verificado por magic bytes)
400wrong_file_countO número de arquivos não corresponde ao modo escolhido
400wrong_file_typesOs tipos de arquivo não correspondem ao modo escolhido
400invalid_file_combinationCombinação de arquivos não corresponde a nenhum modo suportado
400invalid_optionsO campo options não é JSON válido ou não contém um objeto
400invalid_optionUm valor em options é inválido (cor, fonte, posição…)
400file_too_largeUm arquivo excede 500 MB
400text_requiredO campo options.text está ausente ou vazio (modo add_text)
400video_too_longVídeo com mais de 15 minutos (modo add_text)
400text_start_out_of_rangetext_start ultrapassa o final do vídeo
400invalid_voiceID de voice desconhecido.
400invalid_timingsArquivo de tempos ilegível (formato não reconhecido, nenhuma linha com tempo, fim antes do início, longo demais…).
400invalid_orderO array order não é uma permutação válida
400invalid_job_idFormato de job_id incorreto (deve ser hexadecimal de 32 caracteres)
404job_not_foundJob não encontrado — job_id desconhecido ou nunca existiu
410job_expiredJob expirado — existia mas a janela de 2 horas passou
429quota_exceeded20 jobs bem-sucedidos/dia atingidos
429rate_limitedMais de 12 chamadas/min em /api/v1/jobs.php — aguardar Retry-After segundos
500server_errorErro interno do servidor

Exemplos de integração

Exemplos para cada modo — instalar requests com pip install requests.

Configuração comum

import requests, time, sys, json API_BASE = "https://rapidvideomaker.com" API_TOKEN = "rvm_your_token_here" HEADERS = {"Authorization": f"Bearer {API_TOKEN}"}

Modo image_to_video — imagem + áudio → vídeo

with open("scene.jpg", "rb") as fi, open("narration.mp3", "rb") as fa: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("scene.jpg", fi, "image/jpeg")), ("videos[]", ("narration.mp3", fa, "audio/mpeg")), ], data={ "mode": "image_to_video", "options": json.dumps({ "text": "Chapter 1", "font_size": 72, "text_color": "white", "text_position": "bottom", "box": True, "box_color": "black@0.4", "fade_duration": 0.5, "width": 1080, "height": 1920, "image_fit": "contain", # "contain" | "cover" "background_mode": "solid", # or "blur" with contain "blur_strength": 20, "bg_color": "black", # ignored if image_fit="cover" "enable_image_motion": True, "image_motion_effect": "ken_burns", "motion_intensity": 1.0, # 0.25–2.0 — photo animation amplitude "text_effect": "slide_up", # none | fade_in | slide_up | slide_down | slide_left | bounce (ignored if text_mode=word_by_word) "text_effect_intensity": 1.0, # 0.25–2.0 — text animation intensity # word-by-word reveal (mutually exclusive with text_effect): # "text_mode": "word_by_word", "word_reveal_speed": 2.0, "word_anim": "fade" }), }, )

Editar áudio

# Replace audio (deletes original) — mode=add_audio with open("video.mp4", "rb") as fv, open("music.mp3", "rb") as fa: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("video.mp4", fv, "video/mp4")), ("videos[]", ("music.mp3", fa, "audio/mpeg")), ], data={"mode": "add_audio"}, ) # Keep original audio + overlay MP3 — mode=mix_audio with open("video.mp4", "rb") as fv, open("music.mp3", "rb") as fa: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("video.mp4", fv, "video/mp4")), ("videos[]", ("music.mp3", fa, "audio/mpeg")), ], data={"mode": "mix_audio", "options": json.dumps({"mp3_volume": 0.7})}, # mp3_volume : 0.0 = muted, 1.0 = original volume (default), 2.0 = amplified )

Modo overlay_video — picture-in-picture

with open("main.mp4", "rb") as fm, open("overlay.mp4", "rb") as fo: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("main.mp4", fm, "video/mp4")), ("videos[]", ("overlay.mp4", fo, "video/mp4")), ], data={ "mode": "overlay_video", "options": json.dumps({ "position": "bottom-right", # top-left | top-right | bottom-left | bottom-right | center "scale": 0.25, # 0.05–1.0 — overlay width fraction "opacity": 1.0, # 0.0–1.0 — transparency "margin": 20, # 0–200 px — gap from frame edge "audio": "main", # main | overlay | mix # green screen: "chroma_key": True, "chroma_similarity": 0.15 }), }, )

Modo add_text — texto em um vídeo

with open("video.mp4", "rb") as fv: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[("videos[]", ("video.mp4", fv, "video/mp4"))], data={ "mode": "add_text", "options": json.dumps({ "text": "Hello world", # required "text_position": "bottom", # center | top | bottom "font": "amiri", # font id (see the table above) "font_size": 72, "text_start": 2, # appears at 2 s "text_duration": 5, # stays 5 s (0 = until the end) }), }, )

Mesclar vídeos

with open("clip1.mp4", "rb") as f1, open("clip2.mp4", "rb") as f2: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("clip1.mp4", f1, "video/mp4")), ("videos[]", ("clip2.mp4", f2, "video/mp4")), ], data={"transition_type": "fade", "transition_duration": "0.5"}, )

Modo text_to_mp3 — texto para voz

# No files — text + lang (+ optional voice / slow) as form fields resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, data={ "mode": "text_to_mp3", "text": "Welcome to Rapid Video Maker.", "lang": "en", # one of the 20 site language codes "voice": "en-US-AvaNeural", # optional — falls back to the first voice of "lang" "slow": "false", # "true" = -25% speech rate }, )

Polling + download (comum a todos os modos)

resp.raise_for_status() job_id = resp.json()["job_id"] print(f"Job created: {job_id}") for _ in range(120): # timeout 10 min (120 × 5s) r = requests.get( f"{API_BASE}/api/v1/jobs.php", headers=HEADERS, params={"job_id": job_id}, ) data = r.json() status = data["status"] if status == "queued": pos = data.get("queue_position", "?") eta = data.get("eta_minutes", "?") print(f"Queued — position {pos}, ETA ~{eta} min") elif status == "processing": print("Processing…") elif status == "ready": download_url = data["download_url"] break elif status == "error": sys.exit(f"Error: {data.get('error')}") time.sleep(5) else: sys.exit("Timeout: job not completed after 10 min") r = requests.get(download_url, stream=True) with open("output.mp4", "wb") as f: for chunk in r.iter_content(65536): f.write(chunk) print("Downloaded: output.mp4")

Duas abordagens no n8n: polling (loop de status) ou webhook (servidor chama o n8n). O webhook é recomendado — mais limpo, zero carga desnecessária.

Abordagem A — Webhook (recomendado)

Apenas 3 nodes, sem loop.

Node 1 — Trigger Webhook
Adicione um node Webhook como entrada do workflow (método POST). Anote a URL gerada, ex. https://seu-n8n.com/webhook/rvm-callback.

Node 2 — Criar o job (HTTP Request)

MétodoPOST
URLhttps://rapidvideomaker.com/api/v1/render.php
AutenticaçãoHeader Auth — Authorization: Bearer rvm_…
Tipo de conteúdo do bodyForm-Data Multipart
Body paramsCampo Binary videos[] para cada clipe + Campo Text callback_url = URL do node webhook

Guarde o webhook_secret da resposta em uma variável do workflow.

Node 3 — Processar o resultado (no workflow ativado pelo webhook)
Quando o n8n recebe o POST do servidor, $json.status é ready ou error. Se ready, $json.download_url contém a URL de download direto.

Para verificar a assinatura: compare {{ $headers['x-rvm-signature'] }} com sha256= + HMAC-SHA256 do body bruto. Node Code: crypto.createHmac('sha256', secret).update(body).digest('hex').

Abordagem B — Polling (sem webhook)

5 nodes, loop de status a cada 10 seg.

Node 1 — Criar o job — mesma configuração, sem callback_url.

Node 2 — Aguardar — 10 segundos.

Node 3 — Verificar status (HTTP Request GET)

URLhttps://rapidvideomaker.com/api/v1/jobs.php
Parâmetros de queryjob_id = {{ $('Node 1').item.json.job_id }}
AutenticaçãoHeader Auth — mesmo token

Node 4 — If: {{ $json.status }} === 'ready' → true: Node 5 / false: volta ao Node 2.

Adicione um contador em um node Set para interromper o loop após 60 tentativas (máx. 10 min.).

Node 5 — Download: HTTP Request GET em {{ $json.download_url }}, formato de resposta File.

Etapa 1 — Criar o job (escolha um modo)

# fusion JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@clip1.mp4" -F "videos[]=@clip2.mp4") # add_audio (replace audio) JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@video.mp4" -F "videos[]=@music.mp3" \ -F "mode=add_audio") # mix_audio (overlay music at 70% volume) JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@video.mp4" -F "videos[]=@music.mp3" \ -F "mode=mix_audio" -F 'options={"mp3_volume":0.7}') # image_to_video JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_your_token" \ -F "videos[]=@scene.jpg" -F "videos[]=@narration.mp3" \ -F "mode=image_to_video" \ -F 'options={"text":"Chapter 1","font_size":72,"text_position":"bottom","fade_duration":0.5,"width":1080,"height":1920}') JOB_ID=$(echo $JOB | grep -o '"job_id":"[^"]*"' | cut -d'"' -f4) echo "Job ID: $JOB_ID"

Etapa 2 — Polling

while true; do STATUS=$(curl -s \ -H "Authorization: Bearer rvm_your_token" \ "https://rapidvideomaker.com/api/v1/jobs.php?job_id=$JOB_ID") STATE=$(echo $STATUS | grep -o '"status":"[^"]*"' | cut -d'"' -f4) echo "Status: $STATE" [ "$STATE" = "ready" ] && break [ "$STATE" = "error" ] && { echo "Error"; exit 1; } sleep 10 done

Etapa 3 — Download

DOWNLOAD_URL=$(echo $STATUS | grep -o '"download_url":"[^"]*"' | cut -d'"' -f4) curl -o output.mp4 "$DOWNLOAD_URL"

Boas práticas

Os arquivos de resultado são mantidos 2 horas após a conclusão, depois excluídos automaticamente. Baixe seu vídeo assim que o status se tornar ready.