Render Video
https://sangtao.ai/api/v2/render/videoTài liệu cho Render Video.
Tạo video từ scenes (ảnh/video + audio). Job chạy nền, poll trạng thái qua GET /api/v2/jobs/{jobId}.
Bắt đầu nhanh
Làm theo các bước sau để tạo video đầu tiên qua API:
Lấy API Key
Vào Cài đặt → API Key để tạo key. Gửi kèm trong mọi request qua header X-Api-Key.
Chọn Layout (bố cục video)
Layout là bố cục video — quyết định vị trí ảnh, chữ, tỷ lệ khung hình (16:9, 9:16, 1:1). Gọi GET /api/v2/assets/video-layouts để xem danh sách layout và slug tương ứng.
Tạo Scenes (cảnh quay)
Mỗi scene là một đoạn trong video. Mỗi scene cần 1 hình ảnh (URL hoặc prompt để AI tạo) và tùy chọn audio (URL hoặc text để AI đọc). Hãy tưởng tượng scene như các slide trong bài thuyết trình.
Gửi request & theo dõi tiến độ
POST request để nhận jobId. Sau đó poll GET /api/v2/jobs/{jobId} mỗi 3-5 giây cho đến khi status = "Complete" (có URL video) hoặc "Error".
curl -X POST https://sangtao.ai/api/v2/render/video \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"layoutSlug": "news-vtv",
"scenes": [{
"image": { "url": "https://example.com/photo.jpg" },
"audio": { "text": "Xin chào!", "voiceId": "hoai-my" }
}]
}'Các khái niệm chính
Bố cục video quyết định giao diện, tỷ lệ khung hình, vị trí các thành phần. Mỗi layout có 1 slug riêng.
Một đoạn trong video. Gồm hình ảnh/video, audio (tùy chọn), thời lượng, hiệu ứng và chuyển cảnh.
Narration = 1 audio cho toàn bộ video (chia đều cho các scene). Per-scene audio = mỗi scene có audio riêng. Chọn 1 kiểu, không dùng cả 2.
Effect (ZoomIn, PanLeft...) tạo chuyển động cho ảnh trong scene. Transition (Fade, Dissolve...) là hiệu ứng chuyển giữa các scene. Tự động xoay vòng nếu không chỉ định.
Bật phụ đề với caption.enabled=true. Nếu bạn gửi word timestamps thì dùng luôn, không thì hệ thống chạy STT tự động (tính thêm phí nhỏ).
Credit bị khóa khi tạo job. Sau khi render xong, tính chi phí thực tế và hoàn trả chênh lệch tự động.
Luồng xử lý
POST /render/video
Tạo job
Khóa credit
Ước tính phí
Tạo media
Ảnh AI, TTS
Render video
Ghép video hoàn chỉnh
Complete
Có URL video
Nội dung request
| Field | Type | Description |
|---|---|---|
| layoutSlug | string | Slug của layout video. Lấy danh sách từ GET /api/v2/assets/video-layouts. Mặc định: server chọn theo aspectRatio |
| scenes* | array | 1–15 scenes (đoạn video). Mỗi scene cần ít nhất 1 image hoặc 1 video |
| narration | object | 1 audio/TTS dùng cho toàn bộ video, chia đều cho các scene. Không dùng chung với per-scene audio |
| coverPhotoUrl | string | URL ảnh bìa — hiển thị 1 giây đầu video như intro |
| caption | object | Phụ đề: {enabled: true, preset: "phantom"}. Không gửi words → hệ thống tự chạy STT (tính thêm phí) |
| backgroundMusic | object | Nhạc nền: {trackId: slug từ GET /api/v2/assets/background-tracks} hoặc {audioUrl: "URL nhạc"}, volume: 0.0–1.0 |
| overlay | string | Hiệu ứng phủ (tuyết, mưa...): slug từ GET /api/v2/assets/overlays. null = không dùng |
| output | object | Cấu hình đầu ra: {resolution: "720p"|"1080p"|"4k", fps: 24|30|60}. Mặc định 1080p, 30fps |
| headlineText | string | Tiêu đề hiển thị trên layout (nếu layout hỗ trợ) |
| variables | object | Cặp key-value cho biến template layout (VD: {ticker: "AAPL", date: "2026-01-01"}) |
| webhookUrl | string | URL webhook — server sẽ POST đến khi job hoàn thành hoặc lỗi |
Đối tượng Scene
Mỗi scene là một đoạn trong video. Bắt buộc có image hoặc video, audio là tùy chọn.
| Field | Type | Description |
|---|---|---|
| image | object | Hình ảnh cho scene. Bắt buộc 1 trong 2: image hoặc video (xem chi tiết bên dưới) |
| video | object | Video clip cho scene. Bắt buộc 1 trong 2: image hoặc video (xem chi tiết bên dưới) |
| audio | object | Audio cho scene — URL có sẵn hoặc text cho AI đọc (xem chi tiết bên dưới) |
| durationSec | number | Thời lượng scene (giây). Không set → lấy từ audio length. Không có audio → default 4s |
| keyPhrase | string | Câu chữ hiển thị trên video theo vị trí của layout (ví dụ: tiêu đề tin tức) |
| effect | string | Hiệu ứng ảnh: ZoomIn, PanLeft, ... Không set → tự động xoay vòng. Video bỏ qua |
| transition | string | Chuyển cảnh sang scene tiếp: Fade, Dissolve, ... Không set → tự động xoay vòng |
| zoomLevel | number | Mức zoom cho hiệu ứng ảnh (1.0–3.0). Mặc định: 1.15 |
| transitionDuration | number | Thời lượng chuyển cảnh (giây) (0.1–2.0). Mặc định: 1.0 |
| elements | array | Các element phủ lên scene (text, logo). Max 15. Xem phần Overlay Elements |
Đối tượng Image (ảnh)
Cung cấp URL ảnh có sẵn, hoặc viết prompt để AI tạo ảnh. Mỗi scene chọn 1 cách.
| Field | Type | Description |
|---|---|---|
| url | string | URL ảnh có sẵn. Dùng cách này hoặc prompt, không dùng cả 2 |
| prompt | string | Prompt mô tả để AI tạo ảnh. Cần kèm model |
| model | string | Model slug cho AI gen ảnh (GET /api/v2/models?category=image). Bắt buộc khi có prompt |
| fit | string | "cover" | "contain" | "fit" | "fill-content". Default: "contain". Xem phần Chế độ Fit bên dưới |
| aspectRatio | string | Tỷ lệ ảnh AI gen: "9:16" | "16:9" | "1:1". Mặc định theo layout |
Đối tượng Video
Cung cấp URL video clip. Dùng thay image cho các scene cần video thực.
| Field | Type | Description |
|---|---|---|
| url* | string | URL video clip (.mp4, .webm...) |
| fit | string | "cover" | "contain" | "fit" | "fill-content". Default: "contain". Xem phần Chế độ Fit |
Chế độ Fit (hiển thị ảnh/video)
Quyết định cách ảnh/video được co giãn để vừa khung hình. Áp dụng cho cả image.fit và video.fit.
| Value | Cách hoạt động | Mô tả |
|---|---|---|
| cover | Phóng to + cắt rìa | Ảnh phủ kín khung hình, cắt bỏ phần thừa. Không có viền đen. Có thể mất 1 phần ảnh ở rìa. |
| contain | Thu nhỏ + nền blur | Ảnh nằm gọn trong khung, nền blur phía sau phần trống. Giữ nguyên toàn bộ nội dung, không cắt. |
| fit | Thu nhỏ + nền đen | Giống contain nhưng nền đen thay vì blur. Ảnh giữ nguyên tỷ lệ, viền đen 2 bên. |
| fill-content | Blur toàn frame + sharp vùng nội dung | Dùng với layout có bars (trên/dưới). Ảnh sharp chỉ nằm trong vùng content (giữa 2 bars), blur BG phủ toàn bộ frame kể cả phía sau bars. |
Đối tượng Audio (giọng đọc)
Cung cấp URL audio có sẵn, hoặc text + voiceId để AI đọc. Có thể gửi kèm word timestamps để bỏ qua STT.
| Field | Type | Description |
|---|---|---|
| url | string | URL audio có sẵn (.mp3, .wav...). Dùng cách này hoặc text, không dùng cả 2 |
| text | string | Nội dung để AI đọc (TTS). Cần kèm voiceId |
| voiceId | string | Voice slug từ GET /api/v2/assets/voices. Bắt buộc khi có text |
| words | array | Mảng [{word, offsetMs, durationMs}] — timestamps từng từ. Gửi kèm để bỏ qua STT tự động |
Ví dụ request
{
"layoutSlug": "news-vtv",
"scenes": [
{
"image": {
"url": "https://example.com/photo.jpg",
"fit": "cover"
},
"audio": {
"text": "Cuối con phố nhỏ ở Hội An...",
"voiceId": "vi-VN-HoaiMyNeural"
},
"keyPhrase": "Tiệm đèn lồng",
"effect": "ZoomIn",
"transition": "Fade"
},
{
"image": {
"prompt": "cô gái đứng trước tiệm đèn lồng",
"model": "nano-banana-pro",
"fit": "cover"
},
"audio": {
"text": "Những chiếc đèn lồng đỏ rực rỡ...",
"voiceId": "vi-VN-HoaiMyNeural"
},
"effect": "PanRight"
}
],
"caption": { "enabled": true, "preset": "phantom" },
"backgroundMusic": {
"trackId": "fassounds-good-night-lofi",
"volume": 0.2
},
"output": { "resolution": "1080p", "fps": 30 }
}Phản hồi (200 OK)
{
"success": true,
"data": {
"jobId": "a1b2c3d4e5f6...",
"status": "Pending",
"statusUrl": "/api/v2/jobs/a1b2c3d4e5f6...",
"durationSec": 65.0,
"aspectRatio": "16:9",
"renderCost": 27.0,
"imageGenCost": 16.0,
"ttsCost": 1.94,
"sttCost": 3.25,
"totalCost": 48.19
}
}Theo dõi tiến độ
Poll GET /api/v2/jobs/{jobId} mỗi 3–5 giây cho đến khi status = Complete hoặc Error.
// Poll mỗi 3–5 giây
GET /api/v2/jobs/{jobId}
{
"success": true,
"data": {
"jobId": "a1b2c3d4...",
"status": "Processing", // Pending → Processing → Complete | Error
"progress": 45.0,
"result": "generating_media_2_of_3"
}
}| Bước | Tiến độ |
|---|---|
| generating_script | 10–15% |
| generating_media | 15–40% |
| generating_media_N_of_M | 15–40% |
| rendering | 40–90% |
| Complete | 100% |
Hiệu ứng (chỉ ảnh)
| Value | Mô tả |
|---|---|
| Static | Không hiệu ứng |
| ZoomIn | Zoom vào |
| ZoomOut | Zoom ra |
| PanLeft | Pan trái |
| PanRight | Pan phải |
| PanUp | Pan lên |
| PanDown | Pan xuống |
| ZoomInPanUp | Zoom vào + pan lên |
| ZoomInPanLeft | Zoom vào + pan trái |
| ZoomOutPanRight | Zoom ra + pan phải |
Chuyển cảnh
| Value | Mô tả |
|---|---|
| Fade | Fade in/out |
| Dissolve | Hòa tan |
| FadeBlack | Fade qua đen |
| SlideLeft | Trượt trái |
| SlideRight | Trượt phải |
| SlideUp | Trượt lên |
| SlideDown | Trượt xuống |
Mã lỗi
| Mã | Khi nào |
|---|---|
| 400 | Thiếu field bắt buộc (layoutSlug, image/video, voiceId khi có text) |
| 402 | Không đủ credit |
| 404 | Layout/model/preset/track/overlay không tìm thấy |
| 422 | Validation lỗi (image+video cùng lúc, narration+audio cùng lúc, quá 15 scene) |
| 429 | Quá 4 job đang chạy cùng lúc |
Ví dụ code
curl -X POST https://sangtao.ai/api/v2/render/video \
-H "X-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"layoutSlug": "news-vtv",
"scenes": [{
"image": { "url": "https://example.com/photo.jpg" },
"audio": { "text": "Nội dung...", "voiceId": "vi-VN-HoaiMyNeural" }
}],
"output": { "resolution": "1080p" }
}'const response = await fetch('https://sangtao.ai/api/v2/render/video', {
method: 'POST',
headers: {
'X-Api-Key': 'your-api-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
layoutSlug: 'news-vtv',
scenes: [{
image: { url: 'https://example.com/photo.jpg' },
audio: { text: 'Nội dung...', voiceId: 'vi-VN-HoaiMyNeural' },
}],
output: { resolution: '1080p' },
}),
})
const { data } = await response.json()
console.log(data.jobId) // Poll GET /api/v2/jobs/{jobId}Credit & Giá
| Item | Cách tính |
|---|---|
| Render | Base 25 cr (≤60s). Trên 60s: 25 + ceil((duration−60)/10) × 2 cr |
| AI Image Gen | Theo model pricing × số ảnh gen |
| TTS (Free voice) | 500 ký tự đầu miễn phí, sau đó 1 cr mỗi 200 ký tự |
| TTS (Pro 10) | 10 cr mỗi 1.000 ký tự |
| TTS (Pro 40) | 40 cr mỗi 1.000 ký tự |
| TTS (Pro 60) | 60 cr mỗi 1.000 ký tự |
| STT (caption) | ~3 cr/phút audio (chỉ khi caption enabled + không gửi words) |