Mobidoo

쿡북

이 문서는 영문 원고를 AI로 번역한 내용이라 표현이 어색할 수 있습니다.

여기 있는 레시피는 모두 실제 프로덕션 연동이 보내는 모양이며, 고객 데이터만 자리표시자로 바꿨습니다. acme/live-commerce, URL, 문구를 여러분 것으로 바꾸고 구조는 그대로 두세요.

한 번만 설정합니다.

typed output과 웹훅이 있는 라이브 커머스 run

가장 흔한 프로덕션 호출입니다. 제품 페이지, 호스트 이미지, 태그가 붙은 대본, 완성본과 각 씬을 이름 짓는 스키마, run당 cap, 그리고 웹훅. 본문은 파일에 두세요. 실제 대본은 셸 heredoc에 넣기엔 너무 깁니다.

run-body.json:

각 키가 하는 일:

있는 이유
instruction결정 사항: 대본을 그대로 쓸 것, 프레이밍, 넣지 말 것. 4000자 안쪽의 산문.
input데이터: 레시피는 아는 키(product_url, host_image_url, vo_language, script, price)를 읽고, 나머지는 맥락으로 따라갑니다. 여러분의 장부(sheet_no)를 넣어도 되지만 output으로 돌아오지는 않습니다.
output_schemafull_video가 완성본이고, scenes[]가 재시도할 수 있는 안정적인 id를 가진 클립 목록입니다. SumeMediaFile#은 내장 미디어 형태입니다. 모든 속성은 required이며, optional은 nullable로 표현합니다.
primary_output_keyprimary_output_url을 완성본으로 만들고, scenes는 채웠지만 full_video는 못 채운 run을 거짓 성공이 아니라 failed receipt로 바꿉니다.
generation_spend_cap_usd이 run의 천장. 프로덕션 라이브 커머스 run은 $120 안팎입니다.
communication.webhook_urlrun이 끝나면 서명된 POST 한 번. 아무것도 폴링하지 않습니다. result_url은 백업으로 두세요.

202data.iddata.thread_id를 여러분의 행에 저장하세요. 앞의 것은 receipt용, 뒤의 것은 재시도를 묶는 용도입니다.

웹훅이 도착하면 payload.output.full_video.url이 방송이고 payload.output.scenes[]가 클립입니다. status: "stand-in"이나 "failed"인 씬이 아래 재시도 레시피가 고칠 대상입니다.

웹훅 수신기

수신기는 네 가지를 순서대로 합니다. 원본 바이트에 대해 서명을 검증하고, 2xx를 빨리 답하고, request_id로 중복을 제거하고, 그다음에야 outcome에 따라 행동합니다. 아래 두 버전 모두 너무 큰 receipt(payload: null)를 처리합니다.

Node

Web Request API 위의 프레임워크 중립 코드입니다. Next.js route handler, Hono, Workers, Deno 어디서든. @sume-com/sdkverifyWebhook을 씁니다.

SDK를 쓸 수 없다면 검증은 열 줄 남짓입니다. 시크릿으로 ${timestamp}.${raw}의 HMAC-SHA256을 구해 hex로 만들고, 5분 넘게 어긋난 timestamp를 거부한 뒤, x-sume-webhook-signaturesume-v1= 뒤 값과 상수 시간으로 비교합니다. 전체 함수는 Run 웹훅에 있습니다.

Python

FastAPI이며, JSON 파싱 전에 원본 본문을 읽습니다.

첫 수신기마다 걸리는 것이 두 가지입니다. JSON을 대신 파싱해 주는 프레임워크는 서명된 바이트를 이미 망가뜨렸으므로 이 라우트에서는 원본 본문을 읽으세요. 그리고 응답 전에 영상을 렌더링하는 수신기는 10초 시도 예산을 태우고 작업 중에 재시도를 받으니, 기록하고 답한 뒤 처리하세요.

실제 run 없이 테스트하려면 POST /v1/webhooks/test-deliveries(또는 대시보드의 Send test)가 webhook.test 페이로드를 URL로 쏩니다. 실제 전달을 다시 보내려면 POST /v1/format-runs/{run_id}/webhook/redeliver를 쓰세요.

같은 스레드에서 씬 하나 재시도하기

