HiAPI
Блог

Руководство

API преобразования текста в видео PixVerse V6: рабочий пример curl и Python

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

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

Что нужно перед началом

  • API-ключ hiapi. Создайте его в консоли и передавайте в заголовке Authorization: Bearer sk-<ваш ключ>. Формат заголовка см. в документации по аутентификации.
  • model id — pixverse-v6/text-to-video. Сохраняйте косую черту посередине — это часть id, а не путь URL.
  • Для curl ничего устанавливать не нужно; в примере на Python используются только стандартная библиотека и requests.

PixVerse V6 преобразование текста в видео превращает текстовый запрос в видеоклип длительностью 1–15 секунд и разрешением от 360p до 1080p. Используется единый асинхронный интерфейс задач: отправить задачу → опрашивать результат → скачать видео до истечения срока действия URL вывода.

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

Отправьте задачу на POST /v1/tasks:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<ваш ключ>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "pixverse-v6/text-to-video",
    "input": {
      "prompt": "Ранним утром на солнце рыжая лиса бежит трусцой по свежему снегу, кинематографичное качество, замедленная съёмка",
      "aspect_ratio": "16:9",
      "duration": 5,
      "resolution": "720p"
    }
  }'

В ответе вы получите id задачи:

{ "code": 200, "data": { "taskId": "tk-hiapi-...." }, "message": "success" }

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

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-.... \
  -H "Authorization: Bearer sk-<ваш ключ>"

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

