{
  "aboutHtml": "<p>HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.</p><p>Текстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.</p><h4>От первого кадра к движению</h4><p>Alibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.</p><p>Для этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.</p><p>Принимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.</p><h4>Параметры ролика</h4><p>Длительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.</p><p>Описание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.</p>",
  "aboutText": "HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.\n\nТекстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.\n\n### От первого кадра к движению\n\nAlibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.\n\nДля этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.\n\nПринимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.\n\n### Параметры ролика\n\nДлительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.\n\nОписание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.",
  "editorialOverlay": {
    "copy_fields": null,
    "copy_sha256": null,
    "copy_source": null,
    "html_sha256": "c0de17f4ecb44f9c0614db0cbbdb45872a498d6872f9066f7d8222c2b9df5321",
    "module_sha256": "ee9dc1c50b1e6a8fb7fa062030fcb4646b9aaaeb08be513b723a5a92a7290f06",
    "raw_model_unchanged": true,
    "schema": "ailoot-native-model-editorial-v1"
  },
  "locale": "ru",
  "methods": [
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Закрыть\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-1.1-i2v</code><button type=\"button\" id=\"copy-id\">Скопировать ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Разделы карточки модели\"><button type=\"button\" data-card-jump=\"overview\">Начало</button><button type=\"button\" data-card-jump=\"methods\">Входные данные и методы</button><button type=\"button\" data-card-jump=\"pricing\">Тарифы</button><button type=\"button\" data-card-jump=\"examples\">Примеры</button><button type=\"button\" data-card-jump=\"results\">Результаты</button><button type=\"button\" data-card-jump=\"aliases\">Псевдонимы</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"Методы API\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">Видео</button></div><div class=\"idline\"><label for=\"card-model-id\">ID модели</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\" selected>happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Начало</h3><p class=\"mdesc-full\">Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения.</p><dl class=\"card-io\" data-card-io><div><dt>Допустимые входные данные</dt><dd>Текст · Картинки</dd></div><div><dt>Результаты</dt><dd>Видео</dd></div></dl><details class=\"card-about\"><summary>О модели</summary><p class=\"note-s\" data-model-method-boundary>Описание раскрывает возможности модели. Доступные в Ailoot входные данные, результаты и параметры выбранного метода перечислены ниже.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.</p><p>Текстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.</p><h4>От первого кадра к движению</h4><p>Alibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.</p><p>Для этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.</p><p>Принимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.</p><h4>Параметры ролика</h4><p>Длительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.</p><p>Описание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Доступно в Ailoot · входные данные и методы</h3><details class=\"card-method\" open><summary><b>Ailoot · Видео</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Входные данные</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Результат</dt><dd><code>video</code></dd></div><div><dt>Выходной формат</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Поле</th><th>Тип</th><th>Требование</th><th>Значения и ограничения</th><th>По умолчанию</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>happyhorse-1.1-i2v</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимальная длина: 1</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>integer</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум: 3</div><div>Максимум: 15</div><div>Единица: секунды</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Не поддерживается</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум элементов: 1</div><div>Максимум элементов: 1</div><div>Максимум декодированных байтов: 20 971 520</div><div>Типы MIME: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Сочетания входных материалов</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Обязательно: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Параметры и жизненный цикл метода</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Параметр</th><th>Контракт</th></tr></thead><tbody><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>content_type</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>application/json</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>required</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>model, image_urls</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>material_types</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>text, image</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>optional</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>duration, resolution, ratio, prompt</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>duration_integer_range</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>3, 15</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>default_duration</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>5</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>resolution</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>480P, 720P, 1080P</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>default_resolution</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>720P</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>ratio</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span></td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>ratio_must_omit</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>true</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>image_urls</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>{&quot;min_count&quot;:1,&quot;max_count&quot;:1,&quot;schemes&quot;:[&quot;https&quot;,&quot;растровые данные в base64&quot;],&quot;max_data_image_bytes&quot;:20971520}</td></tr></tbody></table></div><p>Жизненный цикл: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Тарифы</h3><h4>Ставки методов Ailoot</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Видео</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Выход</dt><dd>0,18 $ <em>за секунду в 1080p</em></dd></div><div><dt>Выход</dt><dd>0,07 $ <em>за секунду в 480p</em></dd></div><div><dt>Выход</dt><dd>0,14 $ <em>за секунду в 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot резервирует расчётную сумму перед запросом. После получения результата списывает итоговую плату по измеренному расходу. Для окончательного списания за потоковый ответ используется итоговая запись расхода. <a href=\"/docs/ru/billing/reserve/\">Как работают резервирование и расчёт →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Примеры запросов</h3><h4>Ailoot · Видео</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-1-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-1-panel-0\" aria-selected=\"true\" tabindex=\"0\">Изображение-референс</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-1-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-1-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-1.1-i2v&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Получить и сохранить результаты</h3><h4>Ailoot · Видео</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Проверить статус задачи</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-2-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-2-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET статус</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-2-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-2-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Сохраните все готовые материалы</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-3-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-3-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET все готовые материалы</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-3-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-3-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Чтение другого содержимого</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-4-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-4-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET содержимое</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-4-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-4-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Сохраняйте все готовые результаты</h5><p class=\"note-s\">Сохраните каждое готовое видео или полученный файл; загрузите содержимое по каждому фактически полученному URL материала.</p><p class=\"note-s\">Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>Если нужно проверить исходный ответ</h5><p class=\"note-s\">Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.</p></div><details class=\"card-about\" data-output-fields><summary>Поля ответа</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Поле</th><th>Тип</th></tr></thead><tbody><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>object</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Ошибки и дальнейшие шаги</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Ответ</th><th>Условие</th><th>Следующий шаг</th></tr></thead><tbody><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Неверные обязательные поля, представление материалов или значение параметра</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Исправьте указанные поля перед новым запросом на создание.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Содержимое исходного результата пока недоступно</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Проверяйте исходный возвращённый ID и соблюдайте Retry-After.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span><code>server_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Возвращённый ответ указывает, что операция или результат требуют проверки</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Псевдонимы</h3><h4>Псевдонимы моделей</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Псевдонимы путей метода</h4><p class=\"note-s\">Используйте пути методов, указанные выше.</p><h4>Связанные ID для вызова</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-1.1-i2v",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-1.1-i2v",
      "ordinal": 0,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "first_frame_to_video"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-1.1-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "content_type": "application/json",
            "default_duration": 5,
            "default_resolution": "720P",
            "duration_integer_range": [
              3,
              15
            ],
            "image_urls": {
              "max_count": 1,
              "max_data_image_bytes": 20971520,
              "min_count": 1,
              "schemes": [
                "https",
                "растровые данные в base64"
              ]
            },
            "material_types": [
              "text",
              "image"
            ],
            "optional": [
              "duration",
              "resolution",
              "ratio",
              "prompt"
            ],
            "ratio": [],
            "ratio_must_omit": true,
            "required": [
              "model",
              "image_urls"
            ],
            "resolution": [
              "480P",
              "720P",
              "1080P"
            ]
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "first_frame_to_video"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-1.1-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    },
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Закрыть\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-i2v</code><button type=\"button\" id=\"copy-id\">Скопировать ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Разделы карточки модели\"><button type=\"button\" data-card-jump=\"overview\">Начало</button><button type=\"button\" data-card-jump=\"methods\">Входные данные и методы</button><button type=\"button\" data-card-jump=\"pricing\">Тарифы</button><button type=\"button\" data-card-jump=\"examples\">Примеры</button><button type=\"button\" data-card-jump=\"results\">Результаты</button><button type=\"button\" data-card-jump=\"aliases\">Псевдонимы</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"Методы API\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">Видео</button></div><div class=\"idline\"><label for=\"card-model-id\">ID модели</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\" selected>happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Начало</h3><p class=\"mdesc-full\">Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения.</p><dl class=\"card-io\" data-card-io><div><dt>Допустимые входные данные</dt><dd>Текст · Картинки</dd></div><div><dt>Результаты</dt><dd>Видео</dd></div></dl><details class=\"card-about\"><summary>О модели</summary><p class=\"note-s\" data-model-method-boundary>Описание раскрывает возможности модели. Доступные в Ailoot входные данные, результаты и параметры выбранного метода перечислены ниже.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.</p><p>Текстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.</p><h4>От первого кадра к движению</h4><p>Alibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.</p><p>Для этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.</p><p>Принимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.</p><h4>Параметры ролика</h4><p>Длительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.</p><p>Описание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Доступно в Ailoot · входные данные и методы</h3><details class=\"card-method\" open><summary><b>Ailoot · Видео</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Входные данные</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Результат</dt><dd><code>video</code></dd></div><div><dt>Выходной формат</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Поле</th><th>Тип</th><th>Требование</th><th>Значения и ограничения</th><th>По умолчанию</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>happyhorse-i2v</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимальная длина: 1</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>integer</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум: 3</div><div>Максимум: 15</div><div>Единица: секунды</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Не поддерживается</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум элементов: 1</div><div>Максимум элементов: 1</div><div>Максимум декодированных байтов: 20 971 520</div><div>Типы MIME: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Сочетания входных материалов</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Обязательно: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Параметры и жизненный цикл метода</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Параметр</th><th>Контракт</th></tr></thead><tbody><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>material_types</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>text, image</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>required</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>null</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>optional_controls</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>null</td></tr></tbody></table></div><p>Жизненный цикл: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Тарифы</h3><h4>Ставки методов Ailoot</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Видео</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Выход</dt><dd>0,18 $ <em>за секунду в 1080p</em></dd></div><div><dt>Выход</dt><dd>0,07 $ <em>за секунду в 480p</em></dd></div><div><dt>Выход</dt><dd>0,14 $ <em>за секунду в 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot резервирует расчётную сумму перед запросом. После получения результата списывает итоговую плату по измеренному расходу. Для окончательного списания за потоковый ответ используется итоговая запись расхода. <a href=\"/docs/ru/billing/reserve/\">Как работают резервирование и расчёт →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Примеры запросов</h3><h4>Ailoot · Видео</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-5-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-5-panel-0\" aria-selected=\"true\" tabindex=\"0\">Изображение-референс</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-5-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-5-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-i2v&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Получить и сохранить результаты</h3><h4>Ailoot · Видео</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Проверить статус задачи</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-6-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-6-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET статус</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-6-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-6-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Сохраните все готовые материалы</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-7-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-7-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET все готовые материалы</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-7-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-7-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Чтение другого содержимого</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-8-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-8-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET содержимое</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-8-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-8-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Сохраняйте все готовые результаты</h5><p class=\"note-s\">Сохраните каждое готовое видео или полученный файл; загрузите содержимое по каждому фактически полученному URL материала.</p><p class=\"note-s\">Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>Если нужно проверить исходный ответ</h5><p class=\"note-s\">Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.</p></div><details class=\"card-about\" data-output-fields><summary>Поля ответа</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Поле</th><th>Тип</th></tr></thead><tbody><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>object</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Ошибки и дальнейшие шаги</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Ответ</th><th>Условие</th><th>Следующий шаг</th></tr></thead><tbody><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Неверные обязательные поля, представление материалов или значение параметра</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Исправьте указанные поля перед новым запросом на создание.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Содержимое исходного результата пока недоступно</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Проверяйте исходный возвращённый ID и соблюдайте Retry-After.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span><code>server_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Возвращённый ответ указывает, что операция или результат требуют проверки</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Псевдонимы</h3><h4>Псевдонимы моделей</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Псевдонимы путей метода</h4><p class=\"note-s\">Используйте пути методов, указанные выше.</p><h4>Связанные ID для вызова</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-i2v",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-i2v",
      "ordinal": 1,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    },
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">Al</span><h2 id=\"sheet-title\">happyhorse-1.1-i2v</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Закрыть\">×</button></div><div class=\"idline\"><span>Alibaba /</span><code>happyhorse-i2v-latest</code><button type=\"button\" id=\"copy-id\">Скопировать ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Разделы карточки модели\"><button type=\"button\" data-card-jump=\"overview\">Начало</button><button type=\"button\" data-card-jump=\"methods\">Входные данные и методы</button><button type=\"button\" data-card-jump=\"pricing\">Тарифы</button><button type=\"button\" data-card-jump=\"examples\">Примеры</button><button type=\"button\" data-card-jump=\"results\">Результаты</button><button type=\"button\" data-card-jump=\"aliases\">Псевдонимы</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"Методы API\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\">Видео</button></div><div class=\"idline\"><label for=\"card-model-id\">ID модели</label><select class=\"sel\" id=\"card-model-id\" style=\"min-width:0;max-width:100%\"><option value=\"Core|videos|/v1/videos/generations|happyhorse-1.1-i2v\">happyhorse-1.1-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v\">happyhorse-i2v</option><option value=\"Core|videos|/v1/videos/generations|happyhorse-i2v-latest\" selected>happyhorse-i2v-latest</option></select></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Начало</h3><p class=\"mdesc-full\">Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения.</p><dl class=\"card-io\" data-card-io><div><dt>Допустимые входные данные</dt><dd>Текст · Картинки</dd></div><div><dt>Результаты</dt><dd>Видео</dd></div></dl><details class=\"card-about\"><summary>О модели</summary><p class=\"note-s\" data-model-method-boundary>Описание раскрывает возможности модели. Доступные в Ailoot входные данные, результаты и параметры выбранного метода перечислены ниже.</p><div class=\"mabout\" id=\"m-about\"><p>HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.</p><p>Текстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.</p><h4>От первого кадра к движению</h4><p>Alibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.</p><p>Для этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.</p><p>Принимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.</p><h4>Параметры ролика</h4><p>Длительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.</p><p>Описание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Доступно в Ailoot · входные данные и методы</h3><details class=\"card-method\" open><summary><b>Ailoot · Видео</b> <code>POST /v1/videos/generations</code></summary><dl class=\"method-capabilities\"><div><dt>Входные данные</dt><dd><code>text</code>, <code>image</code></dd></div><div><dt>Результат</dt><dd><code>video</code></dd></div><div><dt>Выходной формат</dt><dd>mp4</dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Поле</th><th>Тип</th><th>Требование</th><th>Значения и ограничения</th><th>По умолчанию</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>happyhorse-i2v-latest</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимальная длина: 1</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>integer</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум: 3</div><div>Максимум: 15</div><div>Единица: секунды</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>5</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Необязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>480P, 720P, 1080P</div></td><td data-cell-label=\"По умолчанию\" data-default=\"known\"><span class=\"card-cell-label\">По умолчанию</span>720P</td></tr><tr data-parameter-availability=\"unsupported\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">ratio</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>string</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Не поддерживается</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">image_urls</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span><code>https_url|data_image_url[]</code></td><td data-cell-label=\"Требование\"><span class=\"card-cell-label\">Требование</span>Обязательно</td><td data-cell-label=\"Значения и ограничения\"><span class=\"card-cell-label\">Значения и ограничения</span><div>Минимум элементов: 1</div><div>Максимум элементов: 1</div><div>Максимум декодированных байтов: 20 971 520</div><div>Типы MIME: image/jpeg, image/png, image/webp</div></td><td data-cell-label=\"По умолчанию\" data-default=\"unspecified\"><span class=\"card-cell-label\">По умолчанию</span>—</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Сочетания входных материалов</summary><p class=\"note-s\"><b>first_frame_to_video</b> · Обязательно: image_urls</p></details><details class=\"note-s\" data-method-contract><summary>Параметры и жизненный цикл метода</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Параметр</th><th>Контракт</th></tr></thead><tbody><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>material_types</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>text, image</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>required</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>null</td></tr><tr><th data-cell-label=\"Параметр\" scope=\"row\"><span class=\"card-cell-label\">Параметр</span><code>optional_controls</code></th><td data-cell-label=\"Контракт\"><span class=\"card-cell-label\">Контракт</span>null</td></tr></tbody></table></div><p>Жизненный цикл: <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Тарифы</h3><h4>Ставки методов Ailoot</h4><section class=\"meth\" data-route=\"Core\"><header><b><span class=\"alias\">Ailoot</span> Видео</b><code>POST /v1/videos/generations</code></header><dl><div><dt>Выход</dt><dd>0,18 $ <em>за секунду в 1080p</em></dd></div><div><dt>Выход</dt><dd>0,07 $ <em>за секунду в 480p</em></dd></div><div><dt>Выход</dt><dd>0,14 $ <em>за секунду в 720p</em></dd></div></dl></section><p class=\"note-s\">Ailoot резервирует расчётную сумму перед запросом. После получения результата списывает итоговую плату по измеренному расходу. Для окончательного списания за потоковый ответ используется итоговая запись расхода. <a href=\"/docs/ru/billing/reserve/\">Как работают резервирование и расчёт →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Примеры запросов</h3><h4>Ailoot · Видео</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-9-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-9-panel-0\" aria-selected=\"true\" tabindex=\"0\">Изображение-референс</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-9-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-9-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}&quot;\nexport AILOOT_IMAGE_URL\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\np=json.loads(&#39;{&quot;model&quot;: &quot;happyhorse-i2v-latest&quot;, &quot;prompt&quot;: &quot;The subject walks slowly toward the camera.&quot;, &quot;duration&quot;: 5, &quot;resolution&quot;: &quot;720P&quot;}&#39;)\nfrom urllib.parse import urlsplit\nu=os.environ[&quot;AILOOT_IMAGE_URL&quot;]\nz=urlsplit(u)\nif z.scheme!=&quot;https&quot; or not z.netloc or z.username or z.password:raise SystemExit(&quot;Set the actual HTTPS image URL&quot;)\np[&quot;image_urls&quot;]=[u]\nPath(&quot;request.json&quot;).write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - &lt;&lt;&#39;PY_RESULT&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;result.json&quot;).read_text())\nprint(json.dumps(r))\nPY_RESULT\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Получить и сохранить результаты</h3><h4>Ailoot · Видео</h4><p class=\"note-s\">mp4</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><h5>Проверить статус задачи</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-10-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-10-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET статус</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-10-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-10-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o status.json\npython3 - &lt;&lt;&#39;PY_STATUS&#39;\nimport json\nfrom pathlib import Path\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nprint(json.dumps(r))\nif r.get(&quot;status&quot;)==&quot;completed&quot;:\n    for x in r.get(&quot;data&quot;,[]):print(x)\nPY_STATUS\n</code></pre></div></div></div><h5>Сохраните все готовые материалы</h5><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-11-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-11-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET все готовые материалы</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-11-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-11-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}&quot;\nexport AILOOT_STATUS_FILE\npython3 - &lt;&lt;&#39;PY_REQUEST&#39;\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[&quot;AILOOT_STATUS_FILE&quot;])\nif not f.is_file():raise SystemExit(&quot;Choose the actual completed status file&quot;)\nr=json.loads(f.read_text())\nif r.get(&quot;status&quot;)!=&quot;completed&quot; or not isinstance(r.get(&quot;data&quot;),list) or not r[&quot;data&quot;]:raise SystemExit(&quot;Wait for a completed status with asset paths&quot;)\nurls=[]\nfor x in r[&quot;data&quot;]:\n    if not isinstance(x,str) or &quot;\\n&quot; in x or &quot;\\r&quot; in x:raise SystemExit(&quot;Invalid asset path&quot;)\n    u=urljoin(&quot;https://api.ailoot.ai&quot;,x)\n    z=urlsplit(u)\n    if z.scheme!=&quot;https&quot; or z.netloc!=&quot;api.ailoot.ai&quot; or z.username or z.password:raise SystemExit(&quot;Use the actual Ailoot asset paths from status&quot;)\n    urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; \\\n    -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o &quot;video-${index}.mp4&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div><details class=\"card-about\"><summary>Чтение другого содержимого</summary><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Варианты кода\"><button class=\"cg-tab\" id=\"model-code-12-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-12-panel-0\" aria-selected=\"true\" tabindex=\"0\">GET содержимое</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Скопировать код\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-12-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-12-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\n: &quot;${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}&quot;\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c &#39;import os,urllib.parse;print(urllib.parse.quote(os.environ[&quot;AILOOT_OPERATION_ID&quot;],safe=&quot;&quot;))&#39;)\ncurl --fail-with-body --silent --show-error &quot;https://api.ailoot.ai/v1/videos/generations/$operation_id/content&quot; \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -o video.mp4\n</code></pre></div></div></div></details><div class=\"card-result-process\" data-all-results><h5>Сохраняйте все готовые результаты</h5><p class=\"note-s\">Сохраните каждое готовое видео или полученный файл; загрузите содержимое по каждому фактически полученному URL материала.</p><p class=\"note-s\">Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>Если нужно проверить исходный ответ</h5><p class=\"note-s\">Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.</p></div><details class=\"card-about\" data-output-fields><summary>Поля ответа</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Поле</th><th>Тип</th></tr></thead><tbody><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">object</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">status</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>string</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">content_url</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">data[]</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>signed URL</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">usage</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>object</td></tr><tr><th data-cell-label=\"Поле\" scope=\"row\"><span class=\"card-cell-label\">Поле</span><code class=\"card-field-name\">result_pending_check</code></th><td data-cell-label=\"Тип\" data-field-type><span class=\"card-cell-label\">Тип</span>boolean</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Ошибки и дальнейшие шаги</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Ответ</th><th>Условие</th><th>Следующий шаг</th></tr></thead><tbody><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Неверные обязательные поля, представление материалов или значение параметра</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Исправьте указанные поля перед новым запросом на создание.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span>409 · <code>video_not_ready</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Содержимое исходного результата пока недоступно</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Проверяйте исходный возвращённый ID и соблюдайте Retry-After.</td></tr><tr><th data-cell-label=\"Ответ\" scope=\"row\"><span class=\"card-cell-label\">Ответ</span><code>server_error</code></th><td data-cell-label=\"Условие\"><span class=\"card-cell-label\">Условие</span>Возвращённый ответ указывает, что операция или результат требуют проверки</td><td data-cell-label=\"Следующий шаг\"><span class=\"card-cell-label\">Следующий шаг</span>Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.</td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Псевдонимы</h3><h4>Псевдонимы моделей</h4><p class=\"note-s\"><span data-model-alias-route=\"Core\"><b>Ailoot</b> <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></span></p><h4>Псевдонимы путей метода</h4><p class=\"note-s\">Используйте пути методов, указанные выше.</p><h4>Связанные ID для вызова</h4><p class=\"note-s\"><a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-1.1-i2v&amp;fmt=videos\"><code>happyhorse-1.1-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v&amp;fmt=videos\"><code>happyhorse-i2v</code></a>, <a href=\"#m=happyhorse-1.1-i2v&amp;route=Core&amp;caller=happyhorse-i2v-latest&amp;fmt=videos\"><code>happyhorse-i2v-latest</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "happyhorse-i2v-latest",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos/generations",
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core"
      },
      "method_key": "Core|videos|/v1/videos/generations|happyhorse-i2v-latest",
      "ordinal": 2,
      "rawMethod": {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v-latest"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v-latest\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    }
  ],
  "model_id": "happyhorse-1.1-i2v",
  "nativeProvenance": {
    "input_facts_canonical_sha256": "f9276f978d55cc3ca10cdc9a4407e0a1b7091527259bb6915e0b96118762ed2b",
    "input_html_sha256": "708d9e2ff2ca072c3c893349bd62fd93aea5515006af4ebc031dac5bf3a3055d",
    "private_audit_sha256": "a29fed82b42ae69d745f5e83913daec8dcd52e50ecebfdcee09e2739c923f169",
    "role": "historical-normalized-input-audit-hashes",
    "schema": "ailoot-native-model-provenance-v2"
  },
  "page": {
    "canonical": "https://ailoot.ai/models/ru/happyhorse-1-1-i2v/",
    "description": "Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения.",
    "locale": "ru",
    "md_url": "https://ailoot.ai/models/ru/happyhorse-1-1-i2v/index.md",
    "title": "happyhorse-1.1-i2v — Ailoot",
    "url": "https://ailoot.ai/models/ru/happyhorse-1-1-i2v/"
  },
  "rawModel": {
    "about": "HappyHorse-1.1-I2V — модель Alibaba, которая начинает видеосцену с готового изображения. Картинка становится первым кадром, а текст может определить последующее действие: движение героя, изменения в сцене и направление камеры. Это подходит для оживления иллюстрации, предметной фотографии или заранее подготовленного визуального концепта.\n\nТекстовое описание необязательно. Если его нет, модель сама выводит возможное движение из содержимого начальной картинки. При явном задании исходное изображение определяет композицию и внешность объектов, а слова направляют развитие сцены во времени.\n\n### От первого кадра к движению\n\nAlibaba выделяет сохранение внешности персонажа, визуальную согласованность, плавность движения и сочетание изображения со звуком. В числе заявленных направлений также устойчивость надписей и фактур. Эти свойства относятся к замыслу модели и не означают буквального сохранения каждого пикселя во всех сгенерированных кадрах.\n\nДля этого режима используется одно начальное изображение. Оно задаёт исходную сцену, а не набор независимых образцов для новой композиции. Возможность назначить отдельный завершающий кадр для этой конкретной версии не заявлена.\n\nПринимаются JPEG, JPG, PNG и WEBP. Каждая сторона входного изображения должна быть не меньше 300 пикселей; допустимое соотношение сторон — от 1:2,5 до 2,5:1, размер файла — до 20 МБ. Соотношение сторон готового видео следует первому кадру.\n\n### Параметры ролика\n\nДлительность выбирается целым числом от 3 до 15 секунд. Доступны уровни разрешения 480P, 720P и 1080P; выходной формат — MP4, частота — 24 кадра в секунду. Поддерживается создание звукового сопровождения вместе с видеорядом.\n\nОписание допускает любой язык и содержит до 5000 некитайских либо 2500 китайских символов. Если предел превышен, лишняя часть отбрасывается, поэтому важные действия и особенности движения стоит формулировать в пределах задания. Одинаковое начальное зерно случайности может дать похожие ролики, но не гарантирует их покадровое совпадение.",
    "alias_of": null,
    "aliases": [
      "happyhorse-i2v",
      "happyhorse-i2v-latest"
    ],
    "author": "Alibaba",
    "ctx": null,
    "formats": [
      "videos"
    ],
    "id": "happyhorse-1.1-i2v",
    "input": [
      "text",
      "image"
    ],
    "kind": "video",
    "max_out": null,
    "methods": [
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "first_frame_to_video"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-1.1-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "content_type": "application/json",
            "default_duration": 5,
            "default_resolution": "720P",
            "duration_integer_range": [
              3,
              15
            ],
            "image_urls": {
              "max_count": 1,
              "max_data_image_bytes": 20971520,
              "min_count": 1,
              "schemes": [
                "https",
                "растровые данные в base64"
              ]
            },
            "material_types": [
              "text",
              "image"
            ],
            "optional": [
              "duration",
              "resolution",
              "ratio",
              "prompt"
            ],
            "ratio": [],
            "ratio_must_omit": true,
            "required": [
              "model",
              "image_urls"
            ],
            "resolution": [
              "480P",
              "720P",
              "1080P"
            ]
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "first_frame_to_video"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-1.1-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      },
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      },
      {
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "cache_write_5m": null,
        "conditional_meter": null,
        "contract": {
          "data": {
            "all_results": "Preserve every returned data item/output index. content_url is first only; fetch every actual content path/asset. GETcontentwithoutindex isnotalloutputs.",
            "errors": [
              {
                "code": null,
                "condition": "Неверные обязательные поля, представление материалов или значение параметра",
                "http_status": 400,
                "recovery": "Исправьте указанные поля перед новым запросом на создание.",
                "type": "invalid_request_error"
              },
              {
                "code": null,
                "condition": "Содержимое исходного результата пока недоступно",
                "http_status": 409,
                "recovery": "Проверяйте исходный возвращённый ID и соблюдайте Retry-After.",
                "type": "video_not_ready"
              },
              {
                "code": null,
                "condition": "Возвращённый ответ указывает, что операция или результат требуют проверки",
                "http_status": null,
                "recovery": "Сохраните исходный возвращённый ID операции или задачи, заголовки запроса и ответ; продолжайте поддерживаемые операции чтения исходной операции. Не отправляйте запрос создания повторно.",
                "type": "server_error"
              }
            ],
            "hints": [],
            "ignored_fields": [],
            "lifecycle": {
              "all_results": "Follow everyactualreturnedoutputandownedasset; no result is discardedbecauseindex0orcontent_urlalreadyexists.",
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content"
                }
              ],
              "create": {
                "http": "POST",
                "path": "/v1/videos/generations"
              },
              "id_source": "Actualreturnedpublicid; opaque URLencodeit forGET",
              "mode": "submit_once_poll_original",
              "multioutputs": "retain every completed data output; index0 alone is not all outputs",
              "operation_id_is_not_task_id": true,
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 202,
              "unknown": "Проверяйте существующую исходную задачу; никогда не повторяйте отправку с неизвестным исходом.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              {
                "mode": "first_frame_to_video",
                "required": [
                  "image_urls"
                ]
              }
            ],
            "media_library": {
              "asset": {
                "fields": [
                  {
                    "description": null,
                    "name": "asset_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "task_id",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "output_key",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "family",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "model",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "method",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "status",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "content_type",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "sha256",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "size_bytes",
                    "type": "integer"
                  },
                  {
                    "description": null,
                    "name": "content_url",
                    "type": "string"
                  }
                ],
                "http": "GET",
                "id_source": "actual returned asset_id",
                "path": "/v1/media/assets/{asset_id}"
              },
              "content": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}/content",
                "range_header_supported": true,
                "url_source": "Use exact returned signed content_url including its token; do not construct a token."
              },
              "expired_link": {
                "code": "link_expired",
                "http_status": 404,
                "recovery": "Read the asset again to obtain its refreshed signed content_url, then fetch that URL. Do not regenerate."
              },
              "list": {
                "all_pages": "Follow every returned next_cursor, then select records by their actual task_id/output_key.",
                "http": "GET",
                "output_fields": [
                  {
                    "description": null,
                    "name": "object",
                    "type": "string"
                  },
                  {
                    "description": null,
                    "name": "data",
                    "type": "asset[]"
                  },
                  {
                    "description": null,
                    "name": "next_cursor",
                    "type": "string|null"
                  }
                ],
                "parameters": [
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "family",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": null,
                    "default_known": false,
                    "enum": null,
                    "enum_known": false,
                    "name": "cursor",
                    "required": false,
                    "type": "string"
                  },
                  {
                    "availability": "source_interface",
                    "default": 20,
                    "default_known": true,
                    "enum": null,
                    "enum_known": false,
                    "maximum": 100,
                    "minimum": 1,
                    "name": "limit",
                    "required": false,
                    "type": "integer"
                  }
                ],
                "path": "/v1/media/assets"
              },
              "revoke": {
                "http": "DELETE",
                "meaning": "Revokes/deletes the existing owned file; this is not generation cancellation.",
                "path": "/v1/media/assets/{asset_id}",
                "pending_status": "revoking",
                "success_statuses": [
                  202,
                  204
                ]
              },
              "task": {
                "http": "GET",
                "id_source": "actual returned task_id or media library record; operation_id is not task_id",
                "path": "/v1/media/tasks/{task_id}"
              }
            },
            "operation_modes": [
              "videos"
            ],
            "outputs": {
              "all_results": "Сохраните каждый возвращённый элемент data и индекс результата. content_url относится только к первому результату; получите данные по каждому фактическому пути содержимого или ресурсу. GET содержимого без index не возвращает все результаты.",
              "content_selection": "Oneownedvideo; use actualreturnedcontent_url/data[] ororiginalcontentread. No indexedselection field is promised by thisCorehandler.",
              "create_status": 202,
              "family": "video",
              "fields": [
                {
                  "description": null,
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "object",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "model",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "status",
                  "type": "string"
                },
                {
                  "description": null,
                  "name": "content_url",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "data[]",
                  "type": "signed URL"
                },
                {
                  "description": null,
                  "name": "usage",
                  "type": "object"
                },
                {
                  "description": null,
                  "name": "result_pending_check",
                  "type": "boolean"
                }
              ],
              "format": "mp4"
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "happyhorse-i2v-latest"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "min_length": 1,
                "name": "prompt",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": 5,
                "default_known": true,
                "enum": null,
                "enum_known": false,
                "maximum": 15,
                "minimum": 3,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "секунды"
              },
              {
                "availability": "source_interface",
                "default": "720P",
                "default_known": true,
                "enum": [
                  "480P",
                  "720P",
                  "1080P"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "unsupported",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum_decoded_bytes": 20971520,
                "maximum_items": 1,
                "mime_types": [
                  "image/jpeg",
                  "image/png",
                  "image/webp"
                ],
                "minimum_items": 1,
                "name": "image_urls",
                "required": true,
                "type": "https_url|data_image_url[]"
              }
            ],
            "profile_binding": "Exact existing Ailoot model and method; interface constraints below do not assert provider qualification.",
            "unsupported": [
              "ratiofield"
            ]
          },
          "hints": [
            "Структуры методов и ID указаны точно; возможности поставщика рассматриваются отдельно от допуска."
          ],
          "input": {
            "material_types": [
              "text",
              "image"
            ],
            "optional_controls": null,
            "required": null
          },
          "lifecycle": {
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content"
              }
            ],
            "id_source": "only actual ID/path from creation/status",
            "mode": "submit_once_poll_original",
            "multioutputs": "retain every completed data output; index0 alone is not all outputs",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 202,
            "unknown": "Read existing original job; never resubmit unknown send."
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos/generations"
          },
          "operation_modes": [
            "videos"
          ],
          "output": {
            "family": [
              "video"
            ],
            "format": null,
            "multioutputs": "retain every actual response output"
          }
        },
        "ctx": null,
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_IMAGE_URL:?Set the HTTPS URL of your actual first-frame image}\"\nexport AILOOT_IMAGE_URL\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\np=json.loads('{\"model\": \"happyhorse-i2v-latest\", \"prompt\": \"The subject walks slowly toward the camera.\", \"duration\": 5, \"resolution\": \"720P\"}')\nfrom urllib.parse import urlsplit\nu=os.environ[\"AILOOT_IMAGE_URL\"]\nz=urlsplit(u)\nif z.scheme!=\"https\" or not z.netloc or z.username or z.password:raise SystemExit(\"Set the actual HTTPS image URL\")\np[\"image_urls\"]=[u]\nPath(\"request.json\").write_text(json.dumps(p,ensure_ascii=False))\nPY_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos/generations \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\npython3 - <<'PY_RESULT'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"result.json\").read_text())\nprint(json.dumps(r))\nPY_RESULT\n",
            "label": "Use your actual image reference",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o status.json\npython3 - <<'PY_STATUS'\nimport json\nfrom pathlib import Path\nr=json.loads(Path(\"status.json\").read_text())\nprint(json.dumps(r))\nif r.get(\"status\")==\"completed\":\n    for x in r.get(\"data\",[]):print(x)\nPY_STATUS\n",
            "label": "GET status",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_OPERATION_ID:?Set the actual Ailoot operation ID returned by creation}\"\nexport AILOOT_OPERATION_ID\noperation_id=$(python3 -c 'import os,urllib.parse;print(urllib.parse.quote(os.environ[\"AILOOT_OPERATION_ID\"],safe=\"\"))')\ncurl --fail-with-body --silent --show-error \"https://api.ailoot.ai/v1/videos/generations/$operation_id/content\" \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -o video.mp4\n",
            "label": "GET content",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\n: \"${AILOOT_STATUS_FILE:?Set the actual completed status JSON file}\"\nexport AILOOT_STATUS_FILE\npython3 - <<'PY_REQUEST'\nimport json,os\nfrom pathlib import Path\nfrom urllib.parse import urlsplit,urljoin\nf=Path(os.environ[\"AILOOT_STATUS_FILE\"])\nif not f.is_file():raise SystemExit(\"Choose the actual completed status file\")\nr=json.loads(f.read_text())\nif r.get(\"status\")!=\"completed\" or not isinstance(r.get(\"data\"),list) or not r[\"data\"]:raise SystemExit(\"Wait for a completed status with asset paths\")\nurls=[]\nfor x in r[\"data\"]:\n    if not isinstance(x,str) or \"\\n\" in x or \"\\r\" in x:raise SystemExit(\"Invalid asset path\")\n    u=urljoin(\"https://api.ailoot.ai\",x)\n    z=urlsplit(u)\n    if z.scheme!=\"https\" or z.netloc!=\"api.ailoot.ai\" or z.username or z.password:raise SystemExit(\"Use the actual Ailoot asset paths from status\")\n    urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_REQUEST\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" \\\n    -H \"Authorization: Bearer $AILOOT_API_KEY\" -o \"video-${index}.mp4\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "GET all completed assets",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "http": "POST",
        "img_in": null,
        "img_out": null,
        "in": null,
        "input": [
          "text",
          "image"
        ],
        "label": "Видео",
        "max_out": null,
        "max_tool_calls": null,
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos/generations",
        "pricing_profiles": [
          {
            "dimensions": {},
            "label": "Core",
            "units": [
              {
                "amount": 0.18,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_1080p_second",
                "label": "per second at 1080p",
                "side": "out"
              },
              {
                "amount": 0.07,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_480p_second",
                "label": "per second at 480p",
                "side": "out"
              },
              {
                "amount": 0.14,
                "amount_unit": "usd_per_display_unit",
                "key": "video_output_720p_second",
                "label": "per second at 720p",
                "side": "out"
              }
            ]
          }
        ],
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core",
        "status_reads": [
          "GET /v1/videos/generations/{id}",
          "GET /v1/videos/generations/{id}/content"
        ],
        "tiers": [],
        "tool_prices": null,
        "unit": "conditional",
        "units": [
          {
            "key": "video_output_1080p_second",
            "label": "per second at 1080p",
            "side": "out",
            "usd": 0.18
          },
          {
            "key": "video_output_480p_second",
            "label": "per second at 480p",
            "side": "out",
            "usd": 0.07
          },
          {
            "key": "video_output_720p_second",
            "label": "per second at 720p",
            "side": "out",
            "usd": 0.14
          }
        ]
      }
    ],
    "model_aliases": [
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-1.1-i2v",
        "route_label": "Core"
      },
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-i2v",
        "route_label": "Core"
      },
      {
        "canonical_model_id": "happyhorse-1.1-i2v",
        "request_model_id": "happyhorse-i2v-latest",
        "route_label": "Core"
      }
    ],
    "name": "happyhorse-1.1-i2v",
    "price": {
      "in": null,
      "in_label": null,
      "out": 0.07,
      "out_label": "per second at 480p",
      "sort_in": null,
      "sort_out": null,
      "varies": false
    },
    "short": "Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения."
  },
  "renderer_schema": {
    "method_order": "Original DTO methods order; every exact route/format/path/caller survives.",
    "prices": "Original public DTO fields and original native display HTML; no flattened or normalized offers."
  },
  "representation": "exact-public-dto-and-native-renderer-html",
  "representationNotes": {
    "current_reference": {
      "about_json_pointer": "/aboutHtml",
      "methods": [
        {
          "contract_json_pointer": "/methods/0/rawMethod/contract",
          "html_json_pointer": "/methods/0/html",
          "method_ordinal": 0
        },
        {
          "contract_json_pointer": "/methods/1/rawMethod/contract",
          "html_json_pointer": "/methods/1/html",
          "method_ordinal": 1
        },
        {
          "contract_json_pointer": "/methods/2/rawMethod/contract",
          "html_json_pointer": "/methods/2/html",
          "method_ordinal": 2
        }
      ],
      "role": "current-semantic-reference"
    },
    "raw_input": {
      "examples_role": "historical-input-not-current-ready-examples",
      "json_pointers": [
        "/rawModel",
        "/methods/0/rawMethod",
        "/methods/1/rawMethod",
        "/methods/2/rawMethod"
      ],
      "role": "historical-owner-input"
    },
    "schema": "ailoot-native-model-representations-v1"
  },
  "schema": "ailoot-static-model-facts-v1",
  "schema_version": 1,
  "shortText": "Модель оживления изображения: исходная картинка задаёт первый кадр, а описание направляет дальнейшее движение. Создаёт короткий видеоролик с возможностью звукового сопровождения.",
  "source": {
    "audit_sha256": "2e00086bcbfc28e64d0cebe97aa47c17d8d5618963027f8ffb9dc6123d7d25b1",
    "bridge_map_sha256": "1125275768b9636fc8461bc7da5061239a81ddfe508e2557843ca42c58ab0036",
    "raw_model_json_sha256": "8f9ccb41f0c10016c1cd4ca95822d1ff4714df3b91ee42273a16fa472311b5ce",
    "renderer_sha256": "aa692ffec412026bdeaf316df24a58e6c5083045e5246f6033f898d132afa5ff"
  },
  "sourceRevision": "a4a41847d07b375a7c1c1a42671bcc13edefbafaf8d364b6d012113b69bc5773"
}
