광고 자리 모집 중 · 제휴 문의

Luma Dream Machine API 연동 가이드: 자동 비디오 생성 및 비동기 폴링 파이프라인 구축

365Finds Editorial
Wiki 문서 11,430편 수록

내 AI에서 365 Wiki 사용하기

아래 프롬프트를 복사해 평소 사용하는 AI에 붙여넣고 바로 질문하세요.

전체 Skill 다운로드

먼저 프롬프트로 체험해 보세요. 365 Wiki를 자주 쓴다면 전체 365Wiki Skill을 설치해 매번 붙여넣는 수고를 줄일 수 있습니다. 평소 쓰는 AI가 없다면 Gemini나 Microsoft Copilot 웹 버전도 사용할 수 있습니다.

크리에이티브 엔지니어링 팀과 미디어 파이프라인 개발자가 대규모 AI 비디오 제작을 자동화할 때 마주하는 가장 큰 장벽은 웹 브라우저 기반의 수동 조작 방식입니다. 기업 내 디지털 자산 관리(DAM) 시스템, 이커머스 상품 카탈로그, 프로그래밍 방식의 VFX 파이프라인과 연동하기 위해서는 안정적인 API 통합이 필수적입니다. Luma Dream Machine API는 Ray 시리즈 생성형 비디오 기반 모델(Ray 2 및 Ray 2 Flash 포함)에 대한 프로그래밍 방식의 접근을 지원합니다. RESTful 엔드포인트와 공식 Python 및 Node.js SDK를 활용하면 인증, 텍스트/이미지 기반 비디오 렌더링 요청, 정밀한 카메라 궤적 제어, 비디오 자산의 자동 수집 워크플로를 손쉽게 구축할 수 있습니다.

비디오 렌더링은 전형적인 비동기 고연산 작업입니다. 신뢰할 수 있는 자동화 파이프라인을 구축하려면 안전한 API 인증, 키프레임과 카메라 제어가 포함된 작업 제출, 장애 복구력을 갖춘 비동기 폴링 또는 웹훅 처리, 그리고 완성된 자산의 영구 스토리지 저장이라는 네 가지 핵심 단계가 필요합니다.


아키텍처 개요

이커머스 상품 이미지를 5초 길이의 동적 프로모션 영상으로 대량 변환하는 배치 파이프라인을 예로 들면, 시스템 라이프사이클은 다음과 같이 진행됩니다.

[공개 이미지 저장소 (S3 / CDN)] 
               │
               ▼
   [작업 제출: POST /generations] ──> [Luma Ray 엔진 (대기열 / 렌더링 중)]
               │                                      │
               ├──────────────────────────────────────┘
               ▼
[폴링 루프 (지수 백오프) 또는 웹훅 (callback_url)]
               │
               ▼
  [작업 상태: Completed / Failed]
               │
               ├─> Failed: failure_reason 기록 및 정책 모니터링
               └─> Completed: assets.video 스트리밍 다운로드 후 클라우드 저장
  1. 입력 자산 배치: 원본 이미지는 공용 인터넷에서 접근 가능한 HTTPS CDN 또는 사전 서명된 스토리지 URL에 호스팅합니다.
  2. 작업 제출: 파이프라인이 /dream-machine/v1/generations 엔드포인트로 POST 요청을 전송하며, 프롬프트, 모델 버전, 카메라 제어 컨셉, 키프레임을 지정합니다.
  3. 렌더링 수행: Luma의 스케줄러가 작업을 큐에 등록하고(queued), 영상 합성 단계(dreaming)를 거쳐 최종 상태(completed 또는 failed)에 도달합니다.
  4. 완료 상태 감지: 작업 워커가 무작위 지터를 포함한 지수 백오프 폴링을 수행하거나 웹훅 콜백을 수신합니다.
  5. 자산 영구 저장: 생성된 MP4 비디오 임시 서명 URL(assets.video)을 확보하고, 만료되기 전에 사내 스토리지로 스트리밍 다운로드합니다.

인증 및 SDK 환경 구성

먼저 Luma API Platform에서 API 키를 발급받아 환경 변수로 등록합니다.

