HTTP 404 (Media ID Not Found) do khác tài khoản.• 1. Kiểu I2V (Image-to-Video — Ảnh đầu/khung hình ➔ Video): Dùng khi muốn biến 1 bức ảnh tĩnh thành khung hình bắt đầu của Video. Truyền tham số
start_media_id (hoặc start_media_path).• 2. Kiểu R2V (Reference-to-Video — Ảnh tham chiếu phong cách ➔ Video): Dùng khi muốn giữ phong cách/nhân vật từ 1 hoặc nhiều bức ảnh mẫu. Truyền mảng
media_ids (hoặc ref_image_urls).
Bước 0: Lấy Danh Sách Tài Khoản (Tùy chọn)
Bên thứ 3 có thể lấy danh sách tài khoản nếu muốn chỉ định tài khoản cụ thể. Nếu bỏ trống account_id, hệ thống tự động xoay vòng tài khoản active.
Gửi request GET /api/accounts hoặc GET /api/user/accounts.
Bước 1: Tạo Ảnh Hoặc Upload Ảnh
Gọi POST /api/generate để tạo ảnh từ prompt, hoặc POST /api/upload_image để upload ảnh từ máy. API trả về media_id (UUID) và url.
// Response từ POST /api/generate:
{
"success": true,
"images": [
{
"index": 1,
"url": "https://flow-content.google/image/b42c6ab5-...",
"media_id": "b42c6ab5-982f-41bd-8c84-b35bfe2a4a5f" // ← UUID ảnh vừa tạo
}
],
"account_id": "user_AccountA_101"
}
Bước 2A: Gọi API kiểu I2V (Image-to-Video — Ảnh làm khung hình đầu ở Tài Khoản Video/ULTRA)
Truyền start_media_id lấy từ Bước 1. Bạn có thể chọn bất kỳ **Tài Khoản Video / ULTRA** nào ở account_id. Hệ thống sẽ tự động tìm URL ảnh và re-upload ngầm sang tài khoản Video đó mà không bị lỗi 404.
POST /api/generate_video
{
"prompt": "cô gái mỉm cười, tóc bay nhẹ trong gió, camera slow motion",
"aspect_ratio": "VIDEO_ASPECT_RATIO_LANDSCAPE",
"start_media_id": "b42c6ab5-982f-41bd-8c84-b35bfe2a4a5f", // ← UUID ảnh tạo từ Tài khoản A
"model": "veo_3_1_i2v_lite_low_priority", // ← Model I2V
"use_own_account": true,
"account_id": "user_AccountB_ULTRA_202" // ← BẤT KỲ TÀI KHOẢN VIDEO/ULTRA NÀO! (Server tự re-upload)
}
Bước 2B: Gọi API kiểu R2V (Reference-to-Video — Ảnh làm tham chiếu phong cách)
Truyền mảng media_ids (hoặc ref_image_urls). Tương tự, bạn có thể truyền bất kỳ account_id tài khoản Video/ULTRA nào.
POST /api/generate_video
{
"prompt": "nhân vật đi dạo trên phố ban đêm, ánh đèn neon",
"aspect_ratio": "VIDEO_ASPECT_RATIO_LANDSCAPE",
"media_ids": ["b42c6ab5-982f-41bd-8c84-b35bfe2a4a5f"], // ← Mảng UUID ảnh tạo từ Tài khoản A
"model": "veo_3_1_r2v_lite_low_priority", // ← Model R2V
"use_own_account": true,
"account_id": "user_AccountB_ULTRA_202" // ← TÀI KHOẢN VIDEO/ULTRA BẤT KỲ
}
Bước 2C: Gọi API truyền URL trực tiếp (Dành cho ảnh bên ngoài)
Nếu bạn đã có sẵn URL ảnh công khai (từ trang web khác hoặc server riêng), hãy truyền trực tiếp vào mảng ref_image_urls. Server sẽ tự động download và upload sang tài khoản video hiện tại.
POST /api/generate_video
{
"prompt": "chú mèo chạy trên bãi cỏ, cinematic",
"aspect_ratio": "VIDEO_ASPECT_RATIO_LANDSCAPE",
"ref_image_urls": ["https://example.com/sample_cat.jpg"] // ← URL ảnh bất kỳ
}
•
start_media_id ➔ Kích hoạt chế độ **I2V** (Image-to-Video).•
media_ids ➔ Kích hoạt chế độ **R2V** (Reference-to-Video).•
ref_image_urls ➔ Dùng khi ảnh đến từ URL bên ngoài hoặc muốn hệ thống re-upload tự động.• Khi chuyển tài khoản giữa Tạo Ảnh và Tạo Video, hệ thống tự động tìm URL trong DB để re-upload ➔ **Tuyệt đối không bị lỗi HTTP 404**.
Ví dụ Code Python Hoàn Chỉnh — Chuyển Tài Khoản Tự Động (Tạo ảnh Tk A ➔ Tạo Video Tk B/ULTRA)
import requests, time
BASE = "http://YOUR_SERVER:5000"
IMAGE_ACCOUNT = "user_AccountA_101" # Tài khoản A dùng để tạo ảnh
ULTRA_VIDEO_ACCOUNT = "user_AccountB_202" # Tài khoản B (ULTRA) dùng để tạo video
# ===== Bước 1: Tạo ảnh bằng Tài khoản A =====
print("🎨 Đang tạo ảnh bằng Tài khoản A...")
img_resp = requests.post(f"{BASE}/api/generate", json={
"prompt": "quả táo đỏ trên bàn gỗ, manga style",
"count": 1,
"aspect_ratio": "IMAGE_ASPECT_RATIO_LANDSCAPE",
"model": "GEM_PIX_2",
"use_own_account": True, # Sử dụng tài khoản riêng
"account_id": IMAGE_ACCOUNT, # Chỉ định Tài khoản A
"for_video": True
}, timeout=120).json()
if not img_resp["success"]:
print(f"❌ Lỗi tạo ảnh: {img_resp.get('error')}")
exit()
image = img_resp["images"][0]
media_id_a = image["media_id"] # UUID từ Tài khoản A
print(f"✅ Ảnh tạo từ Tk A thành công:")
print(f" URL: {image['url']}")
print(f" Media ID A: {media_id_a}")
# ===== Bước 2: Tạo video bằng Tài khoản B (ULTRA) từ Media ID của Tài khoản A =====
# (Server tự động tra cứu URL ➔ Download ➔ Re-upload ngầm sang Tk B ➔ 0 lỗi 404!)
print("\n🎬 Đang tạo video bằng Tài khoản B (ULTRA)...")
vid_resp = requests.post(f"{BASE}/api/generate_video", json={
"prompt": "quả táo lăn trên bàn gỗ, camera slow motion",
"start_media_id": media_id_a, # Pass Media ID từ Tài khoản A (Kiểu I2V)
"use_own_account": True,
"account_id": ULTRA_VIDEO_ACCOUNT, # Tài khoản B khác biệt hoàn toàn!
"aspect_ratio": "VIDEO_ASPECT_RATIO_LANDSCAPE"
}, timeout=600).json() # 10 phút timeout
if vid_resp["success"]:
for v in vid_resp["videos"]:
print(f"🎉 SUCCESS! Video tạo từ Tk B: {v['url']}")
else:
print(f"❌ Lỗi tạo video: {vid_resp.get('error')}")
Chạy Thử Trực Tiếp: Tạo Ảnh Tk A ➔ Tạo Video Tk B (ULTRA)
LIVE INTERACTIVE TESTBạn có thể chọn 2 tài khoản khác nhau bên dưới (Tài khoản A tạo ảnh & Tài khoản B ULTRA tạo video) để kiểm tra tính năng Re-upload ngầm tự động ngay trên trang này.
POST /api/auth/login để lấy cookie, sau đó đính kèm cookie session vào header trong các request tiếp theo.
Gửi tài khoản mật khẩu để lấy session cookie.
Parameters (JSON)
| Field | Type | Mô tả |
|---|---|---|
username* | string | Tên đăng nhập |
password* | string | Mật khẩu |
is_extension | bool | Đặt false (mặc định) |
Response Headers
Set-Cookie: session=ey...; Path=/; HttpOnly; SameSite=Lax
Kiểm Thử Đăng Nhập
Bạn có thể kích hoạt chế độ gọi API không cần đăng nhập bằng 1 trong 2 cách:
• Cách 1 (Giao diện Admin): Vào trang Admin UI ➔ phần Cấu Hình Admin & CSDL SQLite ➔ Tích chọn "Tắt Xác Thực Đăng Nhập & API". Hệ thống sẽ lưu trạng thái vào CSDL SQLite (`disable_auth_mode = true`).
• Cách 2 (File Cấu hình .env): Đặt
REQUIRE_API_AUTH=false trong file .env ở thư mục gốc.⚡ Cơ chế Đa Luồng Đa Tài Khoản khi Tắt Xác Thực:
- Khi bật No-Auth Mode, **mọi API** (Tạo Ảnh `/api/generate`, Tạo Video `/api/generate_video`, Upload Ảnh `/api/upload_image`, Refresh Link `/api/refresh_media`, Hàng Chờ Queue...) đều cho phép các ứng dụng/script bên thứ ba gọi trực tiếp 100% không cần truyền Cookie hay Session.
- Server tự động gán session Admin mặc định và **luân chuyển luồng đa tài khoản (AccountManager)** song song dựa theo dung lượng `max_slots` và `max_video_slots` của từng tài khoản.
- Tất cả kịch bản, lịch sử kết quả công việc, và nhật ký đều được tự động lưu trữ và đồng bộ tức thì vào **CSDL SQLite (`database.db`)**.
Admin có thể tạo các API Key dạng
veo_live_abc123... trên Admin Panel kèm theo Hạn ngạch Quota (Ngày/Tháng). Ứng dụng bên thứ ba không cần gọi API Đăng nhập lấy cookie mà chỉ cần gửi Header:
• Header 1:
X-API-Key: veo_live_xxx
• Header 2:
Authorization: Bearer veo_live_xxx
Ví dụ cURL với API Key
curl -X POST "http://127.0.0.1:5000/api/generate_video" \
-H "X-API-Key: veo_live_a1b2c3d4e5f67890..." \
-H "Content-Type: application/json" \
-d '{
"prompt": "chú mèo nhảy múa trong mưa, 4k",
"aspect_ratio": "VIDEO_ASPECT_RATIO_LANDSCAPE"
}'
Ví dụ Code Python với API Key
import requests
API_KEY = "veo_live_a1b2c3d4e5f67890..."
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}
resp = requests.post("http://127.0.0.1:5000/api/generate_video", json={
"prompt": "cô gái mặc áo dài truyền thống Việt Nam",
"aspect_ratio": "VIDEO_ASPECT_RATIO_PORTRAIT"
}, headers=headers).json()
print(resp)
Khi ứng dụng bên thứ ba gửi yêu cầu tạo video/ảnh, ứng dụng có thể đính kèm tham số
webhook_url (ví dụ: https://app-cua-khach.com/api/callback).Khi server render xong video/ảnh, server sẽ tự động gửi một HTTP
POST request chứa toàn bộ kết quả về webhook_url đó. Bên thứ 3 không cần giữ kết nối chờ đợi.
Tham Số Khởi Tạo Request
Trong request POST /api/generate_video hoặc POST /api/generate, bổ sung 2 trường:
| Field | Type | Mô tả |
|---|---|---|
webhook_url | string | URL Server bên thứ ba nhận callback kết quả (ví dụ: https://app.domain.com/webhook) |
webhook_secret | string (optional) | Mã bí mật dùng để kiểm tra chữ ký xác thực HMAC-SHA256 trong Header X-Webhook-Signature |
Cấu Trúc Payload Server Gửi Trả Về Webhook URL
{
"success": true,
"videos": [
{
"url": "http://127.0.0.1:5000/outputs/video_abc123.mp4",
"media_id": "video_abc123",
"index": 1,
"name": "operations/eb4a58ba-..."
}
],
"total_generated": 1,
"prompt": "chú mèo nhảy múa trong mưa, 4k",
"account_id": "user_AccountA_101"
}
Ví dụ Code Server Bên Thứ Ba (Node.js / Express) Kiểm Tra Chữ Ký Webhook Signature
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = "my_webhook_secret_key";
app.post('/api/callback', (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (WEBHOOK_SECRET && signature) {
const expectedSig = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature !== expectedSig) {
console.error("❌ Webhook Signature Invalid!");
return res.status(401).send("Invalid signature");
}
}
console.log("🎉 Nhận kết quả Video thành công từ Veo Server:", req.body);
// Xử lý lưu database hoặc gửi thông báo cho client của bạn ở đây...
res.status(200).send("OK");
});
app.listen(3000, () => console.log('Webhook Listener running on port 3000'));
Gửi prompt tạo ảnh. API trả về URL ảnh khi hoàn thành (đồng bộ). Hỗ trợ ảnh tham chiếu bằng media_ids.
Parameters
| Field | Type | Mô tả |
|---|---|---|
prompt* | string | Nội dung mô tả ảnh muốn tạo |
count | int | Số ảnh (mặc định: 1, tối đa: 4) |
aspect_ratio | string | IMAGE_ASPECT_RATIO_LANDSCAPE (16:9), ..._PORTRAIT (9:16), ..._SQUARE (1:1) |
model | string | GEM_PIX_2 (Nano Banana Pro), NARWHAL (Nano Banana 2) hoặc HARBOR_SEAL (Nano Banana 2 Lite) |
for_video | bool | Ưu tiên tài khoản "both" (hỗ trợ cả ảnh + video) để dùng cho I2V |
media_ids | array | Mảng Media ID ảnh tham chiếu (cho ảnh→ảnh, tối đa 10 ảnh) |
account_id | string | Tài khoản đã upload ảnh tham chiếu (bắt buộc nếu có media_ids) |
Response
{
"success": true,
"images": [
{
"index": 1,
"url": "https://flow-content.google/image/b42c6ab5-...",
"media_id": "b42c6ab5-982f-41bd-8c84-b35bfe2a4a5f" // UUID
}
],
"total_generated": 1,
"account_id": "Maimaicodn", // Tài khoản đã tạo
"project_id": "0ffa648a-...", // Project ID
"acc_type": "both" // Loại tài khoản
}
// → Lưu media_id + account_id → dùng cho /api/generate_video
Kiểm Thử Trực Tiếp
Upload ảnh lên Google qua multipart/form-data. Trả về media_id dùng làm ảnh tham chiếu hoặc khung hình đầu cho Video (I2V).
Request (Form-Data)
| Field | Type | Mô tả |
|---|---|---|
file* | File | File ảnh (PNG, JPG, WEBP) |
cURL
curl -X POST http://127.0.0.1:5000/api/upload_image \ -F "file=@/path/to/image.jpg"
Response
{
"success": true,
"media_id": "projects/.../media/123456789"
}
Kiểm Thử Upload
Click hoặc kéo thả ảnh vào đây
Tạo video qua Google Veo. Text-to-Video (T2V): chỉ cần prompt. Image-to-Video (I2V / R2V): truyền ref_image_urls (URL ảnh) hoặc start_media_path (file ảnh local).
Parameters
| Field | Type | Mô tả |
|---|---|---|
prompt* | string | Mô tả nội dung video muốn tạo |
start_media_id | string | (I2V — Ảnh đầu ➔ Video) UUID của ảnh muốn dùng làm khung hình bắt đầu cho video. |
media_ids | array | (R2V — Ảnh tham chiếu ➔ Video) Mảng UUID ảnh tham chiếu phong cách/nhân vật (tối đa 3 ảnh). |
ref_image_urls | array | (I2V/R2V) Mảng URL ảnh ngoài. Server tự động download & re-upload sang tài khoản Video hiện tại. |
start_media_path | string | (I2V) Đường dẫn file ảnh local trên máy server. |
aspect_ratio | string | VIDEO_ASPECT_RATIO_LANDSCAPE (16:9), ..._PORTRAIT (9:16), ..._SQUARE (1:1) |
model | string | Tự động nhận diện: veo_3_1_i2v_lite_low_priority (cho I2V), veo_3_1_r2v_lite_low_priority (cho R2V), hoặc veo_3_1_t2v_lite_low_priority (cho T2V) |
account_id | string | (Tùy chọn) ID tài khoản chỉ định. Nếu khác tài khoản tạo ảnh, hệ thống tự động re-upload ngầm. |
count | int | Số video muốn tạo (mặc định: 1) |
Ví dụ Python — Tạo ảnh bằng Nano Model rồi tạo video bằng Tài khoản Ultra
import requests
BASE = "http://YOUR_SERVER:5000"
# Bước 1: Tạo ảnh bằng bất kỳ Model Nano nào (Nano Pro, Nano 2, Nano 2 Lite)
img_res = requests.post(f"{BASE}/api/generate", json={
"prompt": "một chú mèo dễ thương",
"model": "GEM_PIX_2" # GEM_PIX_2 (Nano Pro), NARWHAL (Nano 2) hoặc HARBOR_SEAL (Nano 2 Lite)
}, timeout=120).json()
img_url = img_res["images"][0]["url"]
# Bước 2: Tạo video bằng Tài khoản Ultra (Server tự động re-upload ngầm sang Ultra Account)
vid_res = requests.post(f"{BASE}/api/generate_video", json={
"prompt": "chú mèo di chuyển linh hoạt, camera xoay quanh",
"model": "veo_3_1_r2v_lite_low_priority",
"ref_image_urls": [img_url] # Truyền URL ảnh → Server tự động re-upload sang Ultra Account!
}, timeout=600).json()
print("Link Video Ultra:", vid_res["videos"][0]["url"])
Kiểm Thử Tạo Video
media_id và account_id mà không cần render lại.
Hồi sinh link media bằng cách lấy redirect URL mới từ Google.
Parameters
| Field | Type | Mô tả |
|---|---|---|
media_id* | string | UUID của media (ảnh hoặc video) cần refresh |
account_id* | string | Tài khoản sở hữu media_id này |
is_video | bool | true nếu là video, false nếu là ảnh |
project_id | string | (Tùy chọn) Project ID liên kết với media |
Kiểm Thử Trực Tiếp
Trả về trạng thái hoạt động, số tài khoản, hàng chờ.
Lấy danh sách tất cả tài khoản đã đăng ký và trạng thái hoạt động.
Request Body
{
"id": "email@gmail.com",
"cookies": [
{"name":"__Secure-1PSID","value":"...","domain":".google.com"},
{"name":"__Secure-1PSIDTS","value":"..."}
]
}
Lấy danh sách kịch bản đang chờ chạy, đang chạy hoặc tạm dừng.
Thêm một hoặc nhiều tác vụ kịch bản vào cuối hàng chờ để xử lý tuần tự.
Parameters
| Field | Type | Mô tả |
|---|---|---|
item hoặc items | object / array | Nội dung tác vụ kịch bản |
Thay đổi trạng thái hoạt động của hàng chờ (bắt đầu chạy, tạm dừng, xóa hàng chờ, v.v.).
Parameters
| Field | Type | Mô tả |
|---|---|---|
action* | string | Giá trị có thể: start, pause, clear, clear_errors, retry_errors |
Sử dụng PUT để cập nhật tác vụ tại vị trí index hoặc DELETE để xóa tác vụ đó khỏi hàng chờ.
Xem danh sách kết quả các tác vụ đã hoàn thành hoặc thất bại.
Trả về thông số tổng quan hệ thống: Số lượng tạo ảnh/video, tỉ lệ thành công, tài khoản active và lượng tài nguyên đã sử dụng.
Trả về danh sách tất cả các bảng trong CSDL SQLite và số lượng dòng hiện có.
Tải trực tiếp file CSDL database.db về máy tính để sao lưu hoặc kiểm tra offline.
Dọn dẹp các ô nhớ trống và giải phóng dung lượng đĩa cho file database.db.
Đọc hoặc thay đổi trạng thái disable_auth_mode (Cho phép gọi API không cần Cookie/Xác thực).
POST Request Body
{ "disable_auth_mode": true }
Lấy logs realtime để hiển thị trạng thái trên ứng dụng của bạn.