RapidVideoMaker
계정 만들기

API RapidVideoMaker

The REST API lets you process video files from any HTTP client — Python scripts, n8n workflows, third-party tools. Five modes available: Merge videos (multiple MP4), Edit audio (1 MP4 + 1 MP3), Create a video (1 JPG/PNG + 1 MP3), Overlay video (2 MP4 picture-in-picture). Processing is asynchronous: submit files, then poll for the result.

무료로 API 토큰 받기
API 토큰을 받으려면 계정을 만드세요 — 하루 20개 요청 포함.
무료 계정 만들기 이미 계정이 있으신가요? 로그인

완전한 워크플로

모든 통합은 동일한 4단계 순서를 따릅니다:

1
작업 생성 — POST /api/v1/render.php
Bearer 토큰과 함께 파일을 multipart/form-data로 전송합니다. 1개의 JPG/PNG 이미지 + 1개의 MP3 + mode=image_to_video → 비디오 생성. 1개의 MP4 + 1개의 MP3 → 오디오 편집. 여러 MP4 → 병합. 서버는 고유한 job_id를 반환합니다.
2
작업 대기 — GET /api/v1/jobs.php?job_id=…
이 엔드포인트를 주기적으로(5~10초마다) 폴링합니다. 작업은 queuedprocessingready(또는 error)로 진행됩니다.
3
다운로드 URL 가져오기
상태가 ready가 되면 응답에 사용 가능한 download_url 필드가 포함됩니다.
4
파일 다운로드 — GET /api/download.php?job_id=…
최종 MP4를 다운로드합니다. 파일은 작업 완료 후 2시간 동안 사용 가능하며 그 후 자동으로 삭제됩니다.

인증

모든 요청에는 API 토큰이 포함되어야 합니다. 두 가지 형식이 허용됩니다:

# 인증 — 모든 요청에는 API 토큰이 포함되어야 합니다. 두 가지 형식이 허용됩니다: Authorization: Bearer rvm_your_token_here # Alternative X-API-Key: rvm_your_token_here

토큰은 회원 공간에서 사용할 수 있습니다 — 계정당 하나의 토큰, 등록 시 자동으로 생성됩니다.

할당량

각 회원 계정은 웹 인터페이스와 API 간에 공유되는 하루 20개의 요청을 갖습니다. 실패한 작업은 할당량을 소비하지 않습니다. 카운터는 UTC 자정에 재설정됩니다.

POST 응답에는 quota_usedquota_remaining이 포함됩니다. 제한을 초과하면 서버는 429로 응답합니다.

인터페이스 + API = 동일한 카운터. 웹 인터페이스에서 만든 비디오와 API 요청은 각각 동일한 일일 할당량에서 1크레딧을 소비합니다.

대기열

한 번에 하나의 작업이 처리됩니다. 여러 작업이 동시에 제출되면 대기열에 추가되어 순서대로 처리됩니다. 대기 중에는 상태 응답에 다음이 포함됩니다:

속도 제한이 적용됩니다: /api/v1/jobs.php 엔드포인트는 토큰당 분당 12회까지 허용됩니다. 권장: 호출 간격 10초.

사용 가능한 전환 효과

직접 병합에는 transition_type=none(기본값)을 전달하거나, 클립 사이의 페이드를 위해 아래 유형 중 하나를 사용하세요:

none fade fadeblack dissolve wipeleft wiperight slideleft slideright zoomin circleclose

기간(transition_duration)은 0.2~2.0초입니다.

엔드포인트

POST /api/v1/render.php 비디오 처리 작업을 생성합니다

Five modes, accessible via the mode field (omit mode with multiple MP4s to auto-detect fusion):

사용법API 모드필요한 파일설명
비디오 병합 fusion 2~20개의 MP4 파일 클립은 제공된 순서대로 끝에서 끝으로 조립됩니다. 클립 사이에 선택적 전환 효과를 설정할 수 있습니다.
오디오 편집 add_audio 또는 mix_audio 1개의 MP4 + 1개의 MP3 비디오의 오디오 트랙을 교체하거나 강화합니다. 비디오 트랙은 재인코딩되지 않습니다.