export LUMAAI_API_KEY="your_luma_api_key_here"

공식 Python SDK를 사용하면 인증 헤더 조립과 클라이언트 설정이 자동으로 처리됩니다.

pip install lumaai requests

SDK 없이 직접 HTTP 통신을 구성할 경우 표준 Bearer 토큰 헤더를 포함해야 합니다.

Authorization: Bearer your_luma_api_key_here
Content-Type: application/json

비디오 생성 작업 제출

Luma Dream Machine API는 텍스트 투 비디오와 이미지 투 비디오(I2V)를 모두 지원합니다. 상품 동영상 제작이나 비주얼 콘셉트 확장의 경우 keyframes를 이용한 이미지 투 비디오 방식이 가장 널리 쓰입니다.

핵심 요청 매개변수

매개변수타입필수 여부설명
promptstring필수움직임, 조명, 재질 및 연출을 지시하는 프롬프트.
modelstring선택ray-2(고화질 표준 플래그십) 또는 ray-flash-2(저지연 고속 생성).
aspect_ratiostring선택화면비: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9, 9:21.
resolutionstring선택해상도: 540p, 720p, 1080p, 4k.
durationstring선택비디오 길이: 5s 또는 9s.
loopboolean선택앞뒤가 매끄럽게 연결되는 루프 비디오 생성 여부(true 또는 false).
keyframesobject선택시작 프레임(frame0) 또는 종료 프레임(frame1)의 이미지 URL/기존 생성 ID.
conceptsarray선택특정 연출 개념(예: 카메라 워크 [{"key": "dolly_zoom"}]).
callback_urlstring선택렌더링 상태 변경을 통보받을 웹훅 수신 URL.

카메라 모션(Camera Motion) 제어 가이드

Ray 엔진은 전문적인 영상 촬영 용어를 자연어로 이해합니다. 프롬프트에 직접 작성하거나 지원되는 카메라 모션 목록 API(GET /dream-machine/v1/generations/camera_motion/list)에서 확인된 표준 표현을 사용할 수 있습니다. 주요 모션은 다음과 같습니다.

Python 구현: 이미지 투 비디오 작업 제출

import os
from lumaai import LumaAI

client = LumaAI(auth_token=os.environ.get("LUMAAI_API_KEY"))

def dispatch_ecommerce_render(image_url: str, product_title: str) -> str:
    """
    시작 키프레임과 카메라 모션을 지정하여 이미지 투 비디오 렌더링 요청
    """
    prompt = (
        f"Cinematic studio commercial presentation of {product_title}, "
        "dramatic rim light, revolving product podium, camera orbit right slowly"
    )
    
    generation = client.generations.create(
        prompt=prompt,
        model="ray-2",
        resolution="720p",
        duration="5s",
        aspect_ratio="16:9",
        loop=True,
        keyframes={
            "frame0": {
                "type": "image",
                "url": image_url
            }
        }
    )
    
    print(f"작업 제출 완료, 작업 ID: {generation.id}")
    return generation.id

견고한 비동기 폴링 메커니즘 설계

비디오 생성은 모델과 서버 대기 상황에 따라 수십 초에서 수 분까지 소요됩니다. 작업 제출 시 API는 즉시 고유한 작업 ID(UUID v4)를 반환하므로, 백그라운드 프로세스는 GET /dream-machine/v1/generations/{id}를 주기적으로 호출해 상태를 확인해야 합니다.

단순 폴링 방식의 위험 요소

  1. 과도한 고주파 요청: 수백 밀리초 단위로 상태를 확인하면 HTTP 429(Rate Limit) 오류가 발생하고 IP가 일시 차단될 수 있습니다.
  2. 타임아웃 부재로 인한 프로세스 정체: 대기열 지연이나 비정상 상태 시 타임아웃을 두지 않으면 작업 스레드가 무한 대기 상태에 빠집니다.
  3. 콘텐츠 정책 위반 미처리: 안전 필터링에 걸려 생성이 실패하면 상태가 failed로 변경됩니다. 네트워크 예외만 잡고 generation.failure_reason을 확인하지 않으면 원인을 진단할 수 없습니다.

