HiAPI
Блог

Руководство

Как использовать omnihuman-1.5 через HiAPI API: руководство по curl и Python

Полный разбор запроса на генерацию цифрового аватара из аудио в видео, асинхронный опрос статуса и загрузка результата

Nov 3, 2026
深棕与燕麦色宽带交织的扁平编织纹理封面图,点缀克制黄铜色调,几何秩序感强

Возможности и сценарии применения API omnihuman-1.5

omnihuman-1.5 превращает аудиозапись и изображение портрета в говорящее видео цифрового аватара: лицо на изображении приводится в движение, так что губы и голова следуют за поданной речью. В HiAPI эта модель доступна в виде эндпоинта аудио в видео — вы отправляете аудио, опорное изображение и несколько параметров генерации, API возвращает задачу, а затем вы опрашиваете эту задачу, чтобы получить итоговое видео.

В чём преимущество API перед ручными инструментами

Браузерные инструменты подходят для разового монтажа. Когда генерация видео — лишь звено в более крупной системе, правильным выбором становится API:

  • Пакетные конвейеры — генерация множества фрагментов цифрового аватара из скриптов и очередей звуковых дорожек без участия человека.
  • Функции продукта — закадровый голос внутри приложения, локализованные обучающие видео или персонализированные сообщения, где для каждого рендера используются разные аудио и разные портреты.
  • Серверная автоматизация — рабочий процесс создания контента генерирует видео и передаёт его в CMS, хранилище или сервис доставки.

Структура запроса

Каждый вызов omnihuman-1.5 в HiAPI следует одной и той же схеме: один POST создаёт задачу, а последующие запросы проверяют её состояние. Поскольку рендеринг не мгновенный, модель интеграции — отправить → опросить → скачать, а не отправить → получить видео в том же ответе. Остальная часть руководства сначала строит этот процесс на curl, а затем реализует его на Python.

Предварительные требования и ваши учётные данные HiAPI

Перед первым вызовом убедитесь в трёх вещах.

1. Учётная запись и API-ключ

Вам нужна учётная запись HiAPI и API-ключ, созданный в консоли. Относитесь к ключу как к секрету: не помещайте его в систему контроля версий, клиентский код или журналы. При разработке загружайте его из переменных окружения, а в продакшене — из хранилища секретов платформы.

export HIAPI_API_KEY="your-api-key-here"

2. Сетевой доступ и инструменты запросов

С curl подойдёт любая достаточно свежая оболочка. Для Python нужна только библиотека requests — SDK конкретного производителя не требуется, поскольку API — это обычный HTTPS с JSON-телом запроса.

pip install requests

3. Входные данные, необходимые модели

Подготовьте следующее перед написанием запроса:

  • Аудио — голосовая дорожка, управляющая анимацией губ; передаётся в виде URL, доступного API, или ссылки на загруженный файл, в зависимости от того, какие форматы ввода принимает эндпоинт.
  • Изображение портрета — лицо, которое нужно анимировать. Чёткая фронтальная фотография с видимым ртом даёт наиболее предсказуемый результат.
  • Параметры генерации — любые доступные опции разрешения, длительности или качества, которые предоставляет модель. Отправляйте только те поля, которые действительно нужны; при первом тестировании значения по умолчанию обычно разумны.

В каждом запросе ключ передаётся в заголовке Authorization в виде Bearer <your-key>. Если первый же вызов возвращает 401, в первую очередь проверьте этот заголовок.

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

Вызов на отправку — это POST с JSON-телом. Точный путь и имена полей omnihuman-1.5 указаны на странице справки API этой модели; структура ниже показывает форму вызова и поля, которые вы будете заполнять.

curl -X POST "https://api.hiapi.ai/v1/omnihuman-1.5/generate" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_url": "https://your-bucket.example.com/speech.mp3",
    "image_url": "https://your-bucket.example.com/portrait.jpg"
  }'

Разбор по полям

  • Authorization — содержит API-ключ. Без него запрос отклоняется ещё до начала какой-либо работы.
  • Content-Type: application/json — тело запроса является JSON; пропуск этого заголовка — частая причина запутанных ошибок валидации.
  • audio_url — голосовая дорожка. Используйте URL, доступный публично или иным способом доступный API, и предпочитайте стабильное расположение, а не подписанные ссылки, истекающие посреди рендеринга.
  • image_url — портрет для анимации. Действуют те же правила доступности.

Что возвращается

Успешная отправка не возвращает видео, а возвращает объект задачи, содержащий идентификатор (обычно поле id) и состояние, например queued или processing. Сохраните этот идентификатор; это дескриптор, который вы будете использовать при каждой последующей проверке состояния.

{
  "id": "job_abc123",
  "status": "queued"
}

Успешность отправки можно подтвердить, проверив HTTP-код статуса и наличие идентификатора задачи. Если ответ содержит сообщения валидации, они укажут на проблемные поля — обычно это отсутствующие или некорректные URL.

Реализация того же запроса на Python

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

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

def submit_omnihuman_job(audio_url: str, image_url: str, **options) -> str:
    payload = {
        "audio_url": audio_url,
        "image_url": image_url,
    }
    payload.update(options)

    response = requests.post(
        f"{BASE_URL}/omnihuman-1.5/generate",
        headers=HEADERS,
        json=payload,
        timeout=60,
    )
    response.raise_for_status()

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