add_audio — 원본 오디오가 삭제되고 MP3로 완전히 교체됩니다.
mix_audio — 원본 오디오가 유지되고 MP3가 오버레이됩니다.
비디오 만들기 image_to_video 1개의 JPG/PNG + 1개의 MP3 정지 이미지와 오디오 파일에서 비디오를 생성합니다. 텍스트 오버레이, 페이드, 해상도 및 fps는 options 필드를 통해 구성할 수 있습니다.
Overlay video overlay_video 2 MP4 두 번째 동영상을 메인 동영상 위에 겹칩니다. 위치, 크기, 불투명도, 오디오는 options 필드로 설정 가능합니다.
텍스트를 MP3로 text_to_mp3 (텍스트만) 텍스트를 음성으로 변환하고 MP3 파일을 반환합니다. 파일 업로드 불필요 — mode=text_to_mp3, text, lang을 폼 필드로 전송하세요. 사이트의 20개 언어 모두 지원.
엄격한 검증: 각 모드에는 정확한 파일 수와 유형이 필요합니다. add_audiomix_audio는 1개의 MP4 + 1개의 MP3만 허용합니다. image_to_video는 1개의 JPG/PNG + 1개의 MP3만 허용합니다.
기간 규칙: 오디오 및 image_to_video 모드에서 결과 기간은 MP3 기간에 고정됩니다.

공통 매개변수 (multipart/form-data)

필드유형필수설명
videos[]File[]처리할 파일. 모드에 따라 다릅니다: 2~20개의 MP4, 또는 1개의 MP4 + 1개의 MP3, 또는 1개의 이미지(JPG/PNG) + 1개의 MP3. 파일당 최대 500 MB.
modestring*image_to_video | add_audio | mix_audio. 이 세 가지 모드에 필수입니다. 모든 파일이 MP4인 경우에만 무시됩니다(fusion).
orderJSONfusion 모드만 — 클립 순서를 정의하는 인덱스의 JSON 배열.
transition_typestringfusion 모드만. 기본값: none.
transition_durationfloatfusion 모드만. 기간 0.2~2.0초. 기본값: 0.5.
optionsJSONimage_to_video 모드만 — 렌더 매개변수의 JSON 객체.
callback_urlstring작업 완료 시 호출되는 공개 URL(http/https). 응답에 webhook_secret이 포함됩니다.

options 매개변수 — image_to_video 모드

모두 선택 사항입니다. 제공되지 않은 값 → 워커가 기본값을 적용합니다.

