HiAPI
Блог

Руководство

kandinsky-6.0-pro/image-to-video в HiAPI: руководство по curl + Python

Как выполнить рабочий запрос генерации видео из изображения в HiAPI: от загрузки первого кадра до асинхронного опроса и финальной загрузки

Nov 3, 2026
深色底上青绿与石板灰的扁平液态色块相互交叠,构成 kandinsky-6.0-pro 视频教程的封面图。

Обзор процесса image-to-video в HiAPI

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

Этап 1: отправка задачи

Вы отправляете POST-запрос на эндпоинт kandinsky-6.0-pro/image-to-video, приложив изображение первого кадра и короткий промпт с описанием ожидаемого движения. Ответ не содержит байтов видео, а принимает задачу и возвращает идентификатор задачи — этот дескриптор используется для всех последующих операций.

Этап 2: опрос статуса

Генерация видео занимает время, поэтому эндпоинт является асинхронным. Вы вызываете маршрут статуса с идентификатором задачи, и он сообщает текущее состояние задачи: в очереди, в обработке, успешно или неудачно. Вы периодически повторяете проверку, пока статус не станет терминальным.

Этап 3: получение результата

Как только задача сообщает об успехе, полезная нагрузка статуса содержит местоположение готового видео. Вы загружаете его и записываете на диск. Это весь контракт.

Почему такая форма важна

Разделение отправки и опроса не случайно. Это означает, что вашему HTTP-клиенту не нужно держать сокет открытым в течение всего рендеринга, а также что вы можете сохранить идентификатор задачи, уйти и вернуться позже. При ошибке поле статуса сообщает вам, где возникла проблема, что гораздо полезнее непрозрачного тайм-аута.

Запомните эти три этапа: отправка, опрос, загрузка. Примеры ниже на curl и Python — это просто два способа записи одной и той же последовательности.

Подготовка первого кадра и учётных данных API

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

Установка API-ключа как переменной окружения

Не вставляйте ключ в исходные файлы. Экспортируйте его в shell, чтобы и curl, и Python могли получить к нему доступ без жёсткого кодирования:

export HIAPI_API_KEY="your_api_key_here"

В Windows PowerShell эквивалентная запись — $env:HIAPI_API_KEY="your_api_key_here". Перед продолжением убедитесь, что shell его видит:

echo "$HIAPI_API_KEY" | head -c 4; echo

Вы должны увидеть первые несколько символов ключа. Если ничего не видно, переменная не сохранилась в текущей сессии shell — это частая причина последующих ответов 401.

Выбор подходящего изображения первого кадра

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

  • Формат: используйте стандартные веб-форматы изображений, такие как JPEG или PNG. Избегайте редких кодеков, прогрессивных крайних случаев или цветовых профилей CMYK.
  • Доступность: API должен действительно прочитать эти байты. Если вы передаёте URL, убедитесь, что он публично доступен или правильно аутентифицирован; если вы передаёте встроенные данные, убедитесь, что кодирование полное.
  • Размер: изображения разумного размера проходят валидацию быстрее. Очень большие файлы замедляют запрос и часто являются источником ошибок загрузки.
  • Содержание: выбирайте кадр, разумный в качестве отправной точки движения — чёткий субъект, простой фон. Промпт движения описывает, как уйти от этого кадра, поэтому зашумлённый кадр даст зашумлённое видео.

Решение, как ссылаться на изображение

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

  • Если файл уже размещён и публично читается, URL — самый лаконичный вариант.
  • Если изображение локальное или приватное, встроенное кодирование делает весь запрос самодостаточным ценой большего размера полезной нагрузки.

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

Отправка запроса с помощью curl