Почему написано именно так

  • json=payload заставляет requests сериализовать тело запроса и задать тип содержимого, поэтому вы не забудете заголовок JSON.
  • **options сохраняет функцию гибкой: параметры генерации передаются как именованные аргументы, а не требуют правки литерала полезной нагрузки.
  • timeout=60 не позволяет зависшему соединению бесконечно блокировать рабочий процесс. Отправка — быстрый вызов; долгое ожидание должно быть на этапе опроса, а не здесь.
  • raise_for_status() превращает не-2xx ответы в исключения, которые можно перехватить и залогировать, а тело ответа — получить для диагностики.

Сохраните возвращённый идентификатор задачи и передайте его вспомогательной функции опроса — её мы построим в следующем разделе.

Работа с асинхронным жизненным циклом: опрос до завершения

Генерация видео занимает время, поэтому API по своей природе асинхронен. После отправки вы многократно запрашиваете состояние задачи, пока она не достигнет терминального состояния.

Цикл опроса

import time

def wait_for_job(job_id: str, interval: int = 5, max_wait: int = 600) -> dict:
    waited = 0
    while waited < max_wait:
        response = requests.get(
            f"{BASE_URL}/omnihuman-1.5/jobs/{job_id}",
            headers=HEADERS,
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()
        status = job["status"]

        if status == "succeeded" or status == "completed":
            return job
        if status == "failed" or status == "error":
            raise RuntimeError(f"Job {job_id} failed: {job}")

        time.sleep(interval)
        waited += interval

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

Определение момента остановки

Цикл завершается тремя исходами, и ваш код должен обрабатывать каждый:

  • Успех — задача сообщает о состоянии завершения и содержит ссылку на выходное видео. Выходите и переходите к загрузке.
  • Ошибка — задача сообщает о состоянии ошибки. Не повторяйте вслепую; сначала изучите сообщение об ошибке, поскольку сбои обычно вызваны недоступными входными URL или неподдерживаемым аудио.
  • Тайм-аут — достигнут ваш собственный практический предел времени. Считайте это отличным от ошибки случаем: задача может по-прежнему завершиться на стороне сервиса, поэтому осознанно решите, продолжать опрос, продлить временное окно или отказаться.

Культура опроса

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

Загрузка и хранение выходного видео

После того как опрос вернёт завершённую задачу, ответ будет содержать ссылку на видео — обычно это поле URL внутри объекта результата. Получите его и сохраните в собственное хранилище, а не полагайтесь на эту ссылку долгосрочно.

def download_video(job: dict, destination: str) -> None:
    video_url = job.get("output_url") or job.get("result", {}).get("video_url")
    if not video_url:
        raise ValueError(f"No video reference in job payload: {job}")

    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(destination, "wb") as file:
            for chunk in response.iter_content(chunk_size=8192):
                file.write(chunk)

Замечания, экономящие время на отладке

  • Потоковая загрузка. Видео объёмны; запись по частям избегает загрузки всего файла в память, что важно в рабочих процессах с ограниченной памятью.
  • Детерминированные имена файлов. Стройте их из идентификатора задачи плюс временной метки, чтобы запуски были отслеживаемыми, а повторные запуски не конфликтовали.
  • Сначала скачивайте во временный файл, затем перемещайте. Пишите во временный путь и переименовывайте по завершении, чтобы частично загруженный файл никогда не был принят за полный.
  • Считайте возвращённый URL временным. Копируйте байты в собственное хранилище или файловую систему и записывайте идентификатор задачи вместе с объектом хранилища для последующего поиска.
  • Проверяйте перед объявлением успеха. Прежде чем помечать задачу выполненной в базе данных, убедитесь, что скачанный файл не пуст и имеет разумный размер.

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

Большинство проблем интеграции сводится к нескольким категориям. Проверяйте их по порядку.

Ошибки аутентификации и запросов

  • 401 Unauthorized — ключ отсутствует, имеет неверный формат или отправлен не как токен Bearer. Внимательно проверьте заголовок, включая пробел после Bearer.
  • 403 — ключ действителен, но не имеет доступа к этому эндпоинту; убедитесь, что ключ принадлежит нужному вам проекту.
  • Ошибки валидации 422 / 400 — прочитайте сообщение. Частые причины — отсутствие audio_url, отсутствие image_url, недоступный URL или неподдерживаемый аудиоформат.
  • Неожиданный HTML в ответе — вы обратились к неверному хосту или пути. Сверьте базовый URL со справкой API, а не восстанавливайте его по памяти.

Задача завершается ошибкой или не завершается никогда

  • API не может получить доступ к входному URL — ссылка, работающая в браузере, может быть заблокирована частной сетью, истёкшей подписью или защитой от хотлинкинга. Сначала тестируйте на стабильном публичном URL.
  • Несоответствие аудио и изображения — беззвучные, слишком длинные или неподдерживаемые дорожки могут приводить к зависанию или сбою рендеринга. Сначала проверьте конвейер на коротком фрагменте стандартного формата.
  • Слишком частый опрос — плотный цикл может вызвать ограничение частоты и ошибки, похожие на сбой задачи. Замедлитесь и добавьте задержку.
  • Слишком короткое время опроса — отказ от задачи через несколько секунд после постановки в очередь даёт ложные тайм-ауты. Задайте реалистичное максимальное время ожидания и логируйте состояние, наблюдавшееся перед остановкой.
  • Необработанные терминальные состояния — если цикл проверяет только успех, ошибки будут холостым ходом крутиться до тайм-аута. Обрабатывайте состояния ошибки явно.

Привычка минимальной проверки

Когда что-то идёт не так, сократите до минимального теста: короткий аудиофрагмент, небольшой портрет, одна отправка и проверка состояния через несколько секунд. Если это работает, неисправность кроется в вашей полезной нагрузке, логике опроса или хостинге входных данных — а не в самом вызове API.

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

Все статьи →

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

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

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