프로덕션 수준의 Python 폴링 및 다운로드 구현

다음 예제는 지수 백오프, 지터(Jitter), 타임아웃 보호, 대용량 파일 스트리밍 다운로드를 모두 적용한 코드입니다.

import os
import time
import random
import requests
from lumaai import LumaAI

def wait_and_download_render(
    generation_id: str,
    output_filename: str,
    base_interval: float = 4.0,
    max_interval: float = 16.0,
    timeout_seconds: float = 360.0
) -> str:
    """
    Luma 작업 상태를 폴링하고 완료 시 MP4 비디오를 다운로드
    """
    client = LumaAI(auth_token=os.environ.get("LUMAAI_API_KEY"))
    start_time = time.time()
    current_interval = base_interval

    while True:
        elapsed = time.time() - start_time
        if elapsed > timeout_seconds:
            raise TimeoutError(f"작업 {generation_id} 시간 초과 ({timeout_seconds}초 경과)")

        generation = client.generations.get(id=generation_id)
        state = generation.state

        if state == "completed":
            video_url = generation.assets.video
            print(f"렌더링 완료 ({elapsed:.1f}초 소요). 비디오 다운로드 시작...")
            
            # 대용량 메모리 부하를 방지하기 위해 스트리밍 방식으로 파일 기록
            response = requests.get(video_url, stream=True, timeout=30)
            response.raise_for_status()
            with open(output_filename, "wb") as f:
                for chunk in response.iter_content(chunk_size=1024 * 1024):
                    if chunk:
                        f.write(chunk)
                        
            print(f"비디오 저장 완료: {output_filename}")
            return output_filename

        elif state == "failed":
            reason = getattr(generation, "failure_reason", "알 수 없는 오류")
            raise RuntimeError(f"Luma 렌더링 실패 (ID: {generation_id}): {reason}")

        elif state in ("queued", "dreaming"):
            print(f"상태: [{state}] ({elapsed:.1f}초 경과). {current_interval:.1f}초 후 재확인...")
            time.sleep(current_interval + random.uniform(0.1, 0.9))
            current_interval = min(current_interval * 1.5, max_interval)

        else:
            print(f"정의되지 않은 상태 '{state}'. 대기 중...")
            time.sleep(current_interval)

대규모 처리 환경: 폴링과 웹훅의 비교

하루 수백~수천 건 이상의 비디오를 처리하는 대규모 파이프라인에서는 여러 개의 동기 폴링 스레드를 유지하는 것이 불필요한 시스템 리소스 낭비로 이어집니다.

callback_url을 활용한 이벤트 기반 파이프라인

작업 생성 시 callback_url을 지정할 수 있습니다.

generation = client.generations.create(
    prompt="A commercial bottle rotating against a minimalist background",
    model="ray-2",
    callback_url="https://api.yourcompany.com/webhooks/luma"
)

웹훅 동작 규격


프로덕션 운영 권장사항

  1. 즉각적인 미디어 자산 저장: assets.video에 제공되는 URL은 유효기간이 설정된 CDN 임시 서명 링크입니다. 데이터베이스에 해당 URL을 저장하지 말고, 완료 즉시 내부 Amazon S3, Google Cloud Storage, Cloudflare R2로 복제하십시오.
  2. 입력 이미지의 안정적인 호스팅: keyframes에 전달하는 이미지 URL은 퍼블릭 인터넷에서 지연 없이 직접 접근 가능해야 합니다. 방화벽 차단이나 응답 지연이 발생하면 렌더링이 즉시 중단됩니다.
  3. 동시성 및 멱등성 보장: 계정에 부여된 분당 요청 수(RPM)와 동시 실행 가능 작업 수를 확인하십시오. 재시도에 따른 이중 과금을 막기 위해 큐 단계에서 고유 멱등 키를 관리해야 합니다.
  4. 모델 계층별 활용: 대량의 소셜 미디어 배리에이션이나 아이디어 시안 단계에서는 비용 효율적인 ray-flash-2를 우선 적용하고, 최종 제품 홍보용 1080p 및 4k 고화질 영상에는 플래그십 ray-2를 배치하는 단계적 전략이 유리합니다.

참고 자료