RapidVideoMaker
Créer un compte

API RapidVideoMaker

L'API REST permet de traiter des fichiers vidéo depuis n'importe quel client HTTP — scripts Python, workflows n8n, outils tiers. Trois usages sont disponibles : Créer une vidéo (1 image JPG/PNG + 1 MP3 → génère une vidéo avec texte optionnel et fades), Modifier l'audio (1 MP4 + 1 MP3 → remplace ou superpose la piste audio) et Fusionner des vidéos (plusieurs MP4 assemblés en un avec transitions optionnelles). Le traitement est asynchrone : vous soumettez les fichiers, puis vous interrogez le statut jusqu'à ce que le résultat soit prêt.

Obtenez votre token API gratuitement
Créez un compte pour obtenir votre token API — 20 requêtes incluses par jour, utilisables depuis l'interface ou l'API.
Créer un compte gratuit Déjà un compte ? Se connecter

Workflow complet

Toute intégration suit le même enchaînement en 4 étapes :

1
Créer le job — POST /api/v1/render.php
Envoyez vos fichiers en multipart/form-data avec votre token Bearer. 1 image JPG/PNG + 1 MP3 + mode=image_to_video → génération vidéo. 1 MP4 + 1 MP3 → modification audio (ajoutez mode=mix_audio pour superposer les pistes). Plusieurs MP4 → fusion. Le serveur retourne un job_id unique.
2
Attendre la fin du job — GET /api/v1/jobs.php?job_id=…
Interrogez cet endpoint régulièrement (toutes les 5–10 s). Le job passe par les statuts queuedprocessingready (ou error). La réponse inclut la position dans la file et une estimation du temps restant.
3
Récupérer l'URL de téléchargement
Quand le statut est ready, la réponse contient un champ download_url prêt à l'emploi.
4
Télécharger le fichier — GET /api/download.php?job_id=…
Téléchargez le MP4 final. Le fichier est disponible pendant 2 heures après la fin du job, puis supprimé automatiquement. Après expiration, l'API répond 410 Gone (au lieu de 404) pour indiquer que le job a bien existé mais n'est plus récupérable.

Authentification

Chaque requête doit inclure votre token API. Deux formats sont acceptés :

# Format recommandé Authorization: Bearer rvm_votre_token_ici # Alternative X-API-Key: rvm_votre_token_ici

Votre token est disponible dans votre espace membreun seul token par compte, créé automatiquement à l'inscription. Il n'est affiché en clair qu'une seule fois, conservez-le. Si vous le perdez, vous pouvez le régénérer depuis votre espace membre.

Quota

Chaque compte membre dispose de 20 requêtes par jour, partagées entre l'interface web et l'API. Les jobs en erreur ne consomment pas de quota. Le compteur se remet à zéro à minuit UTC.

Les réponses du POST incluent quota_used et quota_remaining. En cas de dépassement, le serveur répond 429.

Interface + API = même compteur. Une vidéo créée depuis l'interface web et une requête API consomment chacune 1 crédit dans le même quota journalier.

File d'attente

Un seul job est traité à la fois. Si plusieurs jobs sont soumis simultanément, ils sont mis en file d'attente et traités dans l'ordre d'arrivée. Pendant l'attente, la réponse de statut inclut :

Limite appliquée : l'endpoint /api/v1/jobs.php accepte au maximum 12 appels par minute par token (1 toutes les 5 s). Au-delà, le serveur répond 429 avec un header Retry-After: 5. Recommandation : 10 secondes entre chaque appel.

Transitions disponibles

Passez transition_type=none (défaut) pour une fusion directe, ou l'un des types ci-dessous pour un fondu entre les clips :

none fade fadeblack dissolve wipeleft wiperight slideleft slideright zoomin circleclose

La durée (transition_duration) est comprise entre 0.2 et 2.0 secondes. Si un clip est trop court pour accueillir la transition, elle est ignorée et la fusion se fait sans transition.

Endpoints

