تولید ویدئو — Video generation
آشا تولید ویدئو از متن (و تصویر مرجع) را از طریق POST /v1/videos پشتیبانی میکند. تولید ویدئو در سرور ناهمگام انجام میشود؛ آشا کار را ثبت و تا پایان پیگیری میکند و نتیجهٔ نهایی را در همان پاسخ برمیگرداند. فهرست مدلها و تعرفهها در صفحهٔ مدلها در دسترس است.
کشف مدلها
مدلهای تولید ویدئو از طریق endpoint سازگار با OpenAI یعنی
GET /v1/models در دسترساند. هر مدل فیلد
architecture.output_modalities دارد که حالتهای
خروجیِ پشتیبانیشده (مثل video) را فهرست میکند:
curl "https://app.asha-ai.ir/v1/models"
مدلهایی که "video" را در
architecture.output_modalities دارند، مدلهای تولید
ویدئو هستند. فهرست کامل و قیمت به تومان در صفحهٔ مدلها هم نمایش داده میشود.
روش کار
تولید ویدئو ناهمگام است، چون ساختن ویدئو بهطور قابلتوجهی طول میکشد. آشا در
POST /v1/videos این کار را برای شما ساده کرده است:
- ارسال درخواست تولید به
POST /v1/videos - انتظار — آشا کار را نزد ارائهدهنده ثبت میکند و تا رسیدن به وضعیت نهایی پیگیری (نظرسنجی) میکند
- دریافت کارِ تکمیلشده در همان پاسخ، همراه آدرسهای دانلود (
unsigned_urls) و هزینهٔ نهایی (usage.cost) - دانلود ویدئو از آدرسهای ارائهشده
استفاده از API
ارسال درخواست تولید ویدئو
import os
import requests
url = "https://app.asha-ai.ir/v1/videos"
headers = {
"Authorization": f"Bearer {os.environ['ASHA_API_KEY']}",
"Content-Type": "application/json",
}
payload = {
"model": "~google/veo-3.1",
"prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background",
}
# Asha submits the job and polls until completion, then returns the final job.
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
result = response.json()
if result["status"] != "completed":
raise RuntimeError(f"Generation failed: {result.get('error', 'Unknown error')}")
# Download the video from the returned content URL
content_url = result["unsigned_urls"][0]
video_response = requests.get(content_url)
with open("output.mp4", "wb") as f:
f.write(video_response.content)
print("Video saved to output.mp4")
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
payload := map[string]any{
"model": "~google/veo-3.1",
"prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://app.asha-ai.ir/v1/videos", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("ASHA_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result struct {
Status string `json:"status"`
UnsignedURLs []string `json:"unsigned_urls"`
Error string `json:"error"`
}
_ = json.NewDecoder(resp.Body).Decode(&result)
if result.Status != "completed" {
fmt.Printf("Generation failed: %sn", result.Error)
return
}
videoResp, err := http.Get(result.UnsignedURLs[0])
if err != nil {
panic(err)
}
defer videoResp.Body.Close()
out, _ := os.Create("output.mp4")
defer out.Close()
_, _ = io.Copy(out, videoResp.Body)
fmt.Println("Video saved to output.mp4")
}
const headers = {
Authorization: `Bearer ${process.env.ASHA_API_KEY}`,
"Content-Type": "application/json",
};
// Asha submits the job and polls until completion, then returns the final job.
const response = await fetch("https://app.asha-ai.ir/v1/videos", {
method: "POST",
headers,
body: JSON.stringify({
model: "~google/veo-3.1",
prompt: "A golden retriever playing fetch on a sunny beach with waves crashing in the background",
}),
});
const result = await response.json();
if (result.status !== "completed") {
throw new Error(`Generation failed: ${result.error ?? "Unknown error"}`);
}
// Download the video from the returned content URL
const videoResponse = await fetch(result.unsigned_urls[0]);
const videoBuffer = await videoResponse.arrayBuffer();
// Save or process the video buffer
console.log(`Video ready: ${result.unsigned_urls[0]}`);
const headers = {
Authorization: `Bearer ${process.env.ASHA_API_KEY}`,
"Content-Type": "application/json",
};
// Asha submits the job and polls until completion, then returns the final job.
const response = await fetch("https://app.asha-ai.ir/v1/videos", {
method: "POST",
headers,
body: JSON.stringify({
model: "~google/veo-3.1",
prompt: "A golden retriever playing fetch on a sunny beach with waves crashing in the background",
}),
});
const result = await response.json();
if (result.status !== "completed") {
throw new Error(`Generation failed: ${result.error ?? "Unknown error"}`);
}
// Download the video from the returned content URL
const videoResponse = await fetch(result.unsigned_urls[0]);
const videoBuffer = await videoResponse.arrayBuffer();
console.log(`Video ready: ${result.unsigned_urls[0]}`);
# Asha submits the job and polls until completion, then returns the final job.
curl -X POST "https://app.asha-ai.ir/v1/videos"
-H "Authorization: Bearer $ASHA_API_KEY"
-H "Content-Type: application/json"
-d '{
"model": "~google/veo-3.1",
"prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background"
}'
# Response:
# {
# "id": "<job_id>",
# "status": "completed",
# "unsigned_urls": ["https://.../output.mp4"],
# "usage": { "cost": 3750, "is_byok": false }
# }
# Once completed, download from unsigned_urls[0]
پارامترهای درخواست
| پارامتر | نوع | الزامی | شرح |
|---|---|---|---|
model | string | بله | مدل تولید ویدئو (مثل ~google/veo-3.1) |
prompt | string | بله | توصیف متنی ویدئوی موردنظر |
duration | integer | خیر | مدت ویدئوی تولیدی بر حسب ثانیه |
resolution | string | خیر | رزولوشن خروجی (مثل 720p، 1080p) |
aspect_ratio | string | خیر | نسبت تصویر خروجی (مثل 16:9، 9:16، 3:2) |
size | string | خیر | ابعاد پیکسل دقیق با فرمت WIDTHxHEIGHT (مثل 1280x720). بهجای resolution + aspect_ratio هم کار میکند |
frame_images | array | خیر | تصاویر قاب اول/آخر (تبدیل تصویر به ویدئو) |
input_references | array | خیر | تصاویر مرجع برای هدایت سبک (مرجع به ویدئو) |
generate_audio | boolean | خیر | آیا صدا هم کنار ویدئو تولید شود. برای مدلهای دارای خروجی صوتی بهطور پیشفرض true است |
seed | integer | خیر | Seed برای تولید قطعی (توسط همهٔ ارائهدهندهها تضمین نمیشود) |
provider | object | خیر | پیکربندی عبور پارامترهای مختص ارائهدهنده |
رزولوشنهای پشتیبانیشده
480p720p768p1080p1K2K4K
نسبتهای تصویر پشتیبانیشده
16:9— گسترده (سینمایی)9:16— عمودی (پرتره)1:1— مربع4:3— استاندارد3:4— پرترهٔ استاندارد3:2— چشمانداز عکاسی2:3— پرترهٔ عکاسی21:9— فوقعریض9:21— فوقبلند
استفاده از تصاویر
دو راه برای دادن تصویر وجود دارد که هر کدام حالت متفاوتی را فعال میکند:
frame_images— تصاویر قاب اول یا آخر برای حالتِ تصویر به ویدئو. هر ورودی بایدframe_typeاز نوعfirst_frameیاlast_frameداشته باشد.input_references— تصاویر مرجعِ سبک یا محتوا برای حالتِ مرجع به ویدئو. مدل از آنها بهعنوان راهنمای بصری استفاده میکند، نه قاب دقیق.
اگر هر دو فیلد پر شوند، frame_images اولویت دارد و درخواست
«تصویر به ویدئو» تلقی میشود.
تصویر به ویدئو (frame_images)
{
"model": "~alibaba/wan-2.7",
"prompt": "A character walking through a forest",
"frame_images": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/first-frame.png"
},
"frame_type": "first_frame"
}
],
"resolution": "1080p"
}
مرجع به ویدئو (input_references)
{
"model": "~alibaba/wan-2.7",
"prompt": "A colossal solar flare beside a planet",
"input_references": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/style-ref.png"
}
}
],
"resolution": "1080p"
}
گزینههای مختص ارائهدهنده
با پارامتر provider گزینههای مختص ارائهدهنده را بفرستید.
گزینهها با نام ارائهدهنده کلید میخورند و فقط گزینههای ارائهدهندهٔ جورشده منتقل میشوند:
{
"model": "~google/veo-3.1",
"prompt": "A time-lapse of a flower blooming",
"provider": {
"options": {
"google-vertex": {
"parameters": {
"personGeneration": "allow",
"negativePrompt": "blurry, low quality"
}
}
}
}
}
گزینههای عبوری که هر مدل میپذیرد، در دادهٔ مدل در GET /v1/models قابل مشاهده است.
قالب پاسخ
درخواست POST /v1/videos پس از رسیدن کار به وضعیت
نهایی، خودِ کارِ تکمیلشده را برمیگرداند. فیلد status
برابر completed است، آرایهٔ
unsigned_urls آدرسهای دانلود محتوا را دارد و
usage.cost هزینهٔ نهایی را به تومان گزارش میکند:
{
"id": "abc123",
"generation_id": "gen-1234567890-abcdef",
"status": "completed",
"unsigned_urls": [
"https://storage.openrouter.ai/files/abc123.mp4"
],
"usage": {
"cost": 3750,
"is_byok": false
}
}
وضعیتهای کار
چون آشا تا رسیدن به وضعیت نهایی نظرسنجی میکند، کلاینت معمولاً فقط وضعیت
completed را میبیند. وضعیتهای شکست با خطای
502 Bad Gateway و پیام حاوی خطای ارائهدهنده
برمیگردند و هزینهای کسر نمیشود:
| وضعیت | شرح |
|---|---|
completed | ویدئو آمادهٔ دانلود است (پاسخ موفق) |
failed | تولید شکست خورده است (فیلد error را ببینید) |
cancelled | کار لغو شده است |
expired | کار از محدودهٔ زمانی مجاز گذشته است |
دانلود ویدئو
پس از تکمیل، فایل را مستقیم از آدرسهای داخل
unsigned_urls دانلود کنید (بدون نیاز به هدر
احراز هویت):
curl "https://storage.openrouter.ai/files/abc123.mp4"
--output video.mp4
وقتی مدل چند خروجی تولید کند، هر خروجی یک آدرس جداگانه در همین آرایه دارد.
بهترین روشها
- Prompt دقیق — برای کیفیت بهتر ویدئو، promptهای مشخص و توصیفی بدهید؛ جزئیات حرکت، زاویهٔ دوربین، نور و ترکیببندی صحنه را بنویسید.
- رزولوشن مناسب — رزولوشن بالاتر، کندتر و گرانتر است؛ بر اساس کاربردتان انتخاب کنید.
- مدیریت انتظار — درخواست تا رسیدن به وضعیت نهایی باز میماند؛ تایماوت سمت کلاینت را بهاندازهٔ کافی بلند بگیرید (تولید ویدئو معمولاً بین ۳۰ ثانیه تا چند دقیقه طول میکشد).
- مدیریت خطا — همیشه وضعیت
failedرا چک کنید و فیلدerrorرا مناسب مدیریت کنید. - تصاویر مرجع — هنگام استفاده از تصویر مرجع، مطمئن شوید باکیفیت و مرتبط با خروجی مطلوب است.
عیبیابی
درخواست زمان زیادی طول میکشد؟
- تولید ویدئو بسته به مدل، رزولوشن و بار سرور میتواند چند دقیقه طول بکشد
- تایماوت سمت کلاینت را بهاندازهٔ کافی افزایش دهید
تولید شکست خورد؟
- پیام خطا و فیلد
errorرا در پاسخ چک کنید - مطمئن شوید مدل تولید ویدئو را پشتیبانی میکند — در GET /v1/models،
architecture.output_modalitiesشاملvideoباشد - از مناسببودن prompt و رعایت راهنمای مدل مطمئن شوید
- چک کنید تصاویر مرجع در دسترس و با فرمت پشتیبانیشده باشند
مدل پیدا نمیشود؟
- با GET /v1/models یا صفحهٔ مدلها مدلهای موجود را پیدا کنید
- درستی نام مدل را چک کنید (مثل
~google/veo-3.1)
سؤالات متداول
تولید ویدئو چقدر طول میکشد؟
بسته به مدل و رزولوشن معمولاً بین ۳۰ ثانیه تا چند دقیقه. آشا نتیجهٔ نهایی را بهصورت همزمان (server-side) پس از تکمیل برمیگرداند.
آیا تولید ویدئو ناهمگام است؟
بله؛ آشا درخواست را بهصورت ناهمگام نزد ارائهدهنده ثبت میکند، تا رسیدن به وضعیت نهایی پیگیری میکند و سپس همان پاسخ، کارِ تکمیلشده را با آدرسهای دانلود (unsigned_urls) برمیگرداند.
میتوانم با تصویر شروع کنم؟
بله؛ با frame_images برای قاب اول/آخر (تصویر به ویدئو) و با input_references برای هدایت سبک (مرجع به ویدئو).
هزینهٔ ویدئو چگونه حساب میشود؟
بر اساس مدت (ثانیه) و رزولوشن؛ فیلد pricing_skus هر مدل و هزینهٔ نهایی در usage.cost به تومان گزارش میشود.
آیا صدا هم تولید میشود؟
برای مدلهای پشتیبانیکننده بله، بهصورت پیشفرض با generate_audio: true؛ میتوانید آن را خاموش کنید.