Руководство
Как вызвать veo-3.1-lite/text-to-video через HiAPI API: curl и Python
Готовые к копированию примеры запросов, процесс генерации видео по промпту и режим асинхронного опроса
Что даёт veo-3.1-lite/text-to-video
veo-3.1-lite/text-to-video — это эндпоинт генерации видео из текста на HiAPI: вы отправляете текстовый промпт, а модель возвращает сгенерированный видеоклип. Слово "lite" в названии — самый важный сигнал при выборе модели. Уровень облегчённой версии создан ради пропускной способности и быстрых итераций, а не ради максимальной точности, поэтому он отлично подходит по умолчанию, когда нужно много коротких клипов, когда вы прототипируете функциональность перед тем, как остановиться на более тяжёлой модели, или когда клип — лишь звено в более крупном автоматизированном конвейере, где задержка одного клипа и масштаб пакетной обработки важнее кинематографического качества.
Когда клип сам по себе является продуктом — например, ключевой визуальный кадр, маркетинговый материал или любой контент, который будут покадрово рассматривать, — стоит перейти на более тяжёлую модель генерации видео из текста. А когда клип — лишь составная часть — например, черновой предпросмотр, фоновый цикл, грубый раскадровочный набросок или первый рендер, который потом будет дорабатываться, — выбирайте veo-3.1-lite/text-to-video.
Две особенности этого эндпоинта определяют всё дальнейшее:
- Он асинхронный. Запрос на генерацию не возвращает готовый к воспроизведению файл в том же ответе. Вы отправляете задачу, получаете ссылку на неё, а затем опрашиваете, пока задача не завершится и URL результата не станет доступен.
- Он управляется промптом. В этом процессе нет входного изображения или исходного видео — отправленный текст и есть полноценный творческий бриф, поэтому качество промпта — ваш главный рычаг.
Остальная часть руководства — это пошаговое практическое занятие: построение запроса, отправка через curl, перенос в Python, корректный опрос и обработка сбоев, с которыми вы реально столкнётесь.
Предварительные требования и аутентификация
Перед первым вызовом убедитесь, что у вас есть:
- API-ключ из вашей учётной записи HiAPI. Относитесь к нему как к паролю от базы данных — храните в тайне.
- Способ отправлять HTTP-запросы:
curlдля быстрых проверок и Python 3 с библиотекойrequestsдля любых сценариев. - Место для хранения итогового клипа, поскольку результат приходит в виде URL, который нужно скачать.
Ключ передаётся в каждом запросе через HTTP-заголовок. Точно копируйте показанное имя заголовка и префикс Bearer; отсутствующий или неправильно отформатированный заголовок — самая частая причина неудачи при первом вызове.
Держите ключ подальше от системы контроля версий
Никогда не вставляйте настоящий ключ в файл, который вы будете коммитить. Используйте переменные окружения:
export HIAPI_API_KEY="your-key-here"
Затем читайте её во время выполнения. Если вы работаете в команде или в CI-конвейере, храните ключ в менеджере секретов и внедряйте его как переменную окружения при развёртывании. Если ключ когда-либо был раскрыт — например, случайно закоммичен, вставлен в тикет или выведен в лог, — немедленно выполните ротацию, а не надейтесь, что никто не заметит.
Прежде чем отлаживать что-либо ещё, быстро проверьте, что переменная окружения задана:
test -n "$HIAPI_API_KEY" && echo "key is set" || echo "key is missing"
Работающий запрос curl
Ниже показан вид запроса на отправку задачи генерации видео из текста. Замените заполнитель базового адреса эндпоинта на адрес, указанный в вашей справочной документации HiAPI, и строго сохраняйте идентификатор модели: veo-3.1-lite/text-to-video.
curl -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-lite/text-to-video",
"prompt": "A slow dolly-in on a rain-soaked neon sign at night, shallow depth of field, gentle camera drift, cinematic color"
}'
Успешная отправка не возвращает байты видео. Она возвращает объект задачи: идентификатор этой задачи, поле status с начальным значением вроде queued или processing, а также метаданные о времени создания. Этот идентификатор — дескриптор для всех последующих действий: вы опрашиваете его, пока статус не станет терминальным, и только тогда ответ будет содержать URL сгенерированного клипа.
Если вы тестируете вручную, сохраняйте полный ответ, а не просто смотрите на него:
curl -s -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"veo-3.1-lite/text-to-video","prompt":"A paper boat drifting down a sunlit gutter, macro lens"}' \
| tee submission.json
Две привычки стоит выработать прямо сейчас. Во-первых, всегда отправляйте Content-Type: application/json; тело запроса, которое выглядит как JSON, но не объявлено как JSON, будет отклонено. Во-вторых, если вызов не удался, сначала прочитайте тело ответа с ошибкой, прежде чем что-либо менять — HiAPI возвращает структурированные сообщения, которые обычно точнее указывают на проблему (неверный ключ, неизвестная модель, отсутствующее поле), чем один только код состояния.
Если здесь возвращается код состояния не из диапазона 2xx, значит, задача так и не была принята. Не опрашивайте неудачную отправку; сначала исправьте запрос.
Тот же запрос на Python
Вызов curl легко переносится. Скрипт ниже отправляет промпт, проверяет, что отправка успешна, и сохраняет ссылку на задачу для шага опроса.
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"]
API_KEY = os.environ["HIAPI_API_KEY"]
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "veo-3.1-lite/text-to-video",
"prompt": (
"A single lantern floating on still black water, "
"soft ripples, warm light against cool darkness, slow push-in"
),
}
response = requests.post(
f"{BASE_URL}/v1/videos/generations",
headers=headers,
json=payload,
timeout=30,
)
if response.status_code >= 400:
raise RuntimeError(f"Submission failed: {response.status_code} {response.text}")
job = response.json()
job_id = job["id"]
print(f"submitted job {job_id} with status {job.get('status')}")
В этом фрагменте есть несколько намеренных решений:
- Использование
json=payloadвместо ручной сборки строки. Пусть библиотека занимается сериализацией и установкой типа содержимого; так вы избегаете целого класса ошибок, связанных с кавычками. - Явная установка
timeout. Без неё зависшее соединение заставит скрипт висеть бесконечно. Вызов отправки быстрый — даже щедрый таймаут здесь остаётся коротким. - Жёсткий сбой при коде не из диапазона 2xx. Немедленное исключение привязывает ошибку к её причине, а не позволяет испорченному ID задачи распространиться в цикл опроса.
- Ключ берётся из
os.environ. Сам файл не содержит никаких секретов.
Оберните это в функцию, возвращающую job_id, и у вас будет готовая часть отправки для любого конвейера.
Опрос асинхронной задачи и скачивание клипа
Генерация видео требует времени. Вызов отправки возвращается за одну-две секунды; фактический рендеринг — нет. Если вы напишете код, предполагающий, что первый ответ содержит URL видео, он потерпит неудачу — не потому, что API сломан, а потому, что вы читаете ещё не завершённую задачу.
Правильный шаблон — ограниченный опрос: пауза между проверками, увеличение задержки по мере роста времени ожидания и отказ после достижения максимального числа попыток вместо бесконечного цикла.
import time
import requests
def wait_for_video(job_id, headers, base_url, max_attempts=60, initial_delay=5):
delay = initial_delay
for attempt in range(1, max_attempts + 1):
r = requests.get(
f"{base_url}/v1/videos/generations/{job_id}",
headers=headers,
timeout=30,
)
if r.status_code >= 400:
raise RuntimeError(f"Poll failed: {r.status_code} {r.text}")
data = r.json()
status = data.get("status")
print(f"attempt {attempt}: {status}")
if status == "completed":
return data
if status in {"failed", "cancelled"}:
raise RuntimeError(f"Job {job_id} ended as {status}: {data}")
time.sleep(delay)
delay = min(delay * 1.5, 30)
raise TimeoutError(f"Job {job_id} did not finish within polling budget")
Когда задача достигает состояния completed, ответ содержит местоположение результата — URL готового клипа. Если клип большой, скачивайте его, а не читайте поток в память целиком:
result = wait_for_video(job_id, headers, BASE_URL)
video_url = result["output"]["url"]
with requests.get(video_url, stream=True, timeout=120) as r:
r.raise_for_status()
with open(f"{job_id}.mp4", "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)
print("saved", f"{job_id}.mp4")
В продакшене важны две детали. Во-первых, URL результата может иметь ограниченное время жизни, поэтому скачивайте вовремя, а не сохраняйте ссылку на несколько дней, чтобы потом её получить — сохраняйте файл или копируйте в собственное хранилище. Во-вторых, записывайте ID задачи рядом с каждым выходным артефактом. Когда в дальнейшем что-то пойдёт не так, ID задачи позволит сверить ваши записи с тем, что фактически вернул API.
Типичные ошибки и способы их исправления
Большинство неудач при первом запуске относятся к нескольким категориям. Ниже — как проявляется каждая из них и что нужно изменить.
Сбой аутентификации
Код 401 или 403 при отправке означает, что ключ не принят. Проверяйте по порядку: действительно ли переменная окружения имеет значение в этой оболочке или процессе; называется ли заголовок Authorization; присутствует ли префикс Bearer и есть ли после него пробел; не был ли ключ ротирован или отозван. Ключ, который работает в вашем терминале, но не работает в CI, почти всегда означает, что секрет не был внедрён в эту среду.
Недействительный идентификатор модели
Код 400 или 404 с указанием имени модели означает, что строка не совпадает. Идентификатор — veo-3.1-lite/text-to-video; косая черта и номер версии являются его частью. Копируйте и вставляйте, а не вводите заново; лишнего пробела или изменённого номера версии достаточно для сбоя.
Неправильный формат или пустой промпт
Пустой prompt, отсутствующее поле prompt или отправка тела запроса без Content-Type: application/json будут отклонены ещё до начала генерации. Если вы строите промпт динамически, логируйте точную строку, которую отправили, при сбое вызова — баги в шаблонах, порождающие пустые или обрезанные промпты, встречаются часто и невидимы, пока их не распечатать.
Тайм-аут опроса
Если wait_for_video исчерпал бюджет, не отправляйте задачу повторно сразу. Задача может всё ещё выполняться. Ещё раз проверьте статус, убедитесь, что ваш интервал опроса не настолько велик, что весь бюджет уходит на сон, и что бюджет реалистичен для запрошенной длины клипа. Повторная отправка при каждом тайм-ауте — именно так вы случайно платите несколько раз за один и тот же клип.
Ограничения частоты
429 означает, что нужен откат. Экспоненциальная задержка в цикле опроса уже помогает в этом; применяйте ту же сдержанность к отправке и ставьте работу в очередь, вместо того чтобы отправлять её залпами. Если сомневаетесь, сначала следуйте любым подсказкам о повторной попытке в заголовках ответа, а затем действуйте по собственному плану отката.
Рекомендации по затратам и итерациям перед продакшеном
Генерация видео оплачивается по объёму результата — то есть по длине созданного вами контента, — поэтому дорогостоящая ошибка — тестировать маленькие идеи длинными клипами. Самый экономный рабочий процесс — тот, который никогда не генерирует ненужные вам клипы.
Тестируйте структуру промпта, а не финальный результат. Пишите и оттачивайте промпты на минимальной длительности, поддерживаемой этим эндпоинтом. Как только композиция, движение и язык камеры читаются правильно на коротком клипе, увеличивайте длительность для финального рендера. Большинство итераций промпта касаются формулировки, а не длины, и короткий рендер точно так же отвечает на вопросы формулировки.
Ведите журнал промптов. Записывайте промпт, длительность и свою оценку для каждого теста. Десять задокументированных итераций дадут вам больше понимания того, на что реагирует модель, чем пятьдесят недокументированных, и вы не будете повторно тестировать уже отвергнутый промпт.
Пакетная обработка с умом. Если вам нужно много клипов, ставьте их в очередь и запускайте параллельно в пределах ограничений частоты — но сначала прогоните всю партию на небольшом количестве промптов. Обнаружить системный баг в промптах после отправки двухсот задач — самая предотвратимая статья расходов.
Опрашивайте сдержанно. Частый опрос не ускорит рендеринг и может привести к ограничению частоты. Умеренный начальный интервал плюс мягкий откат — правильные значения по умолчанию.
Падайте рано и громко. Каждая защита в приведённом выше коде — исключение при коде не из диапазона 2xx при отправке, обнаружение терминального сбоя при опросе, ограниченное число попыток — нужна, чтобы вы не платили дважды за одну и ту же работу. Сохраняйте их в продакшене.
Начните с короткого промпта и запроса curl, убедитесь в жизненном цикле задачи от начала до конца, а затем перенесите тот же процесс в свой Python-конвейер. Полный справочник по эндпоинту находится на странице документации модели veo-3.1-lite/text-to-video в HiAPI.
Похожие статьи
Все статьи →-
Руководство
Как вызвать hailuo-2.3-fast/image-to-video через HiAPI API: практика с curl и Python
Первый рабочий запрос к быстрому и недорогому уровню генерации видео по изображению — от ID модели до загрузки MP4
-
Руководство
Как вызывать hailuo-2.3/text-to-video через API HiAPI: curl, Python и рабочие примеры запросов
-
Руководство
Использование Kandinsky 6.0 Pro для преобразования текста в видео на HiAPI: руководство по curl и Python
Практическая демонстрация с упором на запросы: построение вызова от промпта до видеоклипа, отправка запроса, опрос статуса завершения и скачивание результата