POST /api/v1/render.php Crée un job de traitement vidéo

Trois usages principaux, accessibles via le champ mode :

UsageMode(s) APIFichiers requisDescription
Créer une vidéo image_to_video 1 image JPG/PNG + 1 MP3 Génère une vidéo à partir d'une image fixe et d'un fichier audio. Texte en overlay, fades, résolution et fps configurables via le champ options.
Modifier l'audio add_audio ou mix_audio 1 MP4 + 1 MP3 Remplace ou enrichit la piste audio d'une vidéo. La piste vidéo n'est jamais réencodée (-c:v copy).

add_audio — l'audio d'origine est supprimé et entièrement remplacé par le MP3.
mix_audio — l'audio d'origine est conservé et le MP3 est superposé (amix). Passez options={"mp3_volume":…} pour ajuster le volume du MP3 ajouté. Si la vidéo n'a pas d'audio, se comporte comme add_audio.
Fusionner des vidéos fusion 2–20 fichiers MP4 Les clips sont assemblés bout à bout dans l'ordre fourni. Transitions optionnelles entre les clips.
Validation stricte : chaque mode exige un nombre et des types de fichiers exacts. add_audio et mix_audio acceptent uniquement 1 MP4 + 1 MP3 (exactement). image_to_video accepte uniquement 1 image JPG/PNG + 1 MP3 (exactement). Toute autre combinaison est rejetée avec un code d'erreur explicite. Les types MIME sont vérifiés par magic bytes, pas seulement par l'extension. Plusieurs MP4 sans champ mode → auto-détection fusion.
Règle de durée : en modes audio et image_to_video, la durée du résultat est calée sur la durée du MP3. La piste vidéo n'est jamais réencodée en modes audio (-c:v copy).

Paramètres communs (multipart/form-data)

ChampTypeReq.Description
videos[]File[]OUIFichiers à traiter. Selon le mode : 2–20 MP4, ou 1 MP4 + 1 MP3, ou 1 image (JPG/PNG) + 1 MP3. Max 500 MB par fichier.
modestring*image_to_video | add_audio | mix_audio. Obligatoire pour ces trois modes. Ignoré (et auto-détecté) uniquement si tous les fichiers sont MP4 (fusion). Pour modifier l'audio : add_audio supprime l'original, mix_audio le conserve et superpose. Si le champ mode est fourni, les fichiers envoyés doivent correspondre exactement — sinon la requête est rejetée.
orderJSONMode fusion uniquement — tableau JSON des indices définissant l'ordre des clips.
transition_typestringMode fusion uniquement. Défaut : none. Voir la liste des transitions disponibles.
transition_durationfloatMode fusion uniquement. Durée 0.2–2.0 s. Défaut : 0.5.
optionsJSONMode image_to_video uniquement — objet JSON de paramètres de rendu (voir ci-dessous).
callback_urlstringURL publique (http/https) appelée en fin de job. La réponse inclut un webhook_secret.

Paramètres options — mode image_to_video

Tous optionnels. Valeurs non fournies → defaults appliqués par le worker.

