RapidVideoMaker
Crear una cuenta

API RapidVideoMaker

La API REST te permite procesar archivos de vídeo desde cualquier cliente HTTP — scripts Python, flujos de trabajo n8n, herramientas de terceros. Cinco modos disponibles: Fusionar vídeos (varios MP4), Editar audio (1 MP4 + 1 MP3), Crear un vídeo (1 JPG/PNG + 1 MP3), Superposición de vídeo (2 MP4 picture-in-picture). El procesamiento es asíncrono: envía los archivos y luego consulta el resultado.

Obtén tu token API gratis
Crea una cuenta para obtener tu token API — 20 solicitudes incluidas por día, usables desde la interfaz o la API.
Crear una cuenta gratuita ¿Ya tienes cuenta? Iniciar sesión

Flujo de trabajo completo

Cada integración sigue la misma secuencia de 4 pasos:

1
Crear el trabajo — POST /api/v1/render.php
Envía tus archivos como multipart/form-data con tu token Bearer. 1 imagen JPG/PNG + 1 MP3 + mode=image_to_video → generación de vídeo. 1 MP4 + 1 MP3 → edición de audio (añade mode=mix_audio para superponer pistas). Múltiples MP4 → fusión. El servidor devuelve un job_id único.
2
Esperar el trabajo — GET /api/v1/jobs.php?job_id=…
Consulta este endpoint regularmente (cada 5–10 s). El trabajo avanza por queuedprocessingready (o error). La respuesta incluye la posición en cola y un tiempo estimado restante.
3
Obtener la URL de descarga
Cuando el estado es ready, la respuesta contiene un campo download_url listo para usar.
4
Descargar el archivo — GET /api/download.php?job_id=…
Descarga el MP4 final. El archivo está disponible durante 2 horas tras completarse el trabajo, luego se elimina automáticamente. Tras el vencimiento, la API responde 410 Gone (en lugar de 404) para indicar que el trabajo existió pero ya no está disponible.

Autenticación

Cada solicitud debe incluir tu token API. Se aceptan dos formatos:

# Autenticación — Cada solicitud debe incluir tu token API. Se aceptan dos formatos: Authorization: Bearer rvm_your_token_here # Alternative X-API-Key: rvm_your_token_here

Tu token está disponible en tu espacio de miembroun token por cuenta, creado automáticamente al registrarse. Solo se muestra en claro una vez — guárdalo bien. Si lo pierdes, puedes regenerarlo desde tu espacio de miembro.

Cuota

Cada cuenta de miembro tiene 20 solicitudes por día, compartidas entre la interfaz web y la API. Los trabajos fallidos no consumen cuota. El contador se reinicia a medianoche UTC.

Las respuestas POST incluyen quota_used y quota_remaining. Cuando se supera el límite, el servidor responde 429.

Interfaz + API = mismo contador. Un vídeo creado desde la interfaz web y una solicitud API consumen cada uno 1 crédito del mismo cupo diario.

Cola

Se procesa un trabajo a la vez. Si se envían varios trabajos simultáneamente, se ponen en cola y se procesan en orden de llegada. Mientras espera, la respuesta de estado incluye:

Límite de tasa aplicado: el endpoint /api/v1/jobs.php acepta como máximo 12 llamadas por minuto por token (1 cada 5 s). Más allá, el servidor responde 429 con un encabezado Retry-After: 5. Recomendación: 10 segundos entre cada llamada.

Transiciones disponibles

Pasa transition_type=none (por defecto) para una fusión directa, o uno de los tipos siguientes para un fundido entre clips:

none fade fadeblack dissolve wipeleft wiperight slideleft slideright zoomin circleclose

La duración (transition_duration) está entre 0,2 y 2,0 segundos. Si un clip es demasiado corto para acomodar la transición, se ignora y la fusión procede sin transición.

Endpoints

POST /api/v1/render.php Crea un trabajo de procesamiento de vídeo

Cinco modos, accesibles mediante el campo mode (omite mode con varios MP4 para detectar automáticamente fusion):

UsoModo(s) APIArchivos requeridosDescripción
Fusionar vídeos fusion 2–20 archivos MP4 Los clips se ensamblan de principio a fin en el orden indicado. Transiciones opcionales entre clips.
Editar audio add_audio o mix_audio 1 MP4 + 1 MP3 Reemplaza o enriquece la pista de audio de un vídeo. La pista de vídeo nunca se recodifica (-c:v copy).

