HiAPI
Блог

Руководство

PixVerse V6 API преобразования изображения в видео: готовые к запуску примеры curl и Python

Oct 20, 2026
PixVerse V6 API преобразования изображения в видео: готовые к запуску примеры curl и Python
Модель
pixverse-v6

Чтобы анимировать статичное изображение с помощью pixverse-v6/image-to-video на hiapi, достаточно одного вызова POST /v1/tasks и одного опроса — это в точности та же асинхронная модель задач, что используется для всех генерирующих моделей на платформе. От эндпоинта преобразования текста в видео его отличает входной набор: нужно передать стартовый кадр (image_url) и промпт, описывающий, как он должен двигаться. В этом руководстве приведены готовые к копированию примеры на curl и Python, поля ввода, которые эндпоинт фактически проверяет, и одна неожиданность, в которую спотыкаются люди, переходящие с преобразования текста в видео.

Что вам понадобится

  • Ключ API hiapi. Создайте его в консоли и отправляйте в заголовке Authorization: Bearer sk-<your-key>. Формат заголовка описан в документации по аутентификации.
  • ID модели pixverse-v6/image-to-video (сохраняйте косую черту — она часть ID, а не путь URL). Это отдельный ID модели, отличный от pixverse-v6/text-to-video.
  • Публично доступный URL изображения в качестве первого кадра. Платформа забирает изображение на стороне сервера, поэтому ссылки на localhost или приватные хранилища не подойдут — разместите первый кадр там, куда API сможет обратиться методом GET.
  • Для curl ничего устанавливать не нужно. Для примера на Python нужны только стандартная библиотека и requests.

PixVerse V6 преобразование изображения в видео берёт предоставленное вами статичное изображение как стартовый кадр и анимирует его в клип длительностью 1–15 секунд. Оно работает через единый API асинхронных задач — вы отправляете задачу, опрашиваете результат, а затем скачиваете его, пока выходной URL не истёк.

Минимальный рабочий запрос (curl)

Отправьте задачу на POST /v1/tasks. Поля image_url и prompt обязательны:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "pixverse-v6/image-to-video",
    "input": {
      "image_url": "https://cdn.example.com/your-first-frame.jpg",
      "prompt": "Slow push-in; the subject turns toward the camera and smiles, soft breeze in the hair",
      "duration": 5,
      "resolution": "720p"
    }
  }'

В ответе вернётся ID задачи:

{ "code": 200, "data": { "taskId": "a1b2c3d4-...." } }

Затем опрашивайте GET /v1/tasks/<taskId>, пока data.status не станет success:

curl -s https://api.hiapi.ai/v1/tasks/a1b2c3d4-.... \
  -H "Authorization: Bearer sk-<your-key>"

При успехе URL готового видео находится в data.output[0].url:

