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), Editar áudio (1 MP4 + 1 MP3), Criar um vídeo (1 JPG/PNG + 1 MP3), Sobreposição de vídeo (2 MP4 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 + 1 MP3 → edição de áudio (mode=mix_audio para sobrepor). Vários MP4 → mesclar. O servidor retorna um job_id único.
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 queuedprocessingready (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 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 membroum 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 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 + 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 Gera um vídeo a partir de uma imagem estática e um arquivo de áudio. Sobreposição de texto, fades, resolução e FPS configuráveis via o campo options.
Sobreposição de vídeo overlay_video 2 MP4 Sobrepõe um segundo vídeo ao vídeo principal. Posição, tamanho, opacidade e áudio configuráveis via o campo options.
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 + 1 MP3. image_to_video apenas 1 JPG/PNG + 1 MP3. Os tipos MIME são verificados por magic bytes.
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).

Parâmetros comuns (multipart/form-data)

CampoTipoObr.Descrição
videos[]File[]SIMArquivos a processar. Dependendo do modo: 2–20 MP4, ou 1 MP4 + 1 MP3, ou 1 imagem (JPG/PNG) + 1 MP3. Máx. 500 MB por arquivo.
modestring*image_to_video | add_audio | mix_audio. Obrigatório para esses três modos. Ignorado (detectado automaticamente) apenas se todos os arquivos forem MP4 (fusion). Se fornecido, os arquivos devem corresponder exatamente — caso contrário a requisição é rejeitada.
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.
optionsJSONApenas modo image_to_video — objeto JSON de parâmetros de renderização (veja abaixo).
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.
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"Modo de enquadramento: contain = imagem completa visível, áreas vazias com bg_color; cover = imagem ampliada, bordas cortadas. bg_color ignorado em cover.
bg_colorstring"black"Cor de fundo se a imagem não preencher a resolução — apenas com image_fit=contain (ex. black, white, #1a1a2e).
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_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.
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.

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 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.

Resposta de sucesso (HTTP 200)

{ "success": true, "job_id": "a3f1c8d2e5b09471...", "mode": "fusion", // "fusion" | "add_audio" | "mix_audio" | "image_to_video" | "overlay_video" "file_count": 2, "transition": null, "quota_used": 1, "quota_remaining": 9, "status_url": "https://rapidvideomaker.com/api/v1/jobs.php?job_id=a3f1c8..." }

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" # 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 — black outline around characters (0 = disabled) # 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)

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 — 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"
GET /api/v1/jobs.php?job_id=<hex32> Status do job

Status possíveis

StatusSignificadoCampos adicionais
queued Na fila, ainda não processado queue_position, queue_total, eta_minutes
processing Processamento FFmpeg em andamento
ready Concluído — arquivo disponível download_url, created_at, expires_at
error Processamento falhou error (message)

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 List all jobs created with this token (paginated, sorted by date desc)

Parâmetros comuns (multipart/form-data)

apidocs_th_paramTipoPadrãoapidocs_th_desc
pageinteger1Page number (starts at 1)
limitinteger20Results per page (max 50, default 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 }
POST /api/v1/publish.php Publicar um vídeo no YouTube ou TikTok

Publica um trabalho concluído (status=ready) em uma ou mais contas sociais. O token deve pertencer a uma conta de membro (não um token de administrador).

Pré-requisito: As contas sociais (YouTube, TikTok) devem ser conectadas via OAuth na página de Publicações da área do membro antes de usar este endpoint. O account_id de cada conta é exibido lá.

Parâmetros comuns (multipart/form-data)

apidocs_th_paramTipoapidocs_th_requiredapidocs_th_desc
job_idstringapidocs_requiredID do trabalho (hex 32 caracteres) do vídeo concluído
publicationsarrayapidocs_requiredArray de objetos de publicação (máx. 10)

Objeto de publicação

apidocs_th_paramTipoapidocs_th_requiredapidocs_th_desc
account_idintegerapidocs_requiredID da conta social conectada — encontre-o na página de Publicações da área do membro
titlestringTítulo do vídeo (máx. 512 caracteres)
descriptionstringDescrição do vídeo (máx. 5 000 caracteres)
tagsstringTags separadas por vírgula (máx. 1 024 caracteres)
visibilitystringpublic | private | unlisted — Padrão: public
tiktok_modestringdraft | direct — Somente TikTok — padrão: direct
tiktok_privacystringmodo directSomente TikTok — obrigatório no modo direct
allow_commentbooleanSomente TikTok — permitir comentários
allow_duetbooleanSomente TikTok — permitir duetos
allow_stitchbooleanSomente TikTok — permitir stitches
your_brandbooleanSomente TikTok — conteúdo promocional orgânico ("Sua marca").
branded_contentbooleanSomente TikTok — divulgação de conteúdo de marca
tiktok_cover_msintegerSomente TikTok — timestamp do quadro de capa em ms (0–60 000, padrão 1 000)

Respostas por status

{ "success": true, "results": [ { "account_id": 12, "pub_id": 47, "status": "published", "provider": "youtube", "url": "https://youtu.be/abc123" } ] }

Códigos de erro por publicação

apidocs_th_codeSignificado
job_not_readyTrabalho ainda não concluído
mode_not_supportedJobs text_to_mp3 não podem ser publicados
account_not_foundConta não encontrada ou desconectada
tiktok_privacy_requiredNível de privacidade necessário no modo direct
publication_failedO provedor retornou um erro durante o upload

Exemplo cURL

curl -X POST https://rapidvideomaker.com/api/v1/publish.php \ -H "Authorization: Bearer rvm_your_token" \ -H "Content-Type: application/json" \ -d '{ "job_id": "a3f1c8...", "publications": [ { "account_id": 12, "title": "My video", "description": "Created with RapidVideoMaker", "visibility": "public" } ] }'
GET /api/download.php?job_id=<hex32> Baixar o arquivo final

Retorna o arquivo MP4 final como stream (Content-Type: video/mp4). 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âmetro opcional

ParâmetroDescrição
filenameNome sugerido para o arquivo baixado (ex. meu-video.mp4)

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
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" "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 }), }, )

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"}, )

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.