유형기본값설명
textstring""오버레이로 표시되는 텍스트. 비어 있으면 텍스트 없음. 최대 500자.
font_sizeint60픽셀 단위의 글꼴 크기. 범위: 10~300.
text_colorstring"white"텍스트 색상(예: white, yellow, #ffffff).
text_positionstring"center"텍스트 위치: center, top, bottom.
boxbooltrue텍스트 뒤의 반투명 배경.
box_colorstring"black@0.4"FFmpeg 형식의 색상 + 불투명도: color@opacity.
fade_durationfloat0.5초 단위의 페이드 인/아웃 기간(0~2). 0 = 효과 없음.
widthint1080픽셀 단위의 비디오 너비(64~3840, 짝수 강제).
heightint1920픽셀 단위의 비디오 높이(64~3840, 짝수 강제).
fpsint24프레임 레이트(1~60).
image_fitstring"contain"프레이밍 모드: contain = 전체 이미지 표시; cover = 전체 프레임을 채우도록 확대.
bg_colorstring"black"이미지가 대상 해상도를 채우지 않을 때의 배경 색상.
enable_image_motionboolfalse사진 애니메이션을 활성화합니다. false이면 이미지가 정적으로 유지됩니다.
image_motion_effectstring"ken_burns"애니메이션 효과. 허용 값: zoom_in, zoom_out, pan_left_to_right, ken_burns 등.
motion_intensityfloat1.0사진 애니메이션 강도(0.25~2.0). 줌 진폭과 팬 속도를 곱합니다.
text_effectstring"none"텍스트 오버레이 애니메이션. 허용 값: none, fade_in, slide_up, bounce.
text_effect_intensityfloat1.0텍스트 애니메이션 강도(0.25~2.0). text_effectnone이면 무시됩니다.
text_border_widthint0픽셀 단위의 문자 주변 검은 외곽선 두께(0 = 비활성화).
text_modestring"static"텍스트 표시 모드. static(기본값): 첫 프레임부터 전체 텍스트 표시. word_by_word: word_reveal_speed 속도로 단어가 하나씩 표시됩니다. text_effect와 동시 사용 불가: text_mode=word_by_word이면 text_effect는 무시됩니다.
word_reveal_speedfloat1.5초당 단어 표시 속도(0.3–5.0, 기본값 1.5). text_mode=word_by_word일 때만 사용. OpenAI TTS 동기화 추천 값: 2.0.
word_animstring"none"각 단어 등장 애니메이션. none (기본값): 즉시 표시. fade: 각 단어가 0.2초 페이드로 이전 블록과 크로스페이드. text_mode=word_by_word에서만.

options 파라미터 — overlay_video 모드

모두 선택 사항. 업로드 순서가 중요합니다: 첫 번째 파일은 메인 영상(배경), 두 번째 파일은 오버레이(전경)입니다. chroma_key로 오버레이의 그린스크린을 제거할 수 있습니다.

유형기본값설명
positionstring"bottom-right"오버레이를 배치할 모서리: top-left, top-right, bottom-left, bottom-right, 또는 center.
scalefloat0.30메인 영상 너비 대비 오버레이 크기 비율. 0.25 = 너비의 25%. 범위: 0.05–1.0.
opacityfloat1.0오버레이 투명도. 1.0 = 완전 불투명, 0.0 = 보이지 않음.
marginint10오버레이와 프레임 가장자리 사이의 픽셀 수. position=center이면 무시됩니다. 범위: 0–200.
audiostring"main"유지할 오디오. main: 메인 영상만. overlay: 오버레이만. mix: 두 트랙 혼합.
chroma_keyboolfalsetrue로 설정하면 오버레이의 순수 초록색(#00FF00) 배경을 제거합니다. 그린스크린에서 촬영한 웹캠이나 애니메이션에 유용합니다.
chroma_similarityfloat0.20그린스크린 허용 범위. 낮음 = 엄격한 일치. 높음 = 더 넓은 제거. 권장값: 디지털 그린 0.10–0.20, 물리적 스크린 0.25–0.45. 범위: 0.01–0.60.

options 매개변수 — 오디오 편집(mix_audio)

mode=mix_audio에서만 사용 가능합니다. add_audio에서는 무시됩니다.

유형기본값설명
mp3_volumefloat1.0오버레이된 MP3의 볼륨(0.0 = 음소거, 1.0 = 원래 볼륨, 2.0 = 두 배).

성공 응답 (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..." }

curl 예시 — 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)

curl 예시 — 오디오 편집

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

curl 예시 — 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)

curl 예시 — 비디오 병합

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> 작업 상태

가능한 상태

상태의미추가 필드
queued 대기열 중, 아직 처리되지 않음 queue_position, queue_total, eta_minutes
processing FFmpeg 처리 중
ready 완료 — 파일 사용 가능 download_url, created_at, expires_at
error 처리 실패 error (message)

상태별 응답

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

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)

공통 매개변수 (multipart/form-data)

apidocs_th_param유형기본값apidocs_th_desc
pageinteger1Page number (starts at 1)
limitinteger20Results per page (max 50, default 20)

상태별 응답