{
  "code": 200,
  "data": {
    "status": "success",
    "output": [{ "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }]
  }
}

Этот выходной URL временный — он содержит отметку времени expireAt. Скачайте .mp4 сразу и сохраните в собственное хранилище; не используйте его как горячую ссылку.

Тот же процесс на Python

import time, requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<your-key>", "Content-Type": "application/json"}

def create_task():
    payload = {
        "model": "pixverse-v6/image-to-video",
        "input": {
            "image_url": "https://cdn.example.com/your-first-frame.jpg",
            "prompt": "Slow push-in; the subject turns toward the camera and smiles",
            "duration": 5,
            "resolution": "720p",
        },
    }
    r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    data = r.json()
    task_id = (data.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"create failed: {data}")  # 400s echo the exact bad field
    return task_id

def wait_for(task_id, timeout_s=600):
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        try:
            r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
            task = (r.json().get("data") or {})
        except requests.RequestException:
            time.sleep(5)          # one transient network blip should not abort the whole poll
            continue
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"task failed: {task.get('error')}")
        time.sleep(5)              # still pending — keep the SAME task_id, re-poll
    raise TimeoutError(task_id)

task_id = create_task()
url = wait_for(task_id)
video = requests.get(url, timeout=120).content
open("out.mp4", "wb").write(video)
print("saved out.mp4")

Цикл опроса явно проверяет success и fail и продолжает ждать при любом другом статусе, поэтому он надёжно справляется с любыми промежуточными метками, которые задача сообщает во время рендеринга. Если один запрос опроса завершился ошибкой, подождите и опросите тот же сохранённый task_id, а не отправляйте задачу повторно — повторная отправка приведёт к оплате второго рендеринга.

Параметры, которые фактически проверяет pixverse-v6/image-to-video

Ниже приведены поля, которые реально принимает рабочий эндпоинт. Я подтвердил каждое, отправляя недопустимые значения и читая ошибки валидации, а затем сверил с документацией модели:

Поле Тип Значения / диапазон Описание
image_url string Публичный URL изображения Обязательно. Первый кадр. Одна строка URL — не массив.
prompt string — Обязательно. Описывает движение, применяемое к этому кадру.
duration integer 1–15, по умолчанию 5 В секундах. Должно быть целым числом, а не строкой.
resolution string 360p, 540p, 720p, 1080p Разрешение вывода.
negative_prompt string — Необязательно; контент, которого нужно избегать.
seed integer — Необязательно; повторное использование для воспроизводимых результатов.
style string anime, 3d_animation, clay, comic, cyberpunk Необязательный предустановленный стиль.
generate_audio boolean true / false, по умолчанию false Необязательно; включает или выключает генерируемую звуковую дорожку / фоновый звук.

Здесь нет поля aspect_ratio. Это единственное реальное отличие от запросов преобразования текста в видео, которые вы, возможно, видели, и его стоит запомнить (см. ниже).

Замечания для продакшена

  • Нет aspect_ratio — геометрия вывода следует за вашим входным изображением. Эндпоинт преобразования текста в видео принимает перечисление aspect_ratio; этот эндпоинт его отклоняет. Поскольку вы предоставляете первый кадр, клип наследует размеры этого кадра. Если вам нужен вертикальный клип 9:16, обрежьте или дополните image_url до 9:16 до отправки — нет ручки соотношения, которая могла бы это переопределить.
  • Структура запроса закрыта. Любое поле за пределами таблицы выше отклоняется с ошибкой invalid input: <root>: additional properties '<field>' not allowed. Опечатки или угаданные поля громко проваливаются при отправке, а не игнорируются молча. Такие поля, как first_frame, image, input_image, motion_mode и camera_movement, отклоняются — стартовое изображение передаётся в image_url, а движение камеры описывается текстом в prompt.
  • duration — целое число, в отличие от некоторых других видеомоделей на платформе, принимающих строки ("6"). Отправка "5" вернёт invalid input: duration: got string, want integer. Значения вне диапазона сообщают границу напрямую, например duration: maximum: got 999, want 15.
  • Ошибки возвращаются по одному полю за раз в плоском формате конверта: {"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: image_url: missing required field \"image_url\""}. Исправьте указанное поле и отправьте повторно; следующее недопустимое поле (если есть) всплывёт при следующем вызове.
  • Ошибка задачи всё равно возвращает HTTP 200. Информация об ошибке находится в теле ответа в виде data.status: "fail" — проверяйте поле статуса, а не только HTTP-код. Частой причиной является URL изображения, который платформа не может получить, поэтому сначала убедитесь, что ваш первый кадр публичен.
  • Оплата по секундам и растёт с разрешением и длительностью, поэтому клип 1080p/15s значительно дороже клипа 540p/3s. Перед массовой генерацией сверьтесь с текущими тарифами на странице цен.

Что я проверил (и что не проверял)

Я выяснил входной контракт, отправляя намеренно недопустимые значения на рабочий эндпоинт /v1/tasks для pixverse-v6/image-to-video и читая собственные ответы валидации API — это был только читающий зонд схемы, без обратных вызовов и без затрат на рендеринг. Конкретные находки, которые стоит запомнить:

  • image_url — обязательное поле первого кадра, и это одна строка, а не массив. Отправка числа возвращает image_url: got number, want string; пропуск возвращает missing required field "image_url". Угадываемые альтернативные поля (first_frame, image, input_image) отклоняются как неизвестные свойства.
  • Этот эндпоинт отклоняет aspect_ratio (additional properties 'aspect_ratio' not allowed), хотя оно допустимо в pixverse-v6/text-to-video. Именно поэтому запрос преобразования изображения в видео выглядит иначе, чем запрос преобразования текста в видео: форма вывода определяется вашим кадром, а не параметром.
  • generate_audio — настоящий булев переключатель (по умолчанию false) — отправка строки возвращает generate_audio: got string, want boolean. Если вам нужен звук, установите true; он не включается и не выключается принудительно.

В ходе этого зонда я не рендерил клипы, поэтому руководство не утверждает ничего о качестве движения или о том, насколько точно модель сохраняет входной кадр — оно лишь фиксирует точный контракт запроса, который обеспечивает этот эндпоинт.

Связанные материалы

Часто задаваемые вопросы

Почему в преобразовании изображения в видео нет aspect_ratio?Потому что клип начинается с вашего кадра image_url и наследует его размеры. Чтобы управлять соотношением вывода, измените размер или обрежьте входное изображение перед отправкой — этот эндпоинт отклоняет aspect_ratio как неизвестное поле.

Принимает ли image_url несколько изображений?Нет. На этом эндпоинте это одна строка URL; передача массива приведёт к ошибке валидации. Он задаёт только стартовый кадр.

duration измеряется в секундах или кадрах?В секундах — любое целое число от 1 до 15, по умолчанию 5. Должно быть целым; строка "5" будет отклонена.

Чем это отличается от эндпоинта преобразования текста в видео?pixverse-v6/image-to-video анимирует предоставленный вами кадр (image_url + prompt, без aspect_ratio). pixverse-v6/text-to-video — отдельный ID модели, генерирует только по промпту и действительно принимает aspect_ratio. Используйте преобразование изображения в видео, когда у вас уже есть точный стартовый статичный кадр, который вы хотите оживить.

Почему мой запрос падает с ошибкой "additional properties not allowed"?Вы отправили поле, которого нет в схеме. Ввод принимает только image_url, prompt, duration, resolution, negative_prompt, seed, style и generate_audio.

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

Все статьи →

Начните работать с постоянными артефактами ИИ

Получите API-ключ и вызывайте модели изображений, видео и аудио через один API на основе tasks.

Читать документацию API