add_audio — el audio original se elimina y se reemplaza completamente por el MP3.
mix_audio — el audio original se mantiene y el MP3 se superpone (amix). Pasa options={"mp3_volume":…} para ajustar el volumen del MP3 añadido. Si el vídeo no tiene audio, se comporta como add_audio.
Crear un vídeo image_to_video 1 JPG/PNG + 1 MP3 Genera un vídeo desde una imagen fija y un archivo de audio. Texto superpuesto, fundidos, resolución y fps configurables mediante el campo options.
Superposición de vídeo overlay_video 2 MP4 Superpone un segundo vídeo sobre el principal. Posición, tamaño, opacidad y audio configurables mediante el campo options.
Texto a MP3 text_to_mp3 (solo texto) Convierte texto a voz y devuelve un archivo MP3. No se necesita subir archivos — envía mode=text_to_mp3, text y lang como campos de formulario. Compatible con los 20 idiomas del sitio.
Validación estricta: cada modo requiere un número exacto y tipos de archivos. add_audio y mix_audio solo aceptan 1 MP4 + 1 MP3 (exactamente). image_to_video solo acepta 1 JPG/PNG + 1 MP3 (exactamente). Cualquier otra combinación se rechaza con un código de error explícito. Los tipos MIME se verifican por bytes mágicos, no solo por extensión. Múltiples MP4 sin campo mode → detección automática de fusion.
Regla de duración: en los modos audio e image_to_video, la duración del resultado está fijada a la duración del MP3. La pista de vídeo nunca se recodifica en los modos audio (-c:v copy).

Parámetros comunes (multipart/form-data)

CampoTipoReq.Descripción
videos[]File[]Archivos a procesar. Según el modo: 2–20 MP4, o 1 MP4 + 1 MP3, o 1 imagen (JPG/PNG) + 1 MP3. Máx. 500 MB por archivo.
modestring*image_to_video | add_audio | mix_audio. Requerido para estos tres modos. Ignorado (y detectado automáticamente) solo si todos los archivos son MP4 (fusion). Para edición de audio: add_audio elimina el original, mix_audio lo mantiene y superpone. Si se proporciona el campo mode, los archivos subidos deben coincidir exactamente — de lo contrario la solicitud es rechazada.
orderJSONSolo modo fusion — array JSON de índices que define el orden de los clips.
transition_typestringSolo modo fusion. Por defecto: none. Ver la lista de transiciones disponibles.
transition_durationfloatSolo modo fusion. Duración 0,2–2,0 s. Por defecto: 0,5.
optionsJSONSolo modo image_to_video — objeto JSON de parámetros de renderizado (ver abajo).
callback_urlstringURL pública (http/https) llamada al completarse el trabajo. La respuesta incluye un webhook_secret.

Parámetros de options — modo image_to_video

Todos opcionales. Los valores no proporcionados → valores por defecto aplicados por el worker.