{ "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 YouTube 또는 TikTok에 동영상 게시

하나 이상의 소셜 계정에 완료된 job(status=ready)을 게시합니다. 토큰은 회원 계정 것이어야 합니다(관리자 토큰 불가).

전제 조건: 이 endpoint를 사용하기 전에 회원 영역의 게시 페이지에서 소셜 계정(YouTube, TikTok)을 OAuth로 연결해야 합니다. 각 계정의 account_id가 거기에 표시됩니다.

공통 매개변수 (multipart/form-data)

apidocs_th_param유형apidocs_th_requiredapidocs_th_desc
job_idstringapidocs_required완료된 동영상의 job ID(hex 32자)
publicationsarrayapidocs_required게시 객체 배열(최대 10개)

게시 객체

apidocs_th_param유형apidocs_th_requiredapidocs_th_desc
account_idintegerapidocs_required연결된 소셜 계정의 ID — 회원 영역의 게시 페이지에서 확인 가능
titlestring동영상 제목(최대 512자)
descriptionstring동영상 설명(최대 5,000자)
tagsstring쉼표로 구분된 태그(최대 1,024자)
visibilitystringpublic | private | unlisted — 기본값: public
tiktok_modestringdraft | direct — TikTok 전용 — 기본값: direct
tiktok_privacystringdirect 모드TikTok 전용 — direct 모드에서 필수
allow_commentbooleanTikTok 전용 — 댓글 허용
allow_duetbooleanTikTok 전용 — 듀엣 허용
allow_stitchbooleanTikTok 전용 — 스티치 허용
your_brandbooleanTikTok 전용 — 유기적 홍보 콘텐츠("내 브랜드").
branded_contentbooleanTikTok 전용 — 브랜드 콘텐츠 공개
tiktok_cover_msintegerTikTok 전용 — 커버 프레임 타임스탬프(ms, 0–60,000, 기본값 1,000)

상태별 응답

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

게시별 오류 코드

apidocs_th_code의미
job_not_readyjob이 아직 완료되지 않았습니다
mode_not_supportedtext_to_mp3 job은 게시할 수 없습니다
account_not_found계정을 찾을 수 없거나 연결이 끊어졌습니다
tiktok_privacy_requireddirect 모드에는 개인정보 보호 수준이 필요합니다
publication_failed업로드 중 제공자가 오류를 반환했습니다

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> 최종 파일 다운로드

최종 MP4 파일을 스트림으로 반환합니다(Content-Type: video/mp4). 토큰 불필요. 상태가 ready일 때만 사용 가능.

파일은 작업 완료 후 2시간 동안 보관되며 그 후 삭제됩니다. 상태가 ready가 되는 즉시 다운로드하세요.

선택적 매개변수

매개변수설명
filename다운로드할 파일의 권장 이름(예: my-video.mp4)

curl 예시

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

Webhooks

Webhook은 폴링의 대안입니다: X초마다 상태를 확인하는 대신 URL을 제공하면 서버가 작업 완료 시 자동으로 알립니다.

작동 방식

  1. /api/v1/render.php에 대한 POST에 callback_url을 포함합니다
  2. 응답에는 webhook_secret이 포함됩니다 — 서명 확인을 위해 보관하세요
  3. 작업이 ready 또는 error가 되면 서버는 귀하의 URL로 서명된 JSON POST를 전송합니다
  4. HMAC-SHA256(webhook_secret, raw_body)로 서명을 확인합니다
제약 조건: callback_url은 공개적으로 접근 가능한 URL(http 또는 https)이어야 합니다. 사설, 루프백 및 예약 IP 주소는 서버 측에서 차단됩니다. 타임아웃: 10초.

수신된 페이로드

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

서버가 전송하는 헤더

헤더
Content-Typeapplication/json
X-RVM-Signaturesha256=<hmac_hex> — 원시 본문의 HMAC-SHA256 서명
X-RVM-Job-Id관련 job_id

서명 확인

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

오류 코드

HTTPJSON 코드원인
401unauthorized토큰이 누락, 유효하지 않거나 취소되었습니다
400missing_files수신된 파일이 없습니다
400too_few_files2개 미만의 파일이 전송되었습니다
400too_many_files20개를 초과하는 파일이 전송되었습니다
400invalid_mime지원되지 않는 파일 — MP4, MP3, JPG/PNG만 허용됩니다
400wrong_file_count파일 수가 선택한 모드와 일치하지 않습니다
400wrong_file_types파일 유형이 선택한 모드와 일치하지 않습니다
400invalid_file_combination지정된 모드 없이 파일 조합이 지원되는 모드와 일치하지 않습니다
400invalid_optionsoptions 필드가 유효한 JSON이 아닙니다
400invalid_optionoptions의 값이 유효하지 않습니다
400file_too_large파일이 500 MB를 초과합니다
400invalid_orderorder 배열이 유효한 순열이 아닙니다
400invalid_job_idjob_id 형식이 올바르지 않습니다(32자 16진수여야 함)
404job_not_found작업을 찾을 수 없습니다 — job_id가 알 수 없거나 존재한 적이 없습니다
410job_expired작업이 만료되었습니다 — 존재했지만 2시간 복구 기간이 지났습니다
429quota_exceeded하루 20개의 성공 작업 한도에 도달했습니다
429rate_limited/api/v1/jobs.php에서 분당 12회를 초과했습니다
500server_error내부 서버 오류

통합 예시

각 모드의 예시 — pip install requestsrequests 설치.

공통 구성

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

image_to_video 모드 — 이미지 + 오디오 → 비디오

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

오디오 편집

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

overlay_video 모드 — PIP (화면 속 화면)

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

비디오 병합

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

폴링 + 다운로드(모든 모드에 공통)

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

n8n에서의 두 가지 접근 방식: 폴링(상태 루프) 또는 Webhook(서버가 n8n 호출). Webhook 권장.

방법 A — Webhook(권장)

노드 3개만, 루프 없음.

노드 1 — Webhook 트리거
워크플로 입력으로 Webhook 노드를 추가합니다(메서드 POST).

노드 2 — 작업 생성(HTTP 요청)

메서드POST
URLhttps://rapidvideomaker.com/api/v1/render.php
인증Header Auth — Authorization: Bearer rvm_…
본문 콘텐츠 유형Form-Data Multipart
Body params각 클립에 대한 바이너리 필드 videos[] + 텍스트 필드 callback_url

서명을 확인하기 위해 응답의 webhook_secret을 워크플로 변수에 저장하세요.

노드 3 — 결과 처리(Webhook 트리거 워크플로에서)
n8n이 서버의 POST를 수신하면 $json.statusready 또는 error입니다.

서명을 확인하려면: {{ $headers['x-rvm-signature'] }}webhook_secret의 HMAC-SHA256과 비교하세요.

방법 B — 폴링(Webhook 없이)

노드 5개, 10초마다 상태 루프.

노드 1 — 작업 생성callback_url 없이 동일한 설정.

노드 2 — 대기 — 10초.

노드 3 — 상태 폴링(HTTP 요청 GET)

URLhttps://rapidvideomaker.com/api/v1/jobs.php
쿼리 매개변수job_id = {{ $('노드 1').item.json.job_id }}
인증헤더 인증 — 동일한 토큰

노드 4 — If: {{ $json.status }} === 'ready' → true: 노드 5 / false: 노드 2로 돌아가기.

무한 루프를 방지하기 위해 Set 노드에 반복 카운터를 추가하세요.

노드 5 — 다운로드: {{ $json.download_url }}에서 HTTP 요청 GET.

1단계 — 작업 생성(모드 선택)

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

2단계 — 폴링

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

3단계 — 다운로드

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

모범 사례

결과 파일은 작업 완료 후 2시간 동안 보관되며 그 후 자동으로 삭제됩니다.