요청 형식 주의사항 POST 요청 시
Content-Type: application/json헤더와 함께 JSON body를 그대로 전달하는 방식을 권장합니다.application/x-www-form-urlencoded를 사용할 경우에는 파라미터를 JSON으로 직렬화한 뒤payload필드에 담아 전송하십시오. 예:payload={"apiKey":"...","secret":"..."}
편집 화면 없이 동영상을 자동으로 생성·추출하는 API입니다. 토큰 노출 방지를 위해 반드시 백엔드에서만 호출하십시오.
프로젝트 생성과 추출을 동시에 자동화합니다. 완료된 최종 결과는 webhookUrl 또는 앱 설정의 Export Webhook으로 POST 전달됩니다. 이 방법으로 생성된 프로젝트는 추출 이후 일주일 후 자동으로 삭제됩니다.
| 헤더 | 필수 | 설명 |
|---|---|---|
| Authorization | ✓ | 계정 설정 > API 토큰에서 복사한 토큰. Bearer Qjky6mFiMkRn... 형식 |
| x-nonce | ✓ | 각 요청에 대한 유니크한 값 (중복 요청 구분용) |
| 파라미터 | 필수 | 타입 | 설명 |
|---|---|---|---|
| injector | ✓ | object | 데이터 주입/변형 명세. 아래 Injector 섹션 참고 |
| dictionary | object | TTS/STT 텍스트 치환 규칙. 아래 dictionary 섹션 참고 | |
| baseProjectId | string | 특정 프로젝트를 템플릿으로 사용할 경우의 projectId. 같은 스페이스이거나 public 상태여야 함 | |
| spaceId | int | 대상 워크스페이스 고유번호. 0이면 기본 워크스페이스 | |
| type | string | 추출 파일 형식. mp4 | jpg |
|
| webhookUrl | string | 완료 시 결과를 전달할 URL | |
| webhookType | string | webhook 전달 방식. form | json |
|
| webhookHeader | string | webhook 커스텀 헤더. 헤더명: 값 형식. 예: x-api-key: abc123 |
curl -X POST "https://videostew.com/api/automations" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM" \
-H "Content-Type: application/json" \
-d '{
"baseProjectId": "88282f69vmqbqr9",
"injector": {
"wizard": {
"source": "url",
"sourceContent": "https://doo39oi115k60.cloudfront.net/wizard-url-example/"
}
}
}'
{
"status": "done",
"result": {
"projectId": "abc123..."
}
}
처리 결과 확인:
https://videostew.com/v/{projectId}에 접속했을 때 "추출중입니다" 메시지가 표시되면 렌더링이 정상 진행 중입니다. 약 5분 후 같은 URL에서 완성된 영상을 확인할 수 있습니다. 완료 이벤트를 코드로 받으려면webhookUrl을 지정하세요.
{
"status": "done",
"projectId": "abc123...",
"size": "1080x1920",
"type": "mp4",
"link": "https://cdn.videostew.com/projects/..."
}
데이터를 주입하는 방법으로 wizard, data를 제공하며, 각각은 배타적이므로 한 번에 한가지 방식만 사용할 수 있습니다.
텍스트 또는 URL을 넘기면 AI가 분석해 동영상을 자동으로 만들어줍니다. 세부적인 제어는 어렵지만, 가장 간단하게 동영상을 생성할 수 있는 방법입니다.
| 파라미터 | 설명 |
|---|---|
| source | 소스 타입. text | url |
| sourceContent | source에 대응하는 값. text면 HTML/plain text, url이면 URL 문자열 |
| title | 프로젝트 제목 |
| language | 프로젝트 언어. 예: ko, en, ja |
| opts.replace | AI가 교체할 슬라이드 범위. body=본문만 교체, 인트로/아웃트로는 템플릿 그대로 유지(반복 사용하는 고정 애니메이션·엔딩에 적합). headbody=AI가 소제목을 자동 생성하며 소제목+본문 교체, 인트로/아웃트로 유지. all=인트로/아웃트로 포함 전체 교체 |
| opts.visual | 비주얼 소스 방식. stock-mixed/stock-video/stock-image=비디오스튜 스톡 라이브러리에서 맥락에 맞는 리소스를 자동 매칭(각각 혼합/비디오만/이미지만). ai-image=AI로 이미지 생성. none=비주얼 없음(원본 URL에 이미지가 풍부할 때 적합) |
| opts.autoLineBreak | y로 설정하면 텍스트를 줄 단위로 분리해, 한 줄씩 등장하는 텍스트 애니메이션이 의도대로 동작합니다. 대부분의 템플릿이 이 애니메이션을 기본으로 사용하므로 y 권장 |
| opts.visualStyle | 비주얼 스타일. illust=디지털아트, photo=실사, flat-vector=벡터, editorial-cartoon=만평, editorial-illust=신문 일러스트, silhouette=실루엣. 또는 "수묵화 스타일로 그려줘" 처럼 직접 프롬프트를 입력해 원하는 스타일을 지정 |
| adjust.duration | 목표 분량. keep=원본 유지, 30s | 1m | 3m | 10m | 20m |
| adjust.structure | 구조. keep=원본, body=본문만, headbody=소제목+내용 형식 |
| adjust.style | 스크립트 스타일. keep=원본 유지, colloquial=팟캐스트 같은 대화형, news=뉴스 방송처럼 공식적·객관적, info=정보 전달에 최적화된 명확·간결한 스타일, insight=인사이트와 분석을 강조하는 심층적 스타일, essay=서술적·사색적 에세이 톤, casual=친근하고 편안한 일상 대화 스타일. 또는 "시청자에게 말 걸듯 친근하게, 유머도 살짝 섞어줘" 처럼 직접 프롬프트를 입력해 원하는 스타일을 지정 |
adjust의 모든 키가keep이면 원본 글을 AI로 다듬는 과정 없이 원문 그대로 사용합니다.
{
"wizard": {
"source": "url",
"sourceContent": "https://doo39oi115k60.cloudfront.net/wizard-url-example/",
"language": "ko",
"opts": {
"replace": "all",
"visual": "ai-image",
"visualStyle": "illust",
"autoLineBreak": "y"
},
"adjust": {
"duration": "1m",
"structure": "headbody",
"style": "news"
}
}
}
프로젝트/슬라이드/요소 구조를 직접 지정합니다. 영상을 어떻게 만들 것인지 모든 것을 직접 구성할 때 사용합니다. 기존 요소와 일치하면 대체, 없으면 신규 생성합니다. 변경이 필요한 키만 지정하면 되며, 지정하지 않은 값은 기존 프로젝트의 값을 유지합니다.
data 키
최상위에 지정한 bgm은 slides 배열 전체에 기본값으로 적용됩니다. 각 슬라이드별 지정이 있으면 그 값을 더 우선시합니다.
| 키 | 설명 |
|---|---|
| title | 프로젝트 제목 |
| language | 프로젝트 언어. 예: ko, en |
| bgm | 프로젝트 BGM 파일 URL |
| slides | 슬라이드 배열 |
data.slides[] 키
| 키 | 설명 |
|---|---|
| label | 슬라이드 식별 레이블(기본 베이스 프로젝트내의 슬라이드 라벨기준으로 매칭). 같은 label을 여러 번 지정하면 해당 템플릿 슬라이드를 복제해 슬라이드 수를 늘릴 수 있습니다. 예: main 라벨을 3번 쓰면 main 슬라이드가 3개 생성. 라벨값은 편집화면에서 하단의 슬라이드 패널에서 확인할 수 있습니다. |
| narration | 슬라이드 나레이션. 텍스트를 입력하면 템플릿에 설정된 AI 목소리로 읽어줍니다. 직접 녹음한 오디오를 쓰려면 공개 URL을 입력하세요 |
| sound | 슬라이드 효과음 URL |
| bgm | 이 슬라이드에만 적용할 BGM URL. 최상위 bgm보다 우선 |
| text | 텍스트 요소 내용. 단순 문자열이면 슬라이드의 첫 번째 텍스트 요소에 적용. 슬라이드에 텍스트 요소가 여러 개 있을 때 각 요소를 정확히 타겟팅하려면 { "label": "요소라벨", "content": "내용" } 객체 형태로 배열 지정(라벨은 템플릿에서 설정한 요소 라벨 기준). 빈 문자열이면 요소 삭제. elements 배열 방식은 지원하지 않습니다. |
| image | 이미지 요소 libraryId. 배열로 여러 개 지정 가능 |
| video | 비디오 요소 libraryId. 배열로 여러 개 지정 가능 |
참고: URL을 지정하는 모든 필드(
image,video,sound,bgm,narration등)는 공개(public) 접근 가능한 주소여야 하며, 크롬 브라우저 기준의 표준 파일 형식이어야 합니다.
예시 1 — 텍스트·이미지 치환 + TTS 나레이션
{
"data": {
"language": "ko",
"bgm": "https://example.com/bgm.mp3", // 모든 슬라이드에 공통 적용
"slides": [
{
"label": "title", // 베이스 프로젝트의 슬라이드 레이블로 매칭
"text": "오늘의 뉴스 제목", // 템플릿의 텍스트 요소를 이 내용으로 교체
"image": "https://doo39oi115k60.cloudfront.net/wizard-url-example/01.webp",
"narration": "오늘의 뉴스를 전해드립니다." // 문자열이면 TTS로 생성(베이스 프로젝트의 나레이션 속성 따름)
},
{
"label": "body",
"text": "본문 내용입니다.",
"image": "https://doo39oi115k60.cloudfront.net/wizard-url-example/02.webp"
},
{
"label": "outro",
"text": "" // 빈 문자열이면 해당 텍스트 요소 삭제
}
]
}
}
예시 2 — 라벨로 요소 타겟팅
템플릿에 텍스트 요소가 여러 개 있을 때, { label, content } 형태로 어떤 요소에 무엇을 넣을지 정확히 지정할 수 있습니다. 단, 이 방식은 Videostew 편집 화면에서 각 텍스트 요소에 미리 라벨을 붙여두어야 동작합니다. 라벨이 없는 요소는 타겟팅할 수 없습니다. 예를 들어 상단 요소에 title, 하단 AI 보이스용 요소에 voicetext라고 라벨을 붙여둔 템플릿이라면 아래처럼 각각 제어할 수 있습니다.
{
"data": {
"slides": [
{
"label": "main",
"text": [
{ "label": "title", "content": "이거 진짜 될까?" }, // 화면 상단 타이틀 요소
{ "label": "voicetext", "content": "이거 진짜 될까" } // AI 보이스가 읽을 자막 요소
]
}
]
}
}
예시 3 — 녹음 파일 나레이션 + 슬라이드별 비디오
{
"data": {
"slides": [
{
"label": "intro",
"narration": "https://doo39oi115k60.cloudfront.net/wizard-url-example/narration1.mp3", // 직접 녹음/합성한 오디오 파일
"video": "https://doo39oi115k60.cloudfront.net/wizard-url-example/video1.mp4"
},
{
"label": "body",
"narration": "https://doo39oi115k60.cloudfront.net/wizard-url-example/narration2.mp3",
"video": "https://doo39oi115k60.cloudfront.net/wizard-url-example/video2.mp4",
"bgm": "https://example.com/this-slide-only.mp3" // 이 슬라이드만 다른 BGM
}
]
}
}
단순한 키 대칭으로 표현하기 힘든 상세한 세부 제어가 필요할 때 사용합니다(위치 혹은 복수의 갯수일 때). 아래는 사용 가능한 키의 전체 목록이며, 실제 요청에는 필요한 것만 포함하세요.
color 포맷:
[[R, G, B, A], degree]— R/G/B는 0–255, A는 0–1 (불투명도), degree는 그라데이션 각도 (단색이면0).
{
"data": {
"title": "프로젝트 제목",
"language": "ko",
"slides": [
{
"trans": {
"type": "fade", // auto | fade | flip-ltr | flip-ttb | cube-ltr | cube-rtl | reveal-ltr | reveal-rtl
"durationTime": 0.3
},
"narration": {
"type": "voice", // voice
"libraryId": "https://doo39oi115k60.cloudfront.net/wizard-url-example/narration1.mp3",
"content": "", // TTS 텍스트 (type이 tts일 때),
"volume": 1,
"speed": 1.1,
"trimStart": 0,
"trimEnd": 0
},
"glb": {
"bgmLibraryId": "https://example.com/bgm.mp3",
"bgmVolume": 0.9,
"bgmSpeed": 1,
"soundLibraryId": "https://example.com/sfx.mp3",
"soundVolume": 1,
"soundEvery": true,
"soundFit": false,
"backgroundColor": [[0, 0, 0, 1], 0],
"bgBlr": false,
"bgBlrB": 0.4
},
"elements": [
{
"type": "text",
"content": "텍스트 내용",
"rect": {
"top": 800, "left": 40, "width": 1000, "height": 200,
"opacity": 1
},
"custom": {
"fontSize": 48,
"color": [[255, 255, 255, 1], 0],
"align": "center", // left | center | right
"valign": "v_bottom", // top | middle | bottom | v_top | v_bottom
"lineHeight": 1.2,
"raType": "block", // notset | block | inline | outline | textShadow
"raColor": [[0, 0, 0, 1], 0],
"enabledTts": true,
"splitLine": "1l", // "" | 1l | 2l | p
"splitLineType": "replace" // replace | add
}
},
{
"type": "image",
"libraryId": "https://doo39oi115k60.cloudfront.net/wizard-url-example/01.webp",
"rect": {
"top": 0, "left": 0, "width": 1080, "height": 1920,
"opacity": 1,
"innerType": "cover", // cover | contain | fill
"innerPosition": "50% 30%" // CSS position 형식, 이미지 포커스 위치
}
},
{
"type": "video",
"libraryId": "https://doo39oi115k60.cloudfront.net/wizard-url-example/video1.mp4",
"rect": {
"top": 0, "left": 0, "width": 1080, "height": 1080,
"innerType": "cover",
"innerPosition": "50% 50%"
},
"custom": {
"trimStart": 0,
"trimEnd": 10,
"speed": 1,
"volume": 1,
"loop": 9999 // 0 = 반복 안함, 9999 = 무한 반복
}
},
{
"type": "shape",
"libraryId": "shape-library-id",
"rect": {
"top": 0, "left": 0, "width": 200, "height": 200
},
"custom": {
"color": [[255, 100, 0, 1], 0]
}
}
]
}
]
}
}
TTS/STT 시 적용할 텍스트 치환 규칙입니다. injector와 함께 바디 최상위에 전달합니다. 스페이스 딕셔너리와 병합되며 여기서 지정한 값이 우선합니다. 영역당 최대 100개 항목.
| 키 | 설명 |
|---|---|
tts |
AI 보이스가 텍스트를 읽을 때 적용. 잘못 발음되는 단어를 올바른 발음으로 강제 지정 |
stt |
음성을 텍스트로 변환(자막 생성)할 때 적용. STT가 잘못 인식하는 단어를 올바른 표기로 강제 교정 |
trans |
번역 후처리 시 적용 |
{
"injector": {
"wizard": { "source": "url", "sourceContent": "https://doo39oi115k60.cloudfront.net/wizard-url-example/" }
},
"dictionary": {
"tts": [
{ "i": "3D", "o": "쓰리디" }, // "삼디"로 읽히는 걸 방지
{ "i": "AI", "o": "에이아이" } // "아이"로 읽히는 걸 방지
],
"stt": [
{ "i": "video studio", "o": "videostew" }, // STT가 잘못 인식한 표기를 교정
{ "i": "비디오 스튜", "o": "비디오스튜" } // 띄어쓰기 오인식 교정
]
}
}
curl -X GET "https://videostew.com/api/spaces" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM"
| 파라미터 | 타입 | 설명 |
|---|---|---|
| spaceId | int | 대상 워크스페이스 고유번호. 0이면 기본 워크스페이스 |
| projectIds | string | 콤마로 구분된 프로젝트 ID 목록 |
| folderId | int | 폴더 고유번호. 기본값(루트) 1000000 |
| status | string | public | enabled | secret. trash는 삭제된 상태 |
| limit | int | 페이지당 항목수 |
| page | int | 페이지 번호 |
| title | string | 제목 검색 |
| tags | string | 태그 검색 |
curl -X GET "https://videostew.com/api/projects?spaceId=0&limit=20&page=1" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM"
curl -X GET "https://videostew.com/api/projects/PROJECT_ID" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM"
쿼리 파라미터: includeSlides=true (슬라이드 상세 포함, 대용량)
| 파라미터 | 타입 | 설명 |
|---|---|---|
| spaceId | int | 대상 워크스페이스 고유번호. 0이면 기본 워크스페이스 |
| projectIds | string | 콤마로 구분된 프로젝트 ID 목록 |
| projectId | string | 특정 프로젝트의 추출만 조회 |
| type | string | mp4 | jpg |
| limit | int | 페이지당 항목수 |
| page | int | 페이지 번호 |
curl -X GET "https://videostew.com/api/exports?projectId=PROJECT_ID&limit=20" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM"
curl -X GET "https://videostew.com/api/exports/PROJECT_ID/EXPORT_ID" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM"
| 파라미터 | 타입 | 설명 |
|---|---|---|
| type | string | mp4 | jpg |
| webhookUrl | string | 완료 시 결과를 받을 URL |
| webhookType | string | form | json |
| webhookHeader | string | webhook 커스텀 헤더. 헤더명: 값 형식. 예: x-api-key: abc123 |
curl -X POST "https://videostew.com/api/exports/PROJECT_ID" \
-H "Authorization: Bearer {{bearerToken}}" \
-H "x-nonce: $RANDOM" \
-H "Content-Type: application/json" \
-d '{"type":"mp4","webhookUrl":"https://your-server.com/webhook"}'
응답:
{
"status": "done",
"result": {
"id": "e-19",
"projectId": "...",
"status": "generate",
"type": "mp4"
}
}
Webhook 응답 (추출 완료 시):
{
"status": "done",
"projectId": "...",
"size": "1280x720",
"type": "mp4",
"link": "https://cdn.videostew.com/projects/..."
}
자사의 웹사이트에서 자사의 고객들에게 비디오스튜의 편집화면만 제공할 때 사용합니다.
SDK를 사용할 때는 각 사용자마다 개별 엑세스 토큰을 발급해야 합니다. 토큰은 마지막 사용 이후 1개월 간 유효하며, 재사용 시 자동 연장됩니다. 401 Token is invalid 응답이 오면 새 토큰을 발급해 fallback 처리하세요.
!!
secret키 노출 방지를 위해 반드시 백엔드에서만 요청하십시오.
| 파라미터 | 필수 | 타입 | 설명 |
|---|---|---|---|
| apiKey | ✓ | string | 발급받은 앱의 ApiKey |
| secret | ✓ | string | 발급받은 앱의 시크릿 키 |
| uniqueId | ✓ | any | 자사 플랫폼에서 사용하는 유저의 고유번호 |
| language | string | uniqueId 신규 생성 시 언어 강제 지정. 예: ko, en |
curl -X POST "https://videostew.com/auth/access-token" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "{{apiKey}}",
"secret": "{{secret}}",
"uniqueId": "user_123"
}'
응답:
{
"status": "done",
"apiKey": "abc1de2fg3...",
"token": "Qjky6mFiMkRnOmExYj..."
}
로그아웃 등 모든 활동 종료 시 해당 유저의 토큰을 강제 만료합니다. 토큰은 1회성이 아니므로 강제 삭제 시 사용 중인 다른 탭에서 문제가 발생할 수 있습니다. 사용자가 탈퇴 등으로 확실히 그만두는 시점에서 호출하시면 됩니다.
curl -X POST "https://videostew.com/auth/revoke-access-token" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "{{apiKey}}",
"secret": "{{secret}}",
"uniqueId": "user_123"
}'
버튼 클릭 등의 이벤트에서 편집기를 모달로 엽니다.
<script src="https://cdn.videostew.com/web/sdk/sdk-latest.js"></script>
<script>
videostewSDK.open({
token: "Qjky6mFiMkRnOmEx...", // /auth/access-token 응답의 token 값
projectId: "...", // 수정할 프로젝트 ID (없으면 신규 생성)
// baseProjectId: "...", // 특정 프로젝트를 템플릿으로 사용(신규 생성시)
// language: "ko", // 프로젝트 및 UI 언어 설정
// injector: { ... }, // 데이터 주입/변형 명세
// dictionary: { ... }, // TTS/STT 텍스트 치환 규칙
callbackFunc: function(result) {
// 사용자가 [Done]을 눌렀을 때 호출
console.log(result.projectId);
// result: { projectId, thumbnailUrl, spaceId, width, height, title, status, slideCount, savedAt }
},
eventFunc: function(projectId, eventName) {
// 편집 화면 내 이벤트 발생 시 호출
// eventName: openPreview, saveProject, openDownload,
// requestExportPng, requestExportMp4, exportedPng, exportedMp4,
// downloadPng, downloadMp4, openProjectInfo, updateProjectInfo
},
errorFunc: function(errorMessage) {
// 토큰 만료 시 호출 → 새 토큰 발급 후 재시도 처리
// errorMessage: "Token is invalid"
}
});
</script>
| 옵션 | 필수 | 설명 |
|---|---|---|
| token | ✓ | /auth/access-token 응답의 token 값. 예: Qjky6mFiMkRn... |
| apiKey | 레거시 방식(raw token) 사용 시에만 필요. 신규 방식은 생략 | |
| projectId | 수정할 프로젝트 ID. 없으면 신규 생성 | |
| baseProjectId | 템플릿 프로젝트 ID. 같은 스페이스이거나 public 상태여야 함 | |
| language | 프로젝트 및 UI 언어. 미지정 시 기본 en |
|
| injector | 데이터 주입/변형 명세. Injector 섹션 참고 | |
| dictionary | TTS/STT 텍스트 치환 규칙. dictionary 섹션 참고 | |
| callbackFunc | function(result) — [Done] 버튼 클릭 시 호출, 앱 설정에 Done Webhook이 지정된 경우 이 설정은 무시됩니다. |
|
| eventFunc | function(projectId, eventName) — 편집 화면 내 이벤트 발생 시 호출 |
|
| errorFunc | function(errorMessage) — 토큰 만료 시 호출 |
편집 화면 상태를 저장합니다. 유저가 [Save] 버튼을 누른 것과 동일하므로 특별한 경우가 아니면 호출할 필요가 없습니다.
videostewSDK.save();
편집 내용을 저장하고 callbackFunc 또는 Done Webhook으로 결과를 전달합니다.
videostewSDK.done();
편집기를 닫습니다. 저장되지 않은 내용이 있으면 확인 팝업이 표시됩니다.
videostewSDK.cancel();
// videostewSDK.cancel(true); // 강제 닫기