{
  "code": 200,
  "data": {
    "status": "success",
    "storage": "temp",
    "output": [
      { "type": "video", "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1793036664 }
    ]
  },
  "message": "success"
}

Этот URL вывода является временным — он содержит метку времени expireAt (по моим измерениям, 7 дней после генерации). Сразу скачайте .mp4 и сохраните в собственное объектное хранилище, не используйте этот адрес для прямых ссылок.

Тот же процесс (Python)

import time, requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<ваш ключ>", "Content-Type": "application/json"}

def create_task():
    payload = {
        "model": "pixverse-v6/text-to-video",
        "input": {
            "prompt": "Ранним утром на солнце рыжая лиса бежит трусцой по свежему снегу, кинематографичное качество, замедленная съёмка",
            "aspect_ratio": "16:9",
            "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"创建失败: {data}")
    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)          # 单次网络抖动不该让整个轮询中止
            continue
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"任务失败: {task.get('error')}")
        time.sleep(5)              # 还在排队/渲染——用同一个 task_id 继续轮询
    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("已保存 out.mp4")

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

Параметры, которые действительно проверяет pixverse-v6/text-to-video

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

Поле Тип Значение / диапазон По умолчанию Описание
prompt string 1–2048 байт UTF-8 (1 китайский иероглиф = 3 байта, около 682 символов) — Обязательно.
aspect_ratio enum 16:9, 4:3, 1:1, 3:4, 9:16, 2:3, 3:2, 21:9 16:9 Обратите внимание: поддерживаются 21:9 (сверхширокий) и 2:3/3:2.
duration integer 1–15 5 В секундах, должно быть целым числом, не строкой.
resolution enum 360p, 540p, 720p, 1080p 720p Разрешение вывода.
generate_audio boolean true / false false Генерировать ли одновременно фоновую музыку, звуковые эффекты и диалоги; по умолчанию выключено, для звука нужно явно включить.
negative_prompt string до 2048 байт UTF-8 — Необязательно; то, чего нужно избегать.
seed integer любое целое число — Необязательно; одинаковый seed + одинаковый prompt воспроизводят один и тот же результат.
style enum anime, 3d_animation, clay, comic, cyberpunk нет Необязательный стилевой пресет, оставьте пустым для естественного стиля.

Если нужно использовать callback вместо опроса, на одном уровне с input можно передать объект callback: url (HTTPS-адрес обратного вызова) + when (в настоящее время только final, то есть обратный вызов при конечном состоянии задачи).

Как писать для production

  • Это закрытая схема. Любое поле, отсутствующее в таблице выше, будет сразу отклонено с ошибкой invalid input: <root>: additional properties '<поле>' not allowed. Это на самом деле хорошо: опечатки или выдуманные поля громко проваливаются при отправке, а не игнорируются молча.
  • duration — целое число, в отличие от некоторых видеомоделей на платформе, которые принимают строку ("6"). Отправка "5" даст invalid input: duration: got string, want integer; выход за границы диапазона сразу сообщит границы, например, duration: maximum: got 999, want 15, duration: minimum: got 0, want 1.
  • Сообщение об ошибке указывает только на одно поле за раз, envelope плоский: {"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: aspect_ratio: value must be one of ..."}. Исправьте указанное поле и отправьте снова — следующее некорректное поле (если есть) всплывёт при следующем вызове.
  • При неудаче задачи HTTP всё равно 200. Информация о неудаче находится в data.status: "fail" тела ответа, судить нужно по этому полю status, а не по HTTP-коду состояния.
  • Опрос или callback? Для лёгких скриптов проще всего опрос; для масштабирования, когда не хочется держать соединения постоянно, используйте callback. В любом случае, получив output[0].url, сразу скачивайте — URL содержит expireAt, после истечения он станет 404.

Запись измерений: я действительно запустил один раз

Эта статья — не только лишь read-only пробы: я прошёл полный жизненный цикл с реальным запросом, запись ниже:

  • Создание: запрос выше с 720p / 5 секунд / 16:9 был отправлен и сразу вернул {"code":200,"data":{"taskId":"tk-hiapi-01M5AM..."},"message":"success"}. Обратите внимание, taskId — это строка с префиксом tk-hiapi-, а не UUID.
  • Опрос: data.status в GET /v1/tasks/<id> последовательно прошёл handling → archiving → success, весь 5-секундный ролик от создания до завершения занял около 74 секунд.
  • Вывод: в конечном состоянии data.output[0] равен {"type":"video","url":"https://temp.hiapi.ai/....mp4","expireAt":...,"artifactId":"...","storage":"temp"}. expireAt минус время создания составляет ровно 604800 секунд, то есть 7 дней.
  • Продукт: HEAD-запрос к этому URL вывода вернул content-type: video/mp4, размер около 2.2 MB, подтверждено, что это действительный mp4-файл.

Одно исправление насчёт аудио стоит отметить отдельно: я проверял несколько соседних имён полей с некорректными значениями — generate_audio вернул got string, want boolean (значит, это легальное булево поле), а sound, audio оба вернули additional properties not allowed (не существуют). То есть аудио контролируется переключателем generate_audio, по умолчанию false; на странице цен соответственно есть два уровня «Sound On / Sound Off». В этом измерении я не включал generate_audio, поэтому на выходе получился немой ролик.

Я не давал субъективной оценки качества изображения (в этот раз я проверил только контракт запроса, жизненный цикл задачи и то, что продукт является легальным mp4), эту часть оцените сами, сгенерировав со своим промптом.

Как рассчитывается стоимость

pixverse-v6/text-to-video тарифицируется по секундам (коэффициент биллинга — это duration), чем длиннее, тем дороже; чем выше разрешение, а также при включении generate_audio в режиме «Sound On», цена за секунду будет выше. Конкретные ставки за секунду смотрите в актуальных данных на странице цен, перед массовой генерацией взгляните на них.

Полезные ссылки

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

duration — это секунды или кадры? Секунды — любое целое число от 1 до 15, по умолчанию 5.

Можно ли генерировать видео со звуком? Да. Установите generate_audio в true, и модель сгенерирует вместе с фоновой музыкой, звуковыми эффектами и диалогами; по умолчанию false (без звука). Включение аудио переводит на более дорогой тариф, подробности на странице цен.

Насколько длинным может быть промпт? Верхний предел — 2048 байт UTF-8. Один китайский иероглиф считается за 3 байта, поэтому максимум около 682 китайских иероглифов.

Чем это отличается от преобразования изображения в видео? Этот эндпоинт (pixverse-v6/text-to-video) исходит только из текстового промпта. Преобразование изображения в видео — это другой model id, он принимает начальное изображение и оживляет его — если хотите оживить готовую картинку, а не генерировать с нуля, используйте его.

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

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

Все статьи →

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

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

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