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/MOV), Editar audio (1 MP4/MOV + 1 MP3), Crear un vídeo (1 JPG/PNG + 1 MP3), Superposición de vídeo (2 MP4/MOV 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/MOV + 1 MP3 → edición de audio (añade mode=mix_audio para superponer pistas). Múltiples MP4/MOV → fusión. El servidor devuelve un job_id único. O 1 imagen + options.text + options.voice: la voz se genera a partir del texto, sin MP3.
2
Esperar el trabajo — GET /api/v1/jobs.php?job_id=…
Consulta este endpoint regularmente (cada 5–10 s). El trabajo avanza por queued → processing → ready (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/MOV 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 miembro — un 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/MOV 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/MOV + 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 — o 1 JPG/PNG + un texto (options.text + options.voice): la voz se genera Genera un vídeo a partir de una imagen fija y tu MP3 — o de un simple texto (options.text) cuya voz se genera (options.voice). Texto superpuesto (fijo, palabra a palabra o karaoke), fundidos, resolución y fps configurables mediante el campo options.
Superposición de vídeo overlay_video 2 MP4/MOV Superpone un segundo vídeo sobre el principal. Posición, tamaño, opacidad y audio configurables mediante el campo options.
Añadir texto add_text 1 MP4/MOV Superpone texto a un vídeo existente (se conservan resolución, fotogramas por segundo y audio). Mismos ajustes de texto que image_to_video, más el momento en que aparece el texto. options.text es obligatorio.
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/MOV + 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/MOV sin campo mode → detección automática de fusion. Excepción: con options.text + options.voice, image_to_video acepta 1 imagen sola — la voz se genera a partir del texto (sin MP3).
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). Con options.voice, image_to_video dura lo que la voz generada a partir del texto (+0,6 s).

Parámetros comunes (multipart/form-data)

CampoTipoReq.Descripción
videos[]File[]SÍArchivos a procesar. Según el modo: 2–20 MP4/MOV, o 1 MP4/MOV + 1 MP3, o 1 imagen (JPG/PNG) + 1 MP3. Máx. 500 MB por archivo.
modestring*image_to_video | add_audio | mix_audio | overlay_video | text_to_mp3. Requerido para estos modos no-fusion. Omitir mode con solo archivos MP4/MOV siempre activa fusion (concatenación por copia de flujo) — nunca overlay_video, incluso con exactamente 2 MP4/MOV. 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. add_text también se acepta: es el único modo que recibe un solo archivo MP4/MOV y exige options.text.
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.
optionsJSONObjeto JSON de parámetros de renderizado para image_to_video, add_text, mix_audio y overlay_video (ver las tablas de abajo).
timingsFile / stringimage_to_video / add_text: archivo de tiempos del karaoke (SRT o LRC, 200 KB máx.), como campo de archivo o texto plano. El texto mostrado sale del archivo; impone text_mode=karaoke; no es compatible con voice.
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.
fontstring"default"Fuente del texto, por identificador. Valores aceptados: 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 = fuente estándar (compatible con emoji); amiri = fuente Naskh, ideal para texto en árabe. Cualquier otro valor devuelve el error invalid_option. Los emoji solo se muestran con default.
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"contain: Muestra la imagen o el vídeo completos y rellena el espacio libre con el fondo elegido. solid (predeterminado) o blur. El desenfoque requiere image_fit=contain. El texto permanece nítido. cover: La imagen se amplía para rellenar el marco, centrada — los bordes se recortan.
bg_colorstring"black"background_mode=solid: Color de fondo (relleno) si la imagen no ocupa la resolución objetivo — relevante solo con image_fit=contain (ej. black, white, #1a1a2e).
background_modestring"solid"solid (predeterminado) o blur. El desenfoque requiere image_fit=contain. El texto permanece nítido.
blur_strengthnumber20Número de 1 a 50; predeterminado 20. Desenfoque gaussiano solo en el fondo.
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_border_colorstring"black"Color del contorno de los caracteres (mismo formato que text_color, por defecto "black"). Se usa si text_border_width > 0.
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. "karaoke": el texto cambia de color al ritmo del audio, página por página (hasta 1000 caracteres). Sincronizado palabra por palabra con voice; si no, repartido sobre el audio según la longitud de las palabras.
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.
karaoke_stylestring"fill"Estilo de karaoke: fill (las palabras pronunciadas toman el color de resaltado), sweep (cada palabra se rellena progresivamente; palabras enteras en escrituras de derecha a izquierda) o highlight (solo se colorea la palabra actual).
highlight_colorstring"#FFD200"Color de las palabras pronunciadas / de la palabra actual en modo karaoke (mismo formato que text_color).
karaoke_linesint2Líneas mostradas por página en modo karaoke (1–4).
voicestring""ID de voz (misma lista que text_to_mp3, p. ej. es-ES-ElviraNeural): la voz se genera a partir de text en el mismo trabajo. image_to_video solo necesita entonces la imagen (se rechaza un MP3 enviado además). En modo karaoke, cada palabra se sincroniza con la voz.
voice_rateint0Velocidad de la voz generada, en % (−50 a +50).

Karaoke con tus propios tiempos (SRT / LRC)

Envía un archivo SRT o LRC en el campo timings: cada línea aparece en su momento y forma una página del karaoke (hasta 500 líneas, 5000 caracteres). SRT: una línea desaparece en su hora de fin. LRC: una línea permanece hasta la siguiente (una línea vacía la detiene); se admiten [offset:] y los tiempos por palabra del LRC «enhanced» <mm:ss.xx>; si no, cada línea se reparte en su duración. En add_text, los tiempos son relativos al inicio del vídeo y se desplazan con 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 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 — modo add_text

El texto es obligatorio. Por defecto se conservan el formato, los fotogramas por segundo y el audio. output_format activa el ajuste con image_fit, bg_color y background_mode. width, height, fps y el movimiento de foto siguen ignorados. Duración máxima: 15 minutos.

{"text":"Hello","output_format":"portrait","image_fit":"contain","background_mode":"blur","blur_strength":20}
ClaveTipoPor defectoDescripción
textstringSÍTexto a superponer. Obligatorio, de 1 a 200 caracteres.
text_startfloat0Segundo en el que aparece el texto (≥ 0). Debe ser anterior al final del vídeo.
text_durationfloat0Tiempo que el texto permanece visible, en segundos (0,1–3600). 0 = hasta el final del vídeo.
fontstring"default"Fuente del texto, por identificador. Valores aceptados: 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 = fuente estándar (compatible con emoji); amiri = fuente Naskh, ideal para texto en árabe. Cualquier otro valor devuelve el error invalid_option. Los emoji solo se muestran con default.
font_sizeint60Tamaño de fuente, expresado para un vídeo cuyo lado corto mide 1080 px y escalado automáticamente a la resolución real: el mismo valor se ve igual en 720p y en 4K. Rango: 10–300.
fade_durationfloat0.5Duración del fundido de entrada/salida del texto (no del vídeo), en segundos. Rango: 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 a image_to_video (ver la tabla anterior).
original_volumefloat0.3Con voice: volumen del sonido original del vídeo bajo la voz (0–2, por defecto 0.3; 0 = sustituido). La voz empieza en text_start; el texto permanece hasta que termina y, si supera el final del vídeo, se mantiene la última imagen.
background_modestring"solid"solid (predeterminado) o blur. El desenfoque requiere image_fit=contain. El texto permanece nítido.
blur_strengthnumber20Número de 1 a 50; predeterminado 20. Desenfoque gaussiano solo en el fondo.
output_formatstring"original"Solo add_text: original (predeterminado), portrait (1080×1920), square (1080×1080), landscape (1920×1080). El desenfoque requiere un formato distinto de original.
image_fitstring"contain"contain: Muestra la imagen o el vídeo completos y rellena el espacio libre con el fondo elegido. solid (predeterminado) o blur. El desenfoque requiere image_fit=contain. El texto permanece nítido. cover: La imagen se amplía para rellenar el marco, centrada — los bordes se recortan.
bg_colorstring"black"background_mode=solid: Color de fondo (relleno) si la imagen no ocupa la resolución objetivo — relevante solo con image_fit=contain (ej. black, white, #1a1a2e).

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.

Modo text_to_mp3 — parámetros directos (sin JSON options)

A diferencia de otros modos, estos campos se envían directamente como campos de formulario, no dentro del objeto JSON options. Solo text es obligatorio.

ClaveTipoPor defectoDescripción
textstring—Texto a convertir en voz. Obligatorio. Máximo 5.000 caracteres.
langstring"en"Código de idioma usado para elegir la voz por defecto cuando se omite o no es válido voice. Uno de los 20 idiomas del sitio (ver tabla abajo). Si no se reconoce, usa en.
voicestringautoID de voz edge-tts (ver tabla abajo). Si se omite o no es un ID válido, se usa automáticamente la primera voz de lang.
slowboolfalsePon true (o 1) para reducir la velocidad de la voz un 25%. Cualquier otro valor se trata como false.
No requiere subir archivos: a diferencia de los demás modos, text_to_mp3 no necesita videos[]. Envía mode=text_to_mp3 junto con text / lang / voice / slow como campos de formulario normales.

Voces disponibles (edge-tts, Microsoft Neural), agrupadas por código de idioma:

IdiomaVoces disponibles
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

Respuesta de éxito (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, la respuesta no incluye file_count ni transition (no se sube ningún archivo) — el resto es idéntico: job_id, quota_used, quota_remaining, status_url, webhook_secret.

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" # 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 karaoke con voz generada (image_to_video, sin 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

Karaoke con un archivo SRT (image_to_video + tu 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"

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

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"

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

El estado incluye la etapa real y el tiempo transcurrido. Las estimaciones son orientativas; un tiempo de espera del cliente no implica un fallo. Retoma el seguimiento del mismo ID. Los archivos caducan dos horas después de finalizar.

Estados posibles

EstadoSignificadoCampos adicionales
queued En cola, aún no procesado queue_position, queue_total, eta_minutes
processing Procesamiento FFmpeg en curso processing_stage, processing_elapsed_seconds, stage_elapsed_seconds, last_activity_at, processed_media_seconds, eta_overrun
ready Completado — archivo disponible download_url, media_available, created_at, expires_at
error Procesamiento fallido error (message), quota_refund_status: pending | confirmed | not_required
cancelled Cancelado quota_refund_status: pending | confirmed | not_required

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 Lista todos los trabajos creados con este token (paginado, ordenado por fecha descendente)

Parámetros comunes (multipart/form-data)

ParámetroTipoPor defectoDescripción
pageinteger1Número de página (empieza en 1)
limitinteger20Resultados por página (máx. 50, por defecto 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 }
GET /api/download.php?job_id=<hex32> Descargar el archivo final

Transmite el archivo final. El Content-Type es video/mp4 para los modos de vídeo, o audio/mpeg para text_to_mp3. 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ámetros opcionales

ParámetroDescripción
filenameNombre sugerido para el archivo descargado (ej. mi-video.mp4)
previewEstablece 1 para reproducción en línea (omite Content-Disposition: attachment) en lugar de iniciar una descarga — usado para previsualización en el navegador.

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
400text_requiredFalta el campo options.text o está vacío (modo add_text)
400video_too_longVídeo de más de 15 minutos (modo add_text)
400text_start_out_of_rangetext_start supera el final del vídeo
400invalid_voiceID de voice desconocido.
400invalid_timingsArchivo de tiempos ilegible (formato no reconocido, ninguna línea con tiempo, fin antes del inicio, demasiado largo…).
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" "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 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 }), }, )

Modo add_text — texto sobre un 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) }), }, )

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

Modo text_to_mp3 — texto a 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 + 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.