ClaveTipoPor defectoDescripción
textstring""Texto mostrado como superposición. Vacío = sin texto. Máx. 500 caracteres.
font_sizeint60Tamaño de fuente en píxeles. Rango: 10–300. Recomendado: 36, 48, 60, 72, 96.
text_colorstring"white"Color del texto (ej. white, yellow, #ffffff, 0xffffff).
text_positionstring"center"Posición del texto: center, top, bottom.
boxbooltrueFondo semitransparente detrás del texto.
box_colorstring"black@0.4"Color + opacidad en formato FFmpeg: color@opacity. Colores: black, white, yellow, #ff4444, #00ccff, #ff8800, #ff69b4… Opacidad: 0,0–1,0 (ej. black@0.4 = negro al 40%, white@0.70 = blanco al 70%).
fade_durationfloat0.5Duración del fundido de entrada/salida en segundos (0–2). El texto se incluye en el fundido. 0 = sin fundido.
widthint1080Ancho del vídeo en píxeles (64–3840, forzado par). Combinaciones estándar: 1080/1920/720/1280.
heightint1920Alto del vídeo en píxeles (64–3840, forzado par).
fpsint24Tasa de fotogramas (1–60).
image_fitstring"contain"Modo de encuadre: contain = la imagen completa es visible, áreas vacías rellenadas por bg_color (letterbox/pillarbox); cover = imagen ampliada para rellenar todo el marco, centrada, bordes sobrantes recortados (sin barras negras). El parámetro bg_color se ignora en modo cover.
bg_colorstring"black"Color de fondo (relleno) si la imagen no ocupa la resolución objetivo — relevante solo con image_fit=contain (ej. black, white, #1a1a2e).
enable_image_motionboolfalseActiva la animación de foto. Si es false, la imagen permanece estática. Si es true, se aplica el efecto definido por image_motion_effect mediante el filtro zoompan de FFmpeg.
image_motion_effectstring"ken_burns"Efecto de animación (ignorado si enable_image_motion es false). Valores aceptados: 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. Por defecto si está ausente o es inválido: ken_burns.
motion_intensityfloat1.0Intensidad de la animación de foto (0,25–2,0). Multiplica la amplitud de zoom y la velocidad de paneo. 0,25 = muy sutil, 1,0 = por defecto, 2,0 = doble amplitud. Ignorado si enable_image_motion es false.
text_effectstring"none"Animación del texto superpuesto (ignorado si text está ausente). Valores aceptados: none, fade_in (fundido de entrada), slide_up (deslizar desde abajo), slide_down (deslizar desde arriba), slide_left (deslizar desde la derecha), bounce (oscilación vertical continua).
text_effect_intensityfloat1.0Intensidad de la animación de texto (0,25–2,0). Controla la velocidad del fundido, la duración de entrada del deslizamiento, o la frecuencia y amplitud del rebote. Ignorado si text_effect es none.
text_border_widthint0Grosor del contorno negro alrededor de los caracteres, en píxeles (0 = desactivado, 1–10). Mejora la legibilidad sobre fondos brillantes o de colores. Ignorado si text está ausente.
text_modestring"static"Modo de revelación del texto. static (defecto): texto completo visible desde el primer fotograma. word_by_word: las palabras aparecen de una en una al ritmo de word_reveal_speed. Exclusivo con text_effect: si text_mode=word_by_word, text_effect se ignora.
word_reveal_speedfloat1.5Velocidad de revelación en palabras por segundo (0.3–5.0, por defecto 1.5). Solo con text_mode=word_by_word. Valor recomendado para sincronización con voz OpenAI TTS: 2.0.
word_animstring"none"Animación de aparición de cada palabra. none (por defecto): revelación instantánea. fade: cada nueva palabra aparece con un fundido de 0.2s y crossfade con el bloque anterior. Solo con text_mode=word_by_word.

Parámetros options — modo overlay_video

Todos opcionales. El orden de envío importa: el primer archivo es el vídeo principal (fondo), el segundo archivo es el overlay (primer plano). Usa chroma_key para eliminar un fondo verde del overlay.

ClaveTipoPor defectoDescripción
positionstring"bottom-right"Esquina donde se coloca el overlay: top-left, top-right, bottom-left, bottom-right, o center.
scalefloat0.30Tamaño del overlay como fracción del ancho del vídeo principal. 0.25 = 25% del ancho. Rango: 0.05–1.0.
opacityfloat1.0Transparencia del overlay. 1.0 = totalmente opaco, 0.0 = invisible.
marginint10Separación en píxeles entre el overlay y el borde. Ignorado si position=center. Rango: 0–200.
audiostring"main"Audio a conservar. main: solo audio principal. overlay: solo audio del overlay. mix: ambas pistas mezcladas.
chroma_keyboolfalsePon true para eliminar el fondo verde puro (#00FF00) del overlay — útil para webcam o animaciones filmadas en pantalla verde.
chroma_similarityfloat0.20Tolerancia del chroma key. Bajo = coincidencia estricta. Alto = eliminación más amplia. Recomendado: 0.10–0.20 para verde digital, 0.25–0.45 para pantalla física. Rango: 0.01–0.60.

Parámetros de options — Editar audio (mix_audio)

Disponible solo con mode=mix_audio. Ignorado para add_audio.

ClaveTipoPor defectoDescripción
mp3_volumefloat1.0Volumen del MP3 superpuesto (0,0 = silenciado, 1,0 = volumen original, 2,0 = doble). Los valores superiores a 1,0 pueden provocar saturación.

Respuesta de éxito (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..." }

Ejemplo 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)

Ejemplo curl — Editar audio

# 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)

Ejemplo 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)

Ejemplo curl — Fusionar 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> Estado del trabajo

Estados posibles

EstadoSignificadoCampos adicionales
queued En cola, aún no procesado queue_position, queue_total, eta_minutes
processing Procesamiento FFmpeg en curso
ready Completado — archivo disponible download_url, created_at, expires_at
error Procesamiento fallido error (message)

Respuestas por estado

{ "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" }

Ejemplo 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 comunes (multipart/form-data)

apidocs_th_paramTipoPor defectoapidocs_th_desc
pageinteger1Page number (starts at 1)
limitinteger20Results per page (max 50, default 20)

Respuestas por estado

{ "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 un video en YouTube o TikTok

Publica un trabajo terminado (status=ready) en una o más cuentas sociales. El token debe pertenecer a una cuenta de miembro (no un token de administrador).

Requisito previo: Las cuentas sociales (YouTube, TikTok) deben conectarse primero vía OAuth en la página de Publicaciones del área de miembro. El account_id de cada cuenta se muestra allí.

Parámetros comunes (multipart/form-data)

apidocs_th_paramTipoapidocs_th_requiredapidocs_th_desc
job_idstringapidocs_requiredID del trabajo (hex 32 caracteres) del video terminado
publicationsarrayapidocs_requiredArray de objetos de publicación (máx. 10)

Objeto de publicación

apidocs_th_paramTipoapidocs_th_requiredapidocs_th_desc
account_idintegerapidocs_requiredID de la cuenta social conectada — encuéntralo en la página de Publicaciones de tu área de miembro
titlestringTítulo del video (máx. 512 caracteres)
descriptionstringDescripción del video (máx. 5 000 caracteres)
tagsstringEtiquetas separadas por comas (máx. 1 024 caracteres)
visibilitystringpublic | private | unlisted — Predeterminado: public
tiktok_modestringdraft | direct — Solo TikTok — predeterminado: direct
tiktok_privacystringmodo directoSolo TikTok — requerido en modo directo
allow_commentbooleanSolo TikTok — permitir comentarios
allow_duetbooleanSolo TikTok — permitir duetos
allow_stitchbooleanSolo TikTok — permitir stitches
your_brandbooleanSolo TikTok — contenido promocional orgánico ("Tu marca").
branded_contentbooleanSolo TikTok — divulgación de contenido de marca
tiktok_cover_msintegerSolo TikTok — marca de tiempo del fotograma de portada en ms (0–60 000, predeterminado 1 000)

Respuestas por estado

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

Códigos de error por publicación

apidocs_th_codeSignificado
job_not_readyTrabajo aún no terminado
mode_not_supportedLos trabajos text_to_mp3 no se pueden publicar
account_not_foundCuenta no encontrada o desconectada
tiktok_privacy_requiredNivel de privacidad requerido en modo directo
publication_failedEl proveedor devolvió un error durante la subida

Ejemplo 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> Descargar el archivo final

Devuelve el archivo MP4 final como flujo (Content-Type: video/mp4). No requiere token — la URL es suficientemente opaca. Disponible solo cuando el estado es ready.

El archivo se conserva 2 horas tras completarse el trabajo, luego se elimina. Descárgalo tan pronto como el estado sea ready.

Parámetro opcional

ParámetroDescripción
filenameNombre sugerido para el archivo descargado (ej. mi-video.mp4)

Ejemplo curl

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

Webhooks

Los webhooks son una alternativa al polling: en lugar de verificar el estado cada X segundos, proporcionas una URL y el servidor te llama automáticamente cuando el trabajo se completa.

Cómo funciona

  1. Pasa callback_url en el POST a /api/v1/render.php
  2. La respuesta contiene un webhook_secret — guárdalo para verificar firmas
  3. Cuando el trabajo llega a ready o error, el servidor envía un POST JSON firmado a tu URL
  4. Verifica la firma con HMAC-SHA256(webhook_secret, raw_body)
Restricciones: callback_url debe ser una URL públicamente accesible (http o https). Las direcciones IP privadas, de loopback y reservadas están bloqueadas en el servidor. Tiempo de espera: 10 segundos.

Payload recibido

{ "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" }

Encabezados enviados por el servidor

EncabezadoValor
Content-Typeapplication/json
X-RVM-Signaturesha256=<hmac_hex> — firma HMAC-SHA256 del cuerpo bruto
X-RVM-Job-IdEl job_id correspondiente

Verificación de firma

# 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 error

HTTPCódigo JSONCausa
401unauthorizedToken ausente, inválido o revocado
400missing_filesNo se recibieron archivos
400too_few_filesMenos de 2 archivos enviados
400too_many_filesMás de 20 archivos enviados
400invalid_mimeArchivo no admitido — solo se aceptan MP4, MP3 e imágenes JPG/PNG (MIME verificado por bytes mágicos)
400wrong_file_countEl número de archivos no coincide con el modo elegido (ej. 3 archivos con mode=add_audio que requiere 2)
400wrong_file_typesLos tipos de archivos no coinciden con el modo elegido (ej. 2 MP4 con mode=add_audio que requiere 1 MP4 + 1 MP3; o 1 MP4 + 1 MP3 con mode=image_to_video)
400invalid_file_combinationLa combinación de archivos sin modo especificado no coincide con ningún modo admitido
400invalid_optionsEl campo options no es JSON válido o contiene un objeto esperado
400invalid_optionUn valor en options es inválido (color, nombre de fuente, posición…)
400file_too_largeUn archivo supera los 500 MB
400invalid_orderEl array order no es una permutación válida
400invalid_job_idFormato de job_id incorrecto (debe ser hex de 32 caracteres)
404job_not_foundTrabajo no encontrado — job_id desconocido o nunca existió
410job_expiredTrabajo expirado — existió pero la ventana de recuperación de 2h ha pasado
429quota_exceeded20 trabajos exitosos/día alcanzados (todos los modos combinados)
429rate_limitedMás de 12 llamadas/min en /api/v1/jobs.php — espera Retry-After segundos
500server_errorError interno del servidor

Ejemplos de integración

Ejemplos para cada modo — instala requests con pip install requests.

Configuración común

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 — imagen + audio → 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 audio

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

Fusionar 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 + descarga (común a todos los 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")

Dos enfoques en n8n: polling (bucle de estado) o webhook (el servidor llama a n8n). El webhook es recomendado — más limpio, carga innecesaria cero.

Enfoque A — Webhook (recomendado)

Solo 3 nodos, sin bucle.

Nodo 1 — Webhook trigger
Agrega un nodo Webhook como entrada del flujo de trabajo (método POST). Anota la URL generada, ej.: https://tu-n8n.com/webhook/rvm-callback.

Nodo 2 — Crear el trabajo (HTTP Request)

MétodoPOST
URLhttps://rapidvideomaker.com/api/v1/render.php
AutenticaciónHeader Auth — Authorization: Bearer rvm_…
Tipo de contenidoForm-Data Multipart
Body paramsCampo Binary videos[] para cada clip + campo Text callback_url = URL del nodo Webhook de arriba

Guarda el webhook_secret de la respuesta en una variable del flujo de trabajo para verificar la firma al recibirla.

Nodo 3 — Procesar el resultado (en el flujo de trabajo disparado por el Webhook)
Cuando n8n recibe el POST del servidor, $json.status es ready o error. Si es ready, $json.download_url contiene la URL de descarga directa.

Para verificar la firma: compara {{ $headers['x-rvm-signature'] }} con sha256= + HMAC-SHA256 del cuerpo bruto desde tu webhook_secret. Usa un nodo Code con crypto.createHmac('sha256', secret).update(body).digest('hex').

Enfoque B — Polling (sin webhook)

5 nodos, bucle de estado cada 10 s.

Nodo 1 — Crear el trabajo — misma configuración que arriba, sin callback_url.

Nodo 2 — Wait — 10 segundos.

Nodo 3 — Consultar estado (HTTP Request GET)

URLhttps://rapidvideomaker.com/api/v1/jobs.php
Parámetros de consultajob_id = {{ $('Nodo 1').item.json.job_id }}
AutenticaciónHeader Auth — mismo token

Nodo 4 — If: {{ $json.status }} === 'ready' → true: Nodo 5 / false: volver al Nodo 2.

Agrega un contador de iteraciones en un nodo Set para romper el bucle después de 60 intentos (10 min máx.) y evitar un bucle infinito.

Nodo 5 — Descargar: HTTP Request GET en {{ $json.download_url }}, Response Format File.

Paso 1 — Crear el trabajo (elegir un 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"

Paso 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

Paso 3 — Descargar

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

Buenas prácticas

Los archivos de resultado se conservan 2 horas tras completarse el trabajo, luego se eliminan automáticamente. Descarga tu vídeo tan pronto como el estado sea ready.