GPT-6 Sol и Claude Opus 5.5 уже доступныGPT-6 Sol вдвое дешевле 5.6 Sol

API Wan 3.0: текст в видео и изображение в видео на Python

Один скрипт, два клипа: код, реальное время и цена Alibaba за секунду.

Kiki, OmniaKey COO8 мин чтения
На этой странице

Wan 3.0 работает в Alibaba Cloud Model Studio под идентификатором wan3.0-video и под более быстрым wan3.0-video-prime. Каждый вызов асинхронный: создать задачу, опросить ID, скачать MP4. Наш скрипт на Python сделал 5-секундный клип 720P из текста за 2 min 42 s и клип из кадра за 3 min 20 s, оба со звуком.

  1. Положите ключ в OMNIAKEY_API_KEY.
  2. Отправьте POST на https://api.omniakey.com/v1/media/tasks с моделью, операцией, промптом, параметрами и новым Idempotency-Key.
  3. Опрашивайте GET /v1/media/tasks/{id}, пока статус не станет succeeded, затем сразу скачайте assets[0].url.

Есть ли официальный API Wan 3.0 и какую модель выбрать?

Да. Alibaba Cloud Model Studio — официальный API, в нём есть wan3.0-video и wan3.0-video-prime (справка обновлена 15 октября 2026 г.). Вызов создания требует заголовка X-DashScope-Async: enable, а путь Python у Alibaba — SDK DashScope 2.0.1 или новее.

Alibaba Model StudioOmniaKey
Оба ID моделиЕстьЕсть
Заголовок asyncНуженНе нужен
Ссылка на видео24 часаОколо 1 часа, продлевается
ОплатаЗа секундуЗа секунду
PythonSDK DashScopeСтандартная библиотека

Оба ID принимают одно тело запроса, и модель выбирает режим по присланным медиа. Скрипт ниже запускает wan3.0-video, переключает его строка MODEL. Wan 3.0 Prime мы не запускали: документация OmniaKey описывает его как те же возможности примерно за половину времени (проверено 31 октября 2026 г.).

Что нужно до первого вызова?

Три вещи, и первая — ключ:

  1. Ключ API OmniaKey, экспортированный в оболочке:

    bash
    export OMNIAKEY_API_KEY="your-key"
    
  2. Python 3. Скрипт использует только стандартную библиотеку, поэтому python3 запускает его как есть.

  3. Для изображения в видео нужен первый кадр: JPEG шириной около 1024 px или публичный HTTPS-URL. Скрипт не принимает файл больше 700 000 байт, потому что Base64 добавляет треть, а тело ограничено 1 MiB (документация, проверено 31 октября 2026 г.).

Какие параметры важны?

Семь полей делают основную работу, и каждое — значение внутри parameters.

ПараметрЧто делаетПо умолчанию
ДлительностьДлина клипа, секунды5
РазрешениеУровень размера кадра1080P
ПропорцииФорма кадраadaptive
ЗвукЗвуковая дорожкаon
SeedПодсказка для повтора-1
Расширение промптаПереписывает промптon
Водяной знакСтавит метку в углуoff

Скрипт задаёт длительность, разрешение и пропорции. Он просит 720P, тогда как по умолчанию у Alibaba 1080P, что по прайс-листу стоит вдвое дороже за секунду.

Как выглядит код на Python?

Скрипт ниже отработал без изменений 31 октября 2026 г.: только стандартная библиотека, оба режима, одна строка MODEL для переключения.

python
import base64
import json
import os
import time
import urllib.error
import urllib.request
import uuid

API = "https://api.omniakey.com/v1/media/tasks"
KEY = os.environ["OMNIAKEY_API_KEY"]
MODEL = "wan3.0-video"

def request(method, url, body=None, extra_headers=None):
    headers = {"Authorization": f"Bearer {KEY}", "User-Agent": "omniakey-example/1"}
    data = None
    if body is not None:
        headers["Content-Type"] = "application/json"
        data = json.dumps(body).encode()
    headers.update(extra_headers or {})
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    with urllib.request.urlopen(req, timeout=120) as resp:
        return json.load(resp)

def poll(url, attempts=5):
    for attempt in range(attempts):
        try:
            return request("GET", url)
        except urllib.error.HTTPError as err:
            if err.code < 500 or attempt == attempts - 1:
                raise
        except urllib.error.URLError:
            if attempt == attempts - 1:
                raise
        time.sleep(5 * (attempt + 1))

def run_task(body, out_path):
    task = request("POST", API, body, {"Idempotency-Key": str(uuid.uuid4())})["id"]
    print("task", task, flush=True)
    for _ in range(180):  # 5-second polls, up to 15 minutes
        time.sleep(5)
        state = poll(f"{API}/{task}")
        if state["status"] not in ("queued", "processing"):
            break
    else:
        raise TimeoutError(f"{task} is still {state['status']}: poll it again later, do not resubmit")
    if state["status"] != "succeeded":
        raise RuntimeError(state.get("error") or state["status"])
    asset_url = state["assets"][0]["url"]  # signed link: short-lived, so download now
    req = urllib.request.Request(asset_url, headers={"User-Agent": "omniakey-example/1"})
    with urllib.request.urlopen(req, timeout=300) as resp, open(out_path, "wb") as f:
        f.write(resp.read())
    return task

