Tạo Video

Trạm AI hỗ trợ tạo video từ text prompt (và tùy chọn thêm ảnh tham chiếu) thông qua một API bất đồng bộ chuyên dụng (asynchronous API). Hiện tại Trạm AI hỗ trợ tạo video với các model: google/veo-3.1, bytedance/seedance-2.0, kuaishou/kling-3.0.

Xem khả năng của từng model và bảng giá bằng cách lọc danh sách model theo output video.

Khám phá model

Có thể tìm các model tạo video theo nhiều cách:

Thông qua Models API

Dùng Public Models API để lấy danh sách model, sau đó lọc các model có mode"video":

lines
$# Lấy danh sách tất cả model
$curl "https://api.staging.tram.ai.vn/public/models"
$
$# Tìm model tạo video: lọc các model có mode = "video"

Trên trang Models

Truy cập trang Models và lọc theo output modalities để tìm các model có khả năng tạo video. Hãy để ý những model có liệt kê "video" trong phần output modalities.

Cách hoạt động

Tạo video là quá trình theo cơ chế chạy ngầm (bất đồng bộ-asynchronous), khác với tạo văn bản hay hình ảnh, vì nó mất nhiều thời gian hơn đáng kể. Quy trình diễn ra như sau:

  1. Gửi một request tạo video đến POST /v1/videos
  2. Nhận ngay một job ID (status submitted)
  3. Poll trạng thái job (GET /v1/videos/{jobId}) cho đến khi status là completed
  4. Tải video từ content endpoint (GET /v1/videos/{jobId}/content)

Sử dụng API

Gửi request tạo video

1import requests
2import json
3import time
4
5url = "https://api.staging.tram.ai.vn/v1/videos"
6headers = {
7 "Authorization": f"Bearer {API_KEY_REF}",
8 "Content-Type": "application/json"
9}
10
11payload = {
12 "model": "google/veo-3.1",
13 "prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background"
14}
15
16# Step 1: Submit the generation request
17response = requests.post(url, headers=headers, json=payload)
18result = response.json()
19
20job_id = result["id"]
21print(f"Job submitted: {job_id}")
22print(f"Status: {result['status']}") # "submitted"
23
24# Step 2: Poll until completion
25while True:
26 time.sleep(30) # Wait 30 seconds between polls
27 poll_response = requests.get(f"{url}/{job_id}", headers=headers)
28 status = poll_response.json()
29
30 print(f"Status: {status['status']}")
31
32 if status["status"] == "completed":
33 # Step 3: Download the video
34 content_url = f"{url}/{job_id}/content"
35 video_response = requests.get(content_url, headers=headers)
36 with open("output.mp4", "wb") as f:
37 f.write(video_response.content)
38 print("Video saved to output.mp4")
39 break
40 elif status["status"] == "failed":
41 print(f"Generation failed: {status.get('error', {}).get('message', 'Unknown error')}")
42 break

Tham số request

Tham sốKiểuBắt buộcMô tả
modelstringModel dùng để tạo video (ví dụ: google/veo-3.1, bytedance/seedance-2.0-mini)
promptstringMô tả bằng văn bản về video cần tạo (tối đa 10.000 ký tự)
secondsintegerKhôngThời lượng video được tạo, tính bằng giây. Mặc định là thời lượng tối đa của model
sizestringKhôngKích thước / tỷ lệ khung hình (ví dụ: 1280x720, 16:9)
input_referencestring | objectKhôngẢnh first frame cho image-to-video (data URI hoặc URL). Xem API reference
last_framestring | objectKhôngẢnh last frame — tạo video chuyển tiếp từ first frame đến last frame. Chỉ model Seedance
reference_imagesstring[]KhôngDanh sách URL hoặc data URI ảnh tham khảo (tối đa 9). Chỉ model Seedance. Không dùng cùng input_reference
resolutionstringKhôngĐộ phân giải: 480p, 720p, 1080p, 4k. Chỉ model Seedance
seedintegerKhôngSeed để tạo kết quả có thể tái tạo
generate_audiobooleanKhôngTạo âm thanh đồng bộ. Mặc định true trên Seedance
watermarkbooleanKhôngĐóng dấu “AI-generated” vào video. Chỉ model Seedance
return_last_framebooleanKhôngTrả URL ảnh frame cuối trong response khi hoàn tất. Chỉ model Seedance
parametersobjectKhôngTham số bổ sung truyền thẳng đến provider (xem bên dưới)