Это полный запрос на отправку. Замените своей ссылкой на изображение и промптом и запустите.

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://your-host.example/first-frame.jpg",
    "prompt": "slow dolly-in on the subject, gentle ambient motion, stable camera",
    "duration": 5,
    "aspect_ratio": "16:9"
  }'

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

  • URL указывает именно на модель kandinsky-6.0-pro/image-to-video. Выбор модели находится в пути, а не в теле запроса, поэтому опечатка здесь даст 404, а не дружелюбное сообщение валидации.
  • Authorization несёт bearer-токен из экспортированной вами переменной окружения. Ничто другое не аутентифицирует вызов.
  • Content-Type: application/json важен для любого POST с JSON-телом; без него некоторые прокси исказят полезную нагрузку до того, как она достигнет API.
  • image — ваша ссылка на первый кадр; здесь в форме URL, а если изображение приватное — в виде встроенной закодированной строки.
  • prompt описывает движение. Держите его о движении и поведении камеры, а не о пересказе того, что уже содержит изображение.
  • duration и aspect_ratio формируют результат. Соотношение сторон должно соответствовать первому кадру; несоответствие приведёт к обрезке или чёрным полосам. Оплата рассчитывается по сгенерированному результату, поэтому эти настройки также определяют ваши расходы.

Чтение ответа

Успешная отправка возвращает полезную нагрузку задачи, а не видео. Извлеките из неё идентификатор задачи — позже вы передадите его эндпоинту статуса:

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json | jq -r '.id'

Использование файла body.json вместо встроенного -d позволяет сохранять длинные промпты и закодированные изображения читаемыми. jq необязателен, но он превращает ответ в одну строку, которую можно сразу вставить в следующий вызов.

Вызов того же эндпоинта на Python

Версия на Python — это тот же запрос, то же тело, просто обёрнутое в функцию для повторного использования. Держите тело идентичным версии на curl — именно в этом смысл показа обоих.

import os
import json
import requests

API_BASE = "https://api.hiapi.ai/v1"
ENDPOINT = f"{API_BASE}/kandinsky-6.0-pro/image-to-video"

def submit_video_job(image_ref: str, prompt: str, duration: int = 5, aspect_ratio: str = "16:9") -> str:
    """Submit a first-frame image-to-video job and return the job id."""
    api_key = os.environ.get("HIAPI_API_KEY")
    if not api_key:
        raise RuntimeError("HIAPI_API_KEY is not set in this environment")

    body = {
        "image": image_ref,
        "prompt": prompt,
        "duration": duration,
        "aspect_ratio": aspect_ratio,
    }

    response = requests.post(
        ENDPOINT,
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json=body,
        timeout=60,
    )

    if response.status_code >= 400:
        raise RuntimeError(f"submit failed: {response.status_code} {response.text}")

    payload = response.json()
    return payload["id"]

if __name__ == "__main__":
    job_id = submit_video_job(
        image_ref="https://your-host.example/first-frame.jpg",
        prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
    )
    print(json.dumps({"job_id": job_id}, indent=2))

Замечания о версии на Python

  • Быстрый отказ при отсутствии ключа. Явная проверка окружения превращает самую частую ошибку в понятную локальную ошибку, а не в удалённый 401.
  • json=body против data=json.dumps(body). Передача json= позволяет requests установить тип содержимого за вас, сохраняя заголовки минимальными. Если вместо этого использовать data=, задайте Content-Type явно.
  • Щедрый тайм-аут. Отправка видео иногда включает передачу больших полезных нагрузок изображений. Слишком короткий тайм-аут порождает ложные сбои.
  • Чтение тела ответа при ошибке. Одновременный выброс кода состояния и тела ответа означает, что сообщение о сбое действительно говорит вам, против чего возражает API.

Если первый кадр — локальный файл, прочитайте его, закодируйте в base64 и замените image_ref внутри submit_video_job этой строкой. Сигнатура функции не меняется — именно поэтому два стиля вызова совместно используют одно определение тела.

Опрос задачи и загрузка видео

Отправленная задача — это ещё не готовое видео. Опрашивайте, пока задача не достигнет терминального состояния, затем скачивайте.

Цикл опроса

import time
import requests

def wait_for_video(job_id: str, interval: float = 10.0, max_wait: float = 600.0) -> str:
    """Poll the job until it finishes; return the output URL."""
    import os
    api_key = os.environ["HIAPI_API_KEY"]
    url = f"https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video/{job_id}"
    headers = {"Authorization": f"Bearer {api_key}"}

    deadline = time.time() + max_wait
    while time.time() < deadline:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        payload = response.json()
        status = payload.get("status")

        if status == "succeeded":
            return payload["output"]
        if status == "failed":
            raise RuntimeError(f"job failed: {payload.get('error', 'unknown error')}")

        time.sleep(interval)

    raise TimeoutError(f"job {job_id} did not finish within {max_wait}s")