run은 대화의 한 턴입니다. 클립 하나를 다시 만들려면 previous_run_id로 그 대화를 이어 가며 씬을 지목하세요. 보이스 트랙, 다른 클립, 대본은 그대로이고 전체 씬 목록이 다시 조립되어 돌아옵니다.

운영자의 메모(어느 씬이, 무엇이 잘못됐고, 어떻게 바뀌어야 하는지)는 instruction에 넣고, input.scene_id는 기계가 읽는 포인터로 유지하세요. 두 씬을 한 번에 하려면 "scene_ids": ["sc_7", "sc_9"]입니다.

돌아오는 것은 같은 thread_id 위의 새 run(arun_…, 새 receipt, 자체 웹훅)입니다. output.scenes[]는 다시 전체 목록입니다. 재시도한 씬은 새 URL을 갖고, 나머지는 기존 URL을 유지하며, full_video는 새 URL로 다시 조립됩니다. 씬 하나 재시도의 예산은 생성 run의 일부로 잡으세요(측정된 프로덕션 재시도는 첫 run 비용의 약 20분의 1이었습니다). cap은 항상 보내세요.

재시도는 재인코딩이 아니라 새 테이크입니다. 그 씬의 생성 요소는 전부 다시 굴려집니다. 외관이 바뀌어야 하면 → 씬 재시도. 문구, 호스트, 제품이 바뀌면 → 새 제작, 새 씬 id.

이전 run이 남긴 것이 없으면 400 previous_run_not_resumable, 아직 실행 중이면 409 previous_run_not_terminal, 다른 Format을 주소로 쓰면 400 previous_run_format_mismatch로 거부됩니다. 실행과 결과를 참고하세요.

시트를 bulk run으로 배치하기

방송 시트의 한 행이 항목 하나가 되고, 시트 전체가 POST …/bulk-runs 하나가 됩니다. 큐는 concurrency개의 run을 진행시키고, 자리가 나는 대로 다음 항목을 시작합니다.

bulk-body.json은 키 두 개입니다. 각 항목은 단일 run의 본문 그대로이며, 이 페이지의 첫 레시피를 행마다 하나씩 넣습니다. 완성된 대본이 없는 행은 클라이언트에서 건너뛰세요. 빈 항목은 없습니다.

202는 첫 concurrency개 항목이 이미 running인 큐(frq_…)를 돌려줍니다. 시트 행 ↔ index 매핑은 직접 관리하세요. items[i].index는 제출한 위치입니다.

진행 상황은 자식이 아니라 큐를 폴링하세요.

배치 모양이 분명하게 보여 주는 세 가지. 큐에는 웹훅이 없고 communication.webhook_url은 항목별입니다. 큐의 completed는 모든 항목이 종료됐다는 뜻이지 모두 성공했다는 뜻이 아니므로 counts.failed와 각 자식의 output_error로 분기하세요. 그리고 이미 쓴 Idempotency-Key 큐와 함께 202를 돌려주니, 배치마다 새 키를 만드세요. 전체 계약: 대량 실행.

웹훅 없이 run 기다리기

엔드포인트를 노출할 수 없을 때(스크립트, CI job, 일회성 작업)는 백오프로 폴링하고 종료 status에서 멈추세요.

TypeScript에서는 subscribeFormatRun이 생성과 루프를 한 호출로 합칩니다. 어떤 종료 status에서든 resolve하므로, 실패한 run은 예외가 아니라 분기할 결과입니다.

기본 timeout은 20분입니다. 긴 영상이면 올리고, receipt의 expires_at을 정직한 천장으로 쓰세요. timeout은 run을 취소하지 않습니다. run은 계속 실행되고 청구되니 run id를 보관했다가 나중에 다시 읽으세요.

호출 전에 Format 읽어 보기

설정 화면이나 사전 점검에 유용합니다. 쥐고 있는 키로 주소가 풀리는지, Format이 무엇을 받는지, cap이 얼마인지 확인합니다.

맞다고 믿는 키인데 여기서 404 format_not_found가 나오면 거의 항상 다른 키입니다. 팀 Format은 팀 워크스페이스에서 만든 키에만 답합니다. 키 소유자가 그 팀의 멤버라면 같은 뜻을 더 친절하게 403 workspace_key_required로 말해 줍니다.

다음