CléTypeDéfautDescription
textstring""Texte affiché en overlay. Vide = pas de texte. Max 500 caractères.
font_sizeint60Taille de police en pixels. Plage : 10–300. Valeurs conseillées : 36, 48, 60, 72, 96.
text_colorstring"white"Couleur du texte (ex: white, yellow, #ffffff, 0xffffff).
text_positionstring"center"Position du texte : center, top, bottom.
boxbooltrueFond semi-transparent derrière le texte.
box_colorstring"black@0.4"Couleur + opacité du fond texte au format FFmpeg : couleur@opacité. Couleurs : black, white, yellow, #ff4444, #00ccff, #ff8800, #ff69b4… Opacité : 0.0–1.0 (ex: black@0.4 = noir à 40%, white@0.70 = blanc à 70%).
fade_durationfloat0.5Durée du fondu in/out en secondes (0–2). Le texte est inclu dans le fondu. 0 = pas de fondu.
widthint1080Largeur vidéo en pixels (64–3840, forcé pair). Combos standard : 1080/1920/720/1280.
heightint1920Hauteur vidéo en pixels (64–3840, forcé pair).
fpsint24Fréquence d'images (1–60).
image_fitstring"contain"Mode de cadrage : contain = l'image entière est visible, les bandes vides sont remplies par bg_color (letterbox/pillarbox) ; cover = l'image est zoomée pour remplir le cadre entier, centrée, les bords excédentaires sont rognés (aucune bande noire). Le paramètre bg_color est ignoré en mode cover.
bg_colorstring"black"Couleur de fond (padding) si l'image ne remplit pas la résolution cible — pertinent uniquement avec image_fit=contain (ex: black, white, #1a1a2e).
enable_image_motionboolfalseActive l'animation de la photo. Si false, l'image reste statique. Si true, l'effet défini par image_motion_effect est appliqué via le filtre FFmpeg zoompan.
image_motion_effectstring"ken_burns"Effet d'animation (ignoré si enable_image_motion est false). Valeurs acceptées : 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. Valeur par défaut si absente ou invalide : ken_burns.

Paramètres options — Modifier l'audio (mix_audio)

Disponible uniquement avec mode=mix_audio. Ignoré pour add_audio.

CléTypeDéfautDescription
mp3_volumefloat1.0Volume du MP3 superposé (0.0 = muet, 1.0 = volume original, 2.0 = double). Valeurs au-delà de 1.0 peuvent saturer.

Réponse succès (HTTP 200)

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

Exemple curl — mode image_to_video

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@scene.jpg" \ -F "videos[]=@narration.mp3" \ -F "mode=image_to_video" \ -F 'options={"text":"Chapitre 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"}' # image_fit : "contain" (défaut, image entière visible + fond) | "cover" (zoom centré, remplit le cadre) # bg_color : pertinent uniquement avec image_fit=contain # enable_image_motion : true = animation active, false (défaut) = image statique # 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

Exemple curl — Modifier l'audio

# Remplacer l'audio (supprime l'original) curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@ma_video.mp4" \ -F "videos[]=@ma_musique.mp3" \ -F "mode=add_audio" # Conserver l'audio original + superposer le MP3 curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@ma_video.mp4" \ -F "videos[]=@ma_musique.mp3" \ -F "mode=mix_audio" \ -F 'options={"mp3_volume":0.7}' # mp3_volume : 0.0 (muet) → 1.0 (volume original, défaut) → 2.0 (amplifié)

Exemple curl — Fusionner des vidéos

curl -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_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> Statut d'un job

Statuts possibles

StatutSignificationChamps supplémentaires
queued En file d'attente, pas encore traité queue_position, queue_total, eta_minutes
processing Traitement FFmpeg en cours
ready Terminé — fichier disponible download_url
error Échec du traitement error (message)

Réponses selon le statut

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

Exemple curl

curl -H "Authorization: Bearer rvm_votre_token" \ "https://rapidvideomaker.com/api/v1/jobs.php?job_id=a3f1c8..."
GET /api/download.php?job_id=<hex32> Téléchargement du fichier final

Retourne le fichier MP4 final en streaming (Content-Type: video/mp4). Ne nécessite pas de token — l'URL est suffisamment opaque. Disponible uniquement si le statut est ready.

Le fichier est conservé 2 heures après la fin du job, puis supprimé. Téléchargez-le dès que le statut passe à ready.

Paramètre optionnel

ParamètreDescription
filenameNom suggéré pour le fichier téléchargé (ex: ma-video.mp4)

Exemple curl

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

Webhooks

Le webhook est une alternative au polling : au lieu d'interroger le statut toutes les X secondes, vous fournissez une URL et le serveur vous appelle automatiquement quand le job se termine.

Fonctionnement

  1. Passez callback_url dans le POST /api/v1/render.php
  2. La réponse contient un webhook_secret — conservez-le pour vérifier les signatures
  3. Quand le job passe à ready ou error, le serveur envoie un POST JSON signé vers votre URL
  4. Vérifiez la signature avec HMAC-SHA256(webhook_secret, corps_brut)
Contraintes : callback_url doit être une URL publiquement accessible (http ou https). Les adresses IP privées, loopback et réservées sont bloquées côté serveur. Timeout : 10 secondes.

Payload reçu

{ "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 envoyés par le serveur

HeaderValeur
Content-Typeapplication/json
X-RVM-Signaturesha256=<hmac_hex> — signature HMAC-SHA256 du corps brut
X-RVM-Job-IdLe job_id concerné

Vérification de la signature

# 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) # Dans votre endpoint Flask/FastAPI : sig = request.headers.get("X-RVM-Signature", "") if not verify_webhook(WEBHOOK_SECRET, request.data, sig): return "Signature invalide", 403 data = request.get_json()

Codes d'erreur

HTTPcode JSONCause
401unauthorizedToken absent, invalide ou révoqué
400missing_filesAucun fichier reçu
400too_few_filesMoins de 2 fichiers envoyés
400too_many_filesPlus de 20 fichiers envoyés
400invalid_mimeFichier non supporté — seuls MP4, MP3 et images JPG/PNG sont acceptés (MIME vérifié par magic bytes)
400wrong_file_countLe nombre de fichiers ne correspond pas au mode choisi (ex : 3 fichiers avec mode=add_audio qui en exige 2)
400wrong_file_typesLes types de fichiers ne correspondent pas au mode choisi (ex : 2 MP4 avec mode=add_audio qui exige 1 MP4 + 1 MP3 ; ou 1 MP4 + 1 MP3 avec mode=image_to_video)
400invalid_file_combinationCombinaison de fichiers sans mode précisé ne correspond à aucun mode supporté
400invalid_optionsLe champ options n'est pas un JSON valide ou contient un objet attendu
400invalid_optionUne valeur dans options est invalide (couleur, nom de police, position…)
400file_too_largeUn fichier dépasse 500 MB
400invalid_orderLe tableau order n'est pas une permutation valide
400invalid_job_idFormat job_id incorrect (doit être hex 32 chars)
404job_not_foundJob introuvable — job_id inconnu ou jamais existé
410job_expiredJob expiré — a existé mais la fenêtre de récupération de 2 h est dépassée
429quota_exceeded10 jobs réussis/jour atteints (tous modes confondus)
429rate_limitedPlus de 12 appels/min sur /api/v1/jobs.php — attendre Retry-After secondes
500server_errorErreur interne serveur

Exemples d'intégration

Exemples pour chaque mode — installe requests avec pip install requests.

Configuration commune

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

Mode image_to_video — image + audio → vidéo

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": "Chapitre 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", # ignoré si image_fit="cover" "enable_image_motion": True, "image_motion_effect": "ken_burns", }), }, )

Modifier l'audio

# Remplacer l'audio (supprime l'original) — mode=add_audio with open("video.mp4", "rb") as fv, open("musique.mp3", "rb") as fa: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("video.mp4", fv, "video/mp4")), ("videos[]", ("musique.mp3", fa, "audio/mpeg")), ], data={"mode": "add_audio"}, ) # Conserver l'audio original + superposer le MP3 — mode=mix_audio with open("video.mp4", "rb") as fv, open("musique.mp3", "rb") as fa: resp = requests.post( f"{API_BASE}/api/v1/render.php", headers=HEADERS, files=[ ("videos[]", ("video.mp4", fv, "video/mp4")), ("videos[]", ("musique.mp3", fa, "audio/mpeg")), ], data={"mode": "mix_audio", "options": json.dumps({"mp3_volume": 0.7})}, # mp3_volume : 0.0 = muet, 1.0 = volume original (défaut), 2.0 = amplifié )

Fusionner des vidéos

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 + téléchargement (commun à tous les modes)

resp.raise_for_status() job_id = resp.json()["job_id"] print(f"Job créé : {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"En file — position {pos}, ETA ~{eta} min") elif status == "processing": print("Traitement en cours…") elif status == "ready": download_url = data["download_url"] break elif status == "error": sys.exit(f"Erreur : {data.get('error')}") time.sleep(5) else: sys.exit("Timeout : job non terminé après 10 min") r = requests.get(download_url, stream=True) with open("resultat.mp4", "wb") as f: for chunk in r.iter_content(65536): f.write(chunk) print("Téléchargé : resultat.mp4")

Deux approches possibles dans n8n : polling (boucle sur le statut) ou webhook (le serveur appelle n8n). Le webhook est recommandé — plus propre, zéro charge inutile.

Approche A — Webhook (recommandée)

3 nœuds seulement, pas de boucle.

Nœud 1 — Webhook trigger
Ajoutez un nœud Webhook en entrée de workflow (méthode POST). Notez l'URL générée, ex : https://votre-n8n.com/webhook/rvm-callback.

Nœud 2 — Créer le job (HTTP Request)

MethodPOST
URLhttps://rapidvideomaker.com/api/v1/render.php
AuthenticationHeader Auth — Authorization: Bearer rvm_…
Body Content TypeForm-Data Multipart
Body paramsChamp Binary videos[] pour chaque clip + champ Text callback_url = URL du nœud Webhook ci-dessus

Conservez webhook_secret de la réponse dans une variable de workflow pour vérifier la signature à la réception.

Nœud 3 — Traiter le résultat (dans le workflow déclenché par le Webhook)
Quand n8n reçoit le POST du serveur, $json.status vaut ready ou error. Si ready, $json.download_url contient l'URL de téléchargement directe.

Pour vérifier la signature : comparez {{ $headers['x-rvm-signature'] }} avec sha256= + HMAC-SHA256 du corps brut calculé depuis votre webhook_secret. Utilisez un nœud Code avec crypto.createHmac('sha256', secret).update(body).digest('hex').

Approche B — Polling (sans webhook)

5 nœuds, boucle sur le statut toutes les 10 s.

Nœud 1 — Créer le job — même config que ci-dessus, sans callback_url.

Nœud 2 — Wait — 10 secondes.

Nœud 3 — Interroger le statut (HTTP Request GET)

URLhttps://rapidvideomaker.com/api/v1/jobs.php
Query paramsjob_id = {{ $('Nœud 1').item.json.job_id }}
AuthenticationHeader Auth — même token

Nœud 4 — If : {{ $json.status }} === 'ready' → true : Nœud 5 / false : retour Nœud 2.

Ajoutez un compteur d'itérations dans un nœud Set pour couper la boucle après 60 tentatives (10 min max) et éviter une boucle infinie.

Nœud 5 — Télécharger : HTTP Request GET sur {{ $json.download_url }}, Response Format File.

Étape 1 — Créer le job (choisir un mode)

# Mode fusion JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@clip1.mp4" -F "videos[]=@clip2.mp4") # Mode add_audio (remplacer l'audio) JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@video.mp4" -F "videos[]=@musique.mp3" \ -F "mode=add_audio") # Mode mix_audio (superposer musique à 70% de volume) JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@video.mp4" -F "videos[]=@musique.mp3" \ -F "mode=mix_audio" -F 'options={"mp3_volume":0.7}') # Mode image_to_video JOB=$(curl -s -X POST https://rapidvideomaker.com/api/v1/render.php \ -H "Authorization: Bearer rvm_votre_token" \ -F "videos[]=@scene.jpg" -F "videos[]=@narration.mp3" \ -F "mode=image_to_video" \ -F 'options={"text":"Chapitre 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"

Étape 2 — Polling

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

Étape 3 — Télécharger

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

Bonnes pratiques

Les fichiers résultants sont conservés 2 heures après la fin du job, puis supprimés automatiquement. Téléchargez votre vidéo dès que le statut passe à ready.