Три детали заставляют этот цикл работать хорошо:

  • Отступайте по интервалу, а не полагайтесь на удачу. Фиксированный сон около десяти секунд — разумная отправная точка; не обрушивайте запросы на эндпоинт в тесном цикле.
  • Обрабатывайте каждое терминальное состояние. succeeded даёт вам результат, failed — сообщение об ошибке. Оба должны завершать работу. Цикл, который проверяет только успех, будет крутиться до дедлайна на мёртвой задаче.
  • Ограничивайте время ожидания. max_wait гарантирует, что скрипт завершится, а не будет работать вечно за зависшей задачей.

Загрузка готового видео

Получив URL вывода, потоково записывайте его на диск, а не загружайте весь файл в память:

def download_video(output_url: str, path: str = "result.mp4") -> str:
    with requests.get(output_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(path, "wb") as handle:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    handle.write(chunk)
    return path

Соберите части вместе:

job_id = submit_video_job(
    image_ref="https://your-host.example/first-frame.jpg",
    prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
output_url = wait_for_video(job_id)
saved = download_video(output_url, "kandinsky_result.mp4")
print(f"saved to {saved}")

В производственной среде сохраняйте job_id в момент успешной отправки. Если процесс перезапустится, вы сможете вернуться в цикл опроса с сохранённым идентификатором, не оплачивая новую отправку.

Устранение типичных ошибок запросов и задач

Большинство сбоев относится к трём категориям: ключ, изображение или состояние задачи. Прежде чем менять что-либо ещё, изолируйте категорию.

Ключ отклонён

Симптом: ошибка аутентификации или авторизации до создания какой-либо задачи.

  • Убедитесь, что переменная действительно экспортирована в текущем shell: echo "$HIAPI_API_KEY".
  • Проверьте, не приклеились ли к ключу пробелы или переводы строк; удалите их.
  • Убедитесь, что заголовок написан как Authorization, а значение начинается с Bearer и одного пробела.
  • Если curl работает, а Python нет, выведите os.environ.get("HIAPI_API_KEY") из того же интерпретатора — переменная может существовать в вашем shell, но не в окружении, унаследованном скриптом.

Изображение отклонено

Симптом: ошибка валидации при отправке или немедленный сбой задачи.

  • Неверный или редкий формат. Переэкспортируйте в стандартный JPEG или PNG и повторите попытку. Цветовые профили CMYK и экзотические кодеки — частые виновники.
  • URL недоступен. Откройте URL вашего изображения в окне приватного просмотра; если вы не получаете байты, API тоже их не получит.
  • Повреждённое встроенное кодирование. Если вы кодируете в base64 локально, сначала декодируйте строку один раз и убедитесь, что это валидное изображение, прежде чем отправлять.
  • Несовпадение соотношения сторон. Если видео возвращается обрезанным или с чёрными полосами, выровняйте aspect_ratio по первому кадру, а не боритесь с выводом постфактум.

Задача не завершается или завершается неудачно

Симптом: статус застревает в queued/processing или сообщает failed.

  • Читайте поле error. Неудачные задачи несут сообщение. Оно обычно указывает на проблемное поле или условие. Не угадывайте — логируйте всю полезную нагрузку статуса.
  • Уважайте асинхронный дизайн. Подождать несколько секунд перед проверкой — это нормально. Тесный цикл повторных попыток, который сдаётся через две секунды, — не механизм статуса.
  • Ограничивайте время ожидания. Если задача превышает разумный предел, считайте её неудачной, сохраните идентификатор задачи и отправьте новую, а не опрашивайте вечно.
  • Сравните с заведомо рабочим вызовом. Если пользовательское изображение не работает, запустите точный curl из начала этого руководства с небольшим публичным изображением и коротким промптом. Если он успешен, проблема в ваших входных данных; если тоже нет — в учётных данных или форме запроса.

Ошибки загрузки после успеха

Если задача сообщает succeeded, но загрузка не удаётся, URL вывода мог истечь или быть под контролем доступа. Опрашивайте задачу снова, чтобы получить новое местоположение вывода, а не повторяйте попытку с истёкшим.

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

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

Все статьи →

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

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

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