Tham số pass-through (parameters)

Trường parameters cho phép truyền các tham số riêng của provider mà Trạm AI không map trực tiếp. Các tham số này được chuyển tiếp đến provider.

Các tham số pass-through được hỗ trợ (Vertex AI / Veo):

Tham sốKiểuMô tả
resolutionstringĐộ phân giải video: "720p", "1080p", "4k"
numberOfVideosnumberSố lượng video cần tạo

Ví dụ:

lines
1{
2 "model": "google/veo-3.1",
3 "prompt": "A time-lapse of a flower blooming",
4 "seconds": 8,
5 "size": "1280x720",
6 "parameters": {
7 "resolution": "1080p",
8 "numberOfVideos": 1
9 }
10}

Với model Seedance, resolution là top-level param (cùng với seed, generate_audio, watermark, return_last_frame), không cần đặt trong parameters. Với model Veo, resolution phải đặt trong parameters.

Với model Veo (Google), chỉ các tham số nằm trong block parameters của provider mới được pass-through. Các tham số nằm ở level instances (như lastFrame, referenceImages, video) không thể truyền qua cách này.

Mapping tham số

Trạm AI tự động map các tham số chuẩn sang format của provider:

Tram APIVertex AI (Veo)Seedance (ByteDance)Mô tả
promptinstances[0].promptpromptText prompt
secondsparameters.durationSecondsdurationThời lượng video
sizeparameters.aspectRatioratioTỷ lệ khung hình
input_referenceinstances[0].imageinput_reference (data URI)Ảnh first frame
last_framelast_frame (data URI)Ảnh last frame
reference_imagesreference_imagesẢnh tham khảo
resolutionparameters.resolution ⚠️resolutionĐộ phân giải
seedseedSeed tái tạo
generate_audiogenerate_audioTạo âm thanh
watermarkwatermarkDấu AI-generated
return_last_framereturn_last_frameTrả URL frame cuối

Ràng buộc thời lượng

Mỗi model có ràng buộc thời lượng riêng. Nếu truyền giá trị seconds không hợp lệ, request sẽ bị từ chối với lỗi 400.

ModelThời lượng cho phép (giây)Ghi chú
google/veo-3.14, 6, 8
bytedance/seedance-2.04–15 (integer), hoặc -1-1 để model tự chọn thời lượng phù hợp
kuaishou/kling-3.03–15 (string)Nếu dùng video reference thì tối đa 10 giây

Định dạng response

Response khi gửi (202 Accepted)

Khi người dùng gửi một request tạo video, Trạm AI sẽ trả về response ngay lập tức kèm theo thông tin chi tiết của job:

lines
1{
2 "id": "c0845e6f-...",
3 "object": "video.job",
4 "status": "submitted",
5 "model": "google/veo-3.1",
6 "created_at": 1782886429
7}

Response khi poll

Khi poll trạng thái của job (GET /v1/videos/{jobId}), response sẽ phản ánh trạng thái hiện tại:

Đang xử lý:

lines
1{
2 "id": "c0845e6f-...",
3 "object": "video.job",
4 "status": "processing",
5 "model": "google/veo-3.1",
6 "created_at": 1782886429
7}

Hoàn tất:

lines
1{
2 "id": "c0845e6f-...",
3 "object": "video.job",
4 "status": "completed",
5 "model": "google/veo-3.1",
6 "created_at": 1782886429,
7 "completed_at": 1782886489,
8 "result": {
9 "duration_seconds": 8
10 },
11 "usage": {
12 "duration_seconds": 8,
13 "cost_vnd": 42346
14 }
15}

Thất bại:

lines
1{
2 "id": "c0845e6f-...",
3 "object": "video.job",
4 "status": "failed",
5 "model": "google/veo-3.1",
6 "created_at": 1782886429,
7 "error": {
8 "message": "Video generation failed."
9 }
10}

Các trạng thái của job

StatusMô tả
submittedJob đã được gửi và đang trong hàng đợi
processingVideo đang được tạo
completedVideo đã sẵn sàng để tải
failedQuá trình tạo thất bại (kiểm tra trường error)
expiredJob đã hết hạn trước khi hoàn tất

Tải video

Khi status của job là completed, người dùng có thể tải video từ content endpoint:

lines
$curl "https://api.staging.tram.ai.vn/v1/videos/{jobId}/content" \
> -H "Authorization: Bearer $TRAM_AI_API_KEY" \
> --output video.mp4

Response trả về trực tiếp bytes video (video/mp4).

Liệt kê các job

Người dùng có thể liệt kê các video job của mình:

lines
$# Liệt kê tất cả job (mặc định 20 job gần nhất)
$curl "https://api.staging.tram.ai.vn/v1/videos" \
> -H "Authorization: Bearer $TRAM_AI_API_KEY"
$
$# Lọc theo status
$curl "https://api.staging.tram.ai.vn/v1/videos?status=completed&limit=10" \
> -H "Authorization: Bearer $TRAM_AI_API_KEY"

Response trả về mảng data chứa các job:

lines
1{
2 "data": [
3 {
4 "id": "c0845e6f-...",
5 "object": "video.job",
6 "status": "completed",
7 "model": "google/veo-3.1",
8 "created_at": 1782886429,
9 "completed_at": 1782886489,
10 "result": { "duration_seconds": 8 },
11 "usage": { "duration_seconds": 8, "cost_vnd": 42346 }
12 }
13 ]
14}
Query parameterMô tả
statusLọc theo trạng thái: submitted, processing, completed, failed, expired
limitSố job tối đa trả về (1-100, mặc định 20)

Billing

Tạo video sử dụng cơ chế deferred-settle billing:

  1. Khi gửi: Trạm AI đặt một hold trên tài khoản bạn cho chi phí ước tính tối đa (dựa trên thời lượng × giá mỗi giây)
  2. Khi hoàn tất: Chi phí thực tế được tính dựa trên thời lượng video thực, hold được giải phóng và số tiền chính xác được trừ
  3. Khi thất bại/hết hạn: Hold được giải phóng, không tính phí

Hold có thời hạn tối đa 1 giờ. Chi phí được tính bằng VND (cost_vnd trong response).

Thực hành tốt nhất

  • Prompt chi tiết: Hãy viết prompt cụ thể, giàu tính mô tả để có chất lượng video tốt hơn. Nên nêu rõ về chuyển động, góc máy, ánh sáng và bố cục cảnh
  • Chọn thời lượng phù hợp: Thời lượng càng dài thì càng tốn chi phí. Kiểm tra allowedDurations của model trước khi gửi request
  • Khoảng thời gian poll: Dùng khoảng thời gian poll hợp lý (ví dụ: 30 giây) để tránh gọi API quá mức. Việc tạo video thường mất từ 30 giây đến vài phút, tùy theo model
  • Xử lý lỗi: Luôn kiểm tra trạng thái failedexpired của job và xử lý trường error một cách phù hợp

Zero Data Retention

Việc tạo video không đủ điều kiện áp dụng Zero Data Retention (ZDR). Vì tạo video là quá trình theo cơ chế chạy ngầm (bất đồng bộ-asynchronous), provider phải lưu trữ video output trong một khoảng thời gian ngắn để người dùng có thể truy xuất sau khi quá trình tạo hoàn tất. Việc lưu trữ tạm thời này là đặc tính vốn có của quy trình poll bất đồng bộ và không thể bỏ qua.

Nếu người dùng đã bật bắt buộc ZDR (qua cài đặt tài khoản hoặc tham số zdr theo từng request), Trạm AI sẽ không route các request tạo video.

Khắc phục sự cố

Job ở trạng thái submitted trong thời gian dài?

  • Việc tạo video có thể mất vài phút, tùy theo model và tải của server
  • Hãy tiếp tục poll theo các khoảng đều đặn (30 giây)

Quá trình tạo thất bại?

  • Kiểm tra trường error.message trong response poll để biết chi tiết
  • Xác minh model có hỗ trợ tạo video hay không (kiểm tra mode: "video" qua Public Models API)
  • Đảm bảo prompt phù hợp và nằm trong khuôn khổ hướng dẫn của model
  • Kiểm tra giá trị seconds có nằm trong danh sách thời lượng cho phép của model không

Lỗi 400 khi gửi request?

  • Kiểm tra seconds có nằm trong allowedDurations của model không (ví dụ: veo-3.1 chỉ cho phép 4, 6, 8)
  • Đảm bảo prompt không rỗng và không vượt quá 10.000 ký tự

Không tìm thấy model?

  • Sử dụng trang Models để tìm các model tạo video khả dụng
  • Xác minh model slug đúng (ví dụ: google/veo-3.1)