def text_to_video(prompt, out_path, duration=5, resolution="720P", ratio="16:9"):
    body = {
        "model": MODEL,
        "type": "video",
        "operation": "text_to_video",
        "input": {"prompt": prompt},
        "parameters": {"duration": duration, "resolution": resolution, "ratio": ratio},
    }
    return run_task(body, out_path)

def image_to_video(prompt, image_path, out_path, duration=5, resolution="720P"):
    with open(image_path, "rb") as f:
        raw = f.read()
    if len(raw) > 700_000:  # base64 adds a third, and the whole body must stay under 1 MiB
        raise ValueError("first frame too large: save it as a JPEG about 1024 px wide")
    frame = "data:image/jpeg;base64," + base64.b64encode(raw).decode()
    body = {
        "model": MODEL,
        "type": "video",
        "operation": "image_to_video",
        "input": {"prompt": prompt, "media": [{"type": "first_frame", "url": frame}]},
        "parameters": {"duration": duration, "resolution": resolution, "ratio": "adaptive"},
    }
    return run_task(body, out_path)

if __name__ == "__main__":
    print("done", text_to_video(
        "A blacksmith hammers a glowing horseshoe on an anvil in a dark forge. Sparks fly at each "
        "strike and light his leather apron. The camera slowly pushes in. Sound of the hammer ringing "
        "on steel and the fire crackling. No dialogue, no music, no text.",
        "forge.mp4",
    ))
    print("done", image_to_video(
        "Image 1 is the first frame. The paper boat drifts slowly to the right across the puddle. "
        "Light rain makes small ripples and the cafe lights shimmer in the water. The camera stays "
        "low and still. Sound of light rain. No dialogue, no music, no text.",
        "boat.jpg",
        "boat-drifts.mp4",
    ))

Что делает каждая часть:

  • run_task создаёт новый Idempotency-Key для каждой задачи. Повторная отправка того же ключа с тем же телом возвращает исходную задачу и никогда не списывает деньги дважды (документация, проверено 31 октября 2026 г.).
  • Он опрашивает каждые 5 секунд, максимум 15 минут, и затем поднимает TimeoutError.
  • Таймаут значит: опросить тот же ID позже; повторная отправка создаёт новый ключ, вторую задачу и второй счёт.
  • Он сразу скачивает первый URL ресурса, потому что подписанная ссылка живёт недолго.
  • image_to_video не принимает кадр больше 700 000 байт: Base64 добавляет треть, а тело ограничено 1 MiB.
  • Вызов изображения ставит пропорции adaptive, поэтому клип повторяет форму кадра.

Что он вывел:

text
task task_<id>
done task_<id>
task task_<id>
done task_<id>

Что получилось из двух вызовов?

Оба файла вернулись как MP4 длиной 5,04 секунды, 150 кадров при 30 fps, H.264, со стереодорожкой AAC при 44,1 kHz.

Текст в видео: кузница

Четыре кадра из клипа кузницы Wan 3.0
Текст в видео, 5 s при 720P: кадры на 0,3, 2,2, 3,5 и 4,7 секунды.

Клип следует промпту: кузнец в тёмной рубахе и кожаном фартуке бьёт молотом по раскалённой оранжевой подкове, на 2,2 секунды летят искры, и камера немного наезжает. Недостаток — выштампованное клеймо мастера неразборчивыми буквами на наковальне, хотя промпт просил без текста. От запуска до файла прошло 2 min 42 s; MP4 весит 6,6 МБ при 1280×720.

Изображение в видео: бумажный кораблик

Исходный кадр и три кадра из клипа с бумажным корабликом Wan 3.0
Изображение в видео: отправленный кадр (слева вверху), затем клип на 1,6, 3,5 и 4,7 секунды.

Первый кадр — изображение, сделанное в Nano Banana 2.1: красный бумажный кораблик в дождевой луже; его уменьшили до JPEG 1024×571 весом 158 КБ и отправили встроенным как data URL. Клип сохраняет сумеречный свет и мокрую брусчатку, ведёт кораблик слева направо, как просили, даёт круги на воде на 1,6 секунды и держит камеру низко и неподвижно. Вернулся он как 1284×716, потому что adaptive повторил форму кадра, за 3 min 20 s при 7,4 МБ.

Звук включён, и работает ли "no music"?

Звук включён по умолчанию. Gemini 3.8 Flash описал дорожку кузницы как металлический звон без речи и без музыки, а дорожку кораблика — как меланхоличную спокойную фортепианную мелодию, хотя этот промпт заканчивался на "no music". Гайд по промптам Alibaba (обновлён 16 октября 2026 г.) советует писать "No BGM" или "No background music", а в нашем промпте не было ни того, ни другого.

С "audio": false файл несёт только видеодорожку: наша 2-секундная задача 480P с фонарём пришла без звуковой дорожки, и Alibaba считает одинаково в обоих случаях.

КлипВремяРазмерЗвук
Кузница (текст)2 min 42 s1280×720Звон, без музыки
Кораблик (кадр)3 min 20 s1284×716Фортепиано вопреки "no music"
Фонарь, звук выкл.4 min 36 s854×480Без звуковой дорожки

Время в очереди меняется: задача на 2 секунды без звука заняла 4 min 36 s, дольше любого 5-секундного клипа 720P. Для формулировок промптов в гайде по промптам Wan 3.0 есть структура и примеры.

Как забрать видеофайл и сколько живут ссылки?

Опрашивайте GET /v1/media/tasks/{id}, пока статус не станет succeeded, failed или canceled; пока задача идёт, там queued или processing. Завершённая задача возвращает подписанный URL ресурса, который живёт около часа (документация OmniaKey, проверено 31 октября 2026 г.). Скачайте его сразу, а когда старая ссылка истечёт, опросите задачу снова ради свежей, потому что запись хранится 24 часа.

Файл — это MP4 с видео H.264 при 30 fps, а собственный URL видео у Alibaba живёт 24 часа. Отмена задачи Wan 3.0 не останавливает рендер, и задача, которая успешно завершилась после отмены, всё равно оплачивается, поэтому проверьте длительность и разрешение до отправки.

Какие ошибки вы увидите?

Большинство из них приходят раньше, чем появляется задача, и у каждой есть исправление в запросе или в ключе.

  • 400 model_price_error — длительность вне 2–30 секунд. Наша проверка с "duration": 1 упала за 0,9 s с "media duration must be between 2 and 30 seconds"; задача не создалась, и деньги не списались.
  • 400 missing_idempotency_key — нет заголовка Idempotency-Key. Добавьте его, до 255 символов.
  • 409 idempotency_key_reused — тот же ключ, другое тело. Создавайте новый ключ для каждого промпта.
  • 403 model_not_allowed — ключ не может вызывать эту модель. Проверьте значение model, затем настройки ключа.
  • 403 с сообщением о балансе или лимите расходов — мало средств или лимит на ключ. Пополните баланс или поднимите лимит.
  • 404 task_not_found — неверный ID или задача старше 24 часов. Опросите ID, который вернул вызов создания.
  • 409 task_state_conflict — задача уже завершилась, например когда отмена приходит после успеха. Сначала прочитайте статус.
  • 429 — слишком много запросов. OmniaKey не публикует фиксированные лимиты, поэтому ждите с экспоненциальной задержкой и джиттером.
  • 503 no_available_channel — нет канала для этой операции, например видео в видео. Используйте текст в видео или изображение в видео.
  • TimeoutError — всё ещё идёт после 15 минут. Опросите тот же ID позже; повторная отправка создаст вторую задачу и второй счёт.

Сколько стоит клип Wan 3.0?

Alibaba берёт плату за секунду видео, а неудачный запрос не оплачивается (страница цен обновлена 29 октября 2026 г.). В таблице — прайс-лист Alibaba за секунду для Сингапура, проверенный 31 октября 2026 г., по странице цен Alibaba для Model Studio.

Модель480P720P1080P
Wan 3.0$0.05$0.1$0.2
Wan 3.0 Prime$0.068$0.14$0.28

5-секундный клип 720P стоит у Alibaba $0.50 на Wan 3.0 (5 × $0.1) и $0.70 на Prime (5 × $0.14). У трёх цен Wan 3.0 стоит пометка "Limited-time 30% off", и страница не говорит, включена ли она в цифры. Звук включён или выключен — цена та же.

Бесплатная квота Alibaba — 30 секунд видео, вход плюс выход, на wan3.0-video в Сингапуре; у Prime её нет. У Alibaba в Китае (Пекин) для стандартной модели долларовые ставки ниже: $0.041256, $0.082513 и $0.165025 за секунду при 480P, 720P и 1080P.

OmniaKey тоже берёт плату за секунду, актуальные ставки — на страницах моделей Wan 3.0 и Wan 3.0 Prime.

Частые вопросы

Сколько идёт один вызов?

Alibaba пишет, что задача обычно занимает от 1 до 5 минут, и советует опрашивать каждые 15 секунд (справка, проверено 31 октября 2026 г.). Наши три задачи заняли 2 min 42 s, 3 min 20 s и 4 min 36 s.

Как выключить звук?

Поставьте "audio": false внутри parameters, и MP4 придёт только с видеодорожкой, как наша задача с фонарём. Цена не меняется.

wan3.0-video или wan3.0-video-prime?

Берите wan3.0-video ради более низкой ставки Alibaba и бесплатной квоты 30 секунд в Сингапуре, а Prime — когда важнее время. OmniaKey описывает Prime как те же возможности примерно за половину времени.

Сколько живёт ссылка на видео?

Около часа на OmniaKey, и повторный опрос задачи вернёт свежую ссылку, пока запись хранится 24 часа. Собственный URL видео у Alibaba живёт 24 часа.

Проверенные источники

Модели в этой статье

Wan 3.0video APIPythontext-to-videoimage-to-video

Похожие статьи

Недавние статьи