Wan API
В каталоге 5 записей семейства Wan: версии и режимы. Имя модели ставится в
поле model запроса createTask, а всё
остальное уходит вложенным объектом input. У каждой модели ниже её
поля, готовый вызов и ответ; общее для всех видео — на странице
Видео, а сам порядок вызова разобран в
разделе Как устроена задача.
Модели семейства
| Идентификатор | Модель | Задача | Страница на сайте |
|---|---|---|---|
| wan/3-0-video | Wan 3.0 Video | text-to-video | Открыть |
| wan/2-7-text-to-video | Wan 2.7 text-to-video | text-to-video | Открыть |
| wan/2-7-image-to-video | Wan 2.7 image-to-video | image-to-video | Открыть |
| wan/2-7-r2v | Wan 2.7 reference-to-video | reference-to-video | Открыть |
| wan/2-7-videoedit | Wan 2.7 Video Edit | video-edit | Открыть |
Wan 3.0 Video
Открыть страницу моделиwan/3-0-video
Поля запроса
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| model | текст | обязательное | wan/3-0-video |
| input | объект | обязательное | Параметры генерации — поля из таблицы ниже |
Поля input
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| prompt | текст | обязательное | от 1 до 20 000 символов |
| first_frame_url | ссылка | опц. | одна ссылка на изображение |
| last_frame_url | ссылка | опц. | одна ссылка на изображение |
| reference_image_urls | список ссылок | опц. | до 10 ссылок на изображение |
| reference_video_urls | список ссылок | опц. | до 5 ссылок на видео |
| reference_audio_urls | список ссылок | опц. | до 5 ссылок на аудио |
| reference_file_urls | список ссылок | опц. | до 1 ссылок на аудио |
| reference_link_urls | список ссылок | опц. | до 1 ссылок на аудио |
| resolution | значение из списка | опц. | 480P · 720P · 1080P |
| aspect_ratio | значение из списка | опц. | adaptive · 16:9 · 4:3 · 1:1 · 3:4 · 9:16 |
| duration | целое число | опц. | целое от 2 до 30 |
| audio | да или нет | опц. | true или false |
| seed | целое число | опц. | целое от 0 до 2 147 483 647 |
| nsfw_checker | да или нет | опц. | true или false |
Пример вызова
# 1. Поставить задачу — в ответе придёт её номер
TASK=$(curl -s https://api.gen202.com/api/v1/jobs/createTask \
-H "Authorization: Bearer sk-ваш-ключ" \
-H "Content-Type: application/json" \
-d '{
"model": "wan/3-0-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"aspect_ratio": "adaptive",
"resolution": "480P",
"duration": 2
}
}' | jq -r '.data.taskId')
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while true; do
RECORD=$(curl -s "https://api.gen202.com/api/v1/jobs/recordInfo?taskId=$TASK" \
-H "Authorization: Bearer sk-ваш-ключ")
STATE=$(echo "$RECORD" | jq -r '.data.state')
case "$STATE" in success|fail) break;; esac
sleep 3
done
# 3. Забрать результат. Ссылка на файл лежит в resultJson — это строка JSON
# внутри JSON, поэтому её разбирают вторым разбором (fromjson)
echo "$RECORD" | jq -r '.data |
if .state == "fail"
then "отказ \(.failCode): \(.failMsg)"
else .resultJson | fromjson | .resultUrls[0]
end'
import json
import time
import requests
headers = {"Authorization": "Bearer sk-ваш-ключ"}
# 1. Поставить задачу — в ответе придёт её номер
created = requests.post(
"https://api.gen202.com/api/v1/jobs/createTask",
headers=headers,
json={
"model": "wan/3-0-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"aspect_ratio": "adaptive",
"resolution": "480P",
"duration": 2
}
},
).json()
task_id = created["data"]["taskId"]
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while True:
task = requests.get(
"https://api.gen202.com/api/v1/jobs/recordInfo",
headers=headers,
params={"taskId": task_id},
).json()["data"]
if task["state"] in ("success", "fail"):
break
time.sleep(3)
# 3. Разобрать итог. У неудачи причина в failCode и failMsg
if task["state"] == "fail":
raise SystemExit("отказ " + task["failCode"] + ": " + task["failMsg"])
# resultJson — строка JSON внутри JSON, поэтому разбор второй
result = json.loads(task["resultJson"])
print(result["resultUrls"][0])
print("списано кредитов:", task["creditsConsumed"])
Пример проходит весь путь: ставит задачу, повторяет запрос состояния раз в
3 секунды, пока задача не закончится, и разбирает ответ до ссылки
на файл. Разборов два, потому что поле resultJson — строка JSON
внутри JSON. В теле первого запроса стоят обязательные поля модели и значения из её
перечислений, поэтому он проходит проверку шлюза как есть.
Подставить остаётся только свой ключ.
Пример на оболочке разбирает ответ через jq; на Python своего
ничего не нужно, кроме requests.
Ответ, когда задача готова
{
"code": 200,
"msg": "success",
"data": {
"taskId": "cm8r4t0vk0001s60p2xq7f9ab",
"model": "wan/3-0-video",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://file.example/result.mp4\"]}",
"failCode": "",
"failMsg": ""
}
}
Ссылка на файл лежит в resultJson — это строка, внутри которой ещё
один JSON, поэтому разбирать её нужно вторым разбором. Пока задача не завершилась, там пустая
строка, а в state — waiting,
queuing или generating. В настоящем ответе
есть ещё поле creditsConsumed со списанием; здесь его нет намеренно —
сумма зависит от запрошенного варианта, а цены живут в
каталоге. Все поля записи перечислены в разделе
Формат ответа.
Общее для всех моделей: Как устроена задача — чем отправить и как дождаться · Формат ответа — где в ответе ссылка на файл · Загрузка своих файлов — как получить ссылку на свою картинку · Отказы — что означает отказ
Wan 2.7
Открыть страницу моделиwan/2-7-text-to-video
Поля запроса
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| model | текст | обязательное | wan/2-7-text-to-video |
| input | объект | обязательное | Параметры генерации — поля из таблицы ниже |
Поля input
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| prompt | текст | обязательное | от 1 до 5 000 символов |
| negative_prompt | текст | опц. | не длиннее 500 символов |
| resolution | значение из списка | опц. | 720p · 1080p |
| ratio | значение из списка | опц. | 16:9 · 9:16 · 1:1 · 4:3 · 3:4 |
| duration | целое число | опц. | целое от 2 до 15 |
| audio_url | ссылка | опц. | одна ссылка на аудио |
| prompt_extend | да или нет | опц. | true или false |
| watermark | да или нет | опц. | true или false |
| seed | целое число | опц. | целое от 0 до 2 147 483 647 |
| nsfw_checker | да или нет | опц. | true или false |
Пример вызова
# 1. Поставить задачу — в ответе придёт её номер
TASK=$(curl -s https://api.gen202.com/api/v1/jobs/createTask \
-H "Authorization: Bearer sk-ваш-ключ" \
-H "Content-Type: application/json" \
-d '{
"model": "wan/2-7-text-to-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"resolution": "720p",
"duration": 2
}
}' | jq -r '.data.taskId')
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while true; do
RECORD=$(curl -s "https://api.gen202.com/api/v1/jobs/recordInfo?taskId=$TASK" \
-H "Authorization: Bearer sk-ваш-ключ")
STATE=$(echo "$RECORD" | jq -r '.data.state')
case "$STATE" in success|fail) break;; esac
sleep 3
done
# 3. Забрать результат. Ссылка на файл лежит в resultJson — это строка JSON
# внутри JSON, поэтому её разбирают вторым разбором (fromjson)
echo "$RECORD" | jq -r '.data |
if .state == "fail"
then "отказ \(.failCode): \(.failMsg)"
else .resultJson | fromjson | .resultUrls[0]
end'
import json
import time
import requests
headers = {"Authorization": "Bearer sk-ваш-ключ"}
# 1. Поставить задачу — в ответе придёт её номер
created = requests.post(
"https://api.gen202.com/api/v1/jobs/createTask",
headers=headers,
json={
"model": "wan/2-7-text-to-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"resolution": "720p",
"duration": 2
}
},
).json()
task_id = created["data"]["taskId"]
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while True:
task = requests.get(
"https://api.gen202.com/api/v1/jobs/recordInfo",
headers=headers,
params={"taskId": task_id},
).json()["data"]
if task["state"] in ("success", "fail"):
break
time.sleep(3)
# 3. Разобрать итог. У неудачи причина в failCode и failMsg
if task["state"] == "fail":
raise SystemExit("отказ " + task["failCode"] + ": " + task["failMsg"])
# resultJson — строка JSON внутри JSON, поэтому разбор второй
result = json.loads(task["resultJson"])
print(result["resultUrls"][0])
print("списано кредитов:", task["creditsConsumed"])
Пример проходит весь путь: ставит задачу, повторяет запрос состояния раз в
3 секунды, пока задача не закончится, и разбирает ответ до ссылки
на файл. Разборов два, потому что поле resultJson — строка JSON
внутри JSON. В теле первого запроса стоят обязательные поля модели и значения из её
перечислений, поэтому он проходит проверку шлюза как есть.
Подставить остаётся только свой ключ.
Пример на оболочке разбирает ответ через jq; на Python своего
ничего не нужно, кроме requests.
Ответ, когда задача готова
{
"code": 200,
"msg": "success",
"data": {
"taskId": "cm8r4t0vk0001s60p2xq7f9ab",
"model": "wan/2-7-text-to-video",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://file.example/result.mp4\"]}",
"failCode": "",
"failMsg": ""
}
}
Ссылка на файл лежит в resultJson — это строка, внутри которой ещё
один JSON, поэтому разбирать её нужно вторым разбором. Пока задача не завершилась, там пустая
строка, а в state — waiting,
queuing или generating. В настоящем ответе
есть ещё поле creditsConsumed со списанием; здесь его нет намеренно —
сумма зависит от запрошенного варианта, а цены живут в
каталоге. Все поля записи перечислены в разделе
Формат ответа.
wan/2-7-image-to-video
Поля запроса
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| model | текст | обязательное | wan/2-7-image-to-video |
| input | объект | обязательное | Параметры генерации — поля из таблицы ниже |
Поля input
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| prompt | текст | обязательное | от 1 до 5 000 символов |
| negative_prompt | текст | опц. | не длиннее 500 символов |
| resolution | значение из списка | опц. | 720p · 1080p |
| first_frame_url | ссылка | опц. | одна ссылка на изображение |
| last_frame_url | ссылка | опц. | одна ссылка на изображение |
| first_clip_url | ссылка | опц. | одна ссылка на видео |
| driving_audio_url | ссылка | опц. | одна ссылка на аудио |
| duration | целое число | опц. | целое от 2 до 15 |
| prompt_extend | да или нет | опц. | true или false |
| watermark | да или нет | опц. | true или false |
| seed | целое число | опц. | целое от 0 до 2 147 483 647 |
| nsfw_checker | да или нет | опц. | true или false |
Пример вызова
# 1. Поставить задачу — в ответе придёт её номер
TASK=$(curl -s https://api.gen202.com/api/v1/jobs/createTask \
-H "Authorization: Bearer sk-ваш-ключ" \
-H "Content-Type: application/json" \
-d '{
"model": "wan/2-7-image-to-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"resolution": "720p",
"duration": 2
}
}' | jq -r '.data.taskId')
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while true; do
RECORD=$(curl -s "https://api.gen202.com/api/v1/jobs/recordInfo?taskId=$TASK" \
-H "Authorization: Bearer sk-ваш-ключ")
STATE=$(echo "$RECORD" | jq -r '.data.state')
case "$STATE" in success|fail) break;; esac
sleep 3
done
# 3. Забрать результат. Ссылка на файл лежит в resultJson — это строка JSON
# внутри JSON, поэтому её разбирают вторым разбором (fromjson)
echo "$RECORD" | jq -r '.data |
if .state == "fail"
then "отказ \(.failCode): \(.failMsg)"
else .resultJson | fromjson | .resultUrls[0]
end'
import json
import time
import requests
headers = {"Authorization": "Bearer sk-ваш-ключ"}
# 1. Поставить задачу — в ответе придёт её номер
created = requests.post(
"https://api.gen202.com/api/v1/jobs/createTask",
headers=headers,
json={
"model": "wan/2-7-image-to-video",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"resolution": "720p",
"duration": 2
}
},
).json()
task_id = created["data"]["taskId"]
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while True:
task = requests.get(
"https://api.gen202.com/api/v1/jobs/recordInfo",
headers=headers,
params={"taskId": task_id},
).json()["data"]
if task["state"] in ("success", "fail"):
break
time.sleep(3)
# 3. Разобрать итог. У неудачи причина в failCode и failMsg
if task["state"] == "fail":
raise SystemExit("отказ " + task["failCode"] + ": " + task["failMsg"])
# resultJson — строка JSON внутри JSON, поэтому разбор второй
result = json.loads(task["resultJson"])
print(result["resultUrls"][0])
print("списано кредитов:", task["creditsConsumed"])
Пример проходит весь путь: ставит задачу, повторяет запрос состояния раз в
3 секунды, пока задача не закончится, и разбирает ответ до ссылки
на файл. Разборов два, потому что поле resultJson — строка JSON
внутри JSON. В теле первого запроса стоят обязательные поля модели и значения из её
перечислений, поэтому он проходит проверку шлюза как есть.
Подставить остаётся только свой ключ.
Пример на оболочке разбирает ответ через jq; на Python своего
ничего не нужно, кроме requests.
Ответ, когда задача готова
{
"code": 200,
"msg": "success",
"data": {
"taskId": "cm8r4t0vk0001s60p2xq7f9ab",
"model": "wan/2-7-image-to-video",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://file.example/result.mp4\"]}",
"failCode": "",
"failMsg": ""
}
}
Ссылка на файл лежит в resultJson — это строка, внутри которой ещё
один JSON, поэтому разбирать её нужно вторым разбором. Пока задача не завершилась, там пустая
строка, а в state — waiting,
queuing или generating. В настоящем ответе
есть ещё поле creditsConsumed со списанием; здесь его нет намеренно —
сумма зависит от запрошенного варианта, а цены живут в
каталоге. Все поля записи перечислены в разделе
Формат ответа.
wan/2-7-r2v
Поля запроса
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| model | текст | обязательное | wan/2-7-r2v |
| input | объект | обязательное | Параметры генерации — поля из таблицы ниже |
Поля input
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| prompt | текст | обязательное | от 1 до 5 000 символов |
| negative_prompt | текст | опц. | не длиннее 500 символов |
| resolution | значение из списка | опц. | 720p · 1080p |
| reference_image | список ссылок | опц. | до 5 ссылок на изображение |
| reference_video | список ссылок | опц. | до 5 ссылок на видео |
| first_frame | ссылка | опц. | одна ссылка на изображение |
| reference_voice | ссылка | опц. | одна ссылка на аудио |
| aspect_ratio | значение из списка | опц. | 16:9 · 9:16 · 1:1 · 4:3 · 3:4 |
| duration | целое число | опц. | целое от 2 до 10 |
| prompt_extend | да или нет | опц. | true или false |
| watermark | да или нет | опц. | true или false |
| seed | целое число | опц. | целое от 0 до 2 147 483 647 |
| nsfw_checker | да или нет | опц. | true или false |
Пример вызова
# 1. Поставить задачу — в ответе придёт её номер
TASK=$(curl -s https://api.gen202.com/api/v1/jobs/createTask \
-H "Authorization: Bearer sk-ваш-ключ" \
-H "Content-Type: application/json" \
-d '{
"model": "wan/2-7-r2v",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 2
}
}' | jq -r '.data.taskId')
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while true; do
RECORD=$(curl -s "https://api.gen202.com/api/v1/jobs/recordInfo?taskId=$TASK" \
-H "Authorization: Bearer sk-ваш-ключ")
STATE=$(echo "$RECORD" | jq -r '.data.state')
case "$STATE" in success|fail) break;; esac
sleep 3
done
# 3. Забрать результат. Ссылка на файл лежит в resultJson — это строка JSON
# внутри JSON, поэтому её разбирают вторым разбором (fromjson)
echo "$RECORD" | jq -r '.data |
if .state == "fail"
then "отказ \(.failCode): \(.failMsg)"
else .resultJson | fromjson | .resultUrls[0]
end'
import json
import time
import requests
headers = {"Authorization": "Bearer sk-ваш-ключ"}
# 1. Поставить задачу — в ответе придёт её номер
created = requests.post(
"https://api.gen202.com/api/v1/jobs/createTask",
headers=headers,
json={
"model": "wan/2-7-r2v",
"input": {
"prompt": "Рыжий кот в скафандре на фоне Земли, мягкий свет",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 2
}
},
).json()
task_id = created["data"]["taskId"]
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while True:
task = requests.get(
"https://api.gen202.com/api/v1/jobs/recordInfo",
headers=headers,
params={"taskId": task_id},
).json()["data"]
if task["state"] in ("success", "fail"):
break
time.sleep(3)
# 3. Разобрать итог. У неудачи причина в failCode и failMsg
if task["state"] == "fail":
raise SystemExit("отказ " + task["failCode"] + ": " + task["failMsg"])
# resultJson — строка JSON внутри JSON, поэтому разбор второй
result = json.loads(task["resultJson"])
print(result["resultUrls"][0])
print("списано кредитов:", task["creditsConsumed"])
Пример проходит весь путь: ставит задачу, повторяет запрос состояния раз в
3 секунды, пока задача не закончится, и разбирает ответ до ссылки
на файл. Разборов два, потому что поле resultJson — строка JSON
внутри JSON. В теле первого запроса стоят обязательные поля модели и значения из её
перечислений, поэтому он проходит проверку шлюза как есть.
Подставить остаётся только свой ключ.
Пример на оболочке разбирает ответ через jq; на Python своего
ничего не нужно, кроме requests.
Ответ, когда задача готова
{
"code": 200,
"msg": "success",
"data": {
"taskId": "cm8r4t0vk0001s60p2xq7f9ab",
"model": "wan/2-7-r2v",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://file.example/result.mp4\"]}",
"failCode": "",
"failMsg": ""
}
}
Ссылка на файл лежит в resultJson — это строка, внутри которой ещё
один JSON, поэтому разбирать её нужно вторым разбором. Пока задача не завершилась, там пустая
строка, а в state — waiting,
queuing или generating. В настоящем ответе
есть ещё поле creditsConsumed со списанием; здесь его нет намеренно —
сумма зависит от запрошенного варианта, а цены живут в
каталоге. Все поля записи перечислены в разделе
Формат ответа.
wan/2-7-videoedit
Поля запроса
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| model | текст | обязательное | wan/2-7-videoedit |
| input | объект | обязательное | Параметры генерации — поля из таблицы ниже |
Поля input
| Поле | Тип | Обяз. | Допустимые значения |
|---|---|---|---|
| video_url | ссылка | обязательное | одна ссылка на видео |
| prompt | текст | опц. | не длиннее 5 000 символов |
| negative_prompt | текст | опц. | не длиннее 500 символов |
| resolution | значение из списка | опц. | 720p · 1080p |
| reference_image | список ссылок | опц. | до 5 ссылок на изображение |
| aspect_ratio | значение из списка | опц. | 16:9 · 9:16 · 1:1 · 4:3 · 3:4 |
| duration | целое число | опц. | целое от 0 до 10 |
| audio_setting | значение из списка | опц. | auto · origin |
| prompt_extend | да или нет | опц. | true или false |
| watermark | да или нет | опц. | true или false |
| seed | целое число | опц. | целое от 0 до 2 147 483 647 |
| nsfw_checker | да или нет | опц. | true или false |
Пример вызова
# 1. Поставить задачу — в ответе придёт её номер
TASK=$(curl -s https://api.gen202.com/api/v1/jobs/createTask \
-H "Authorization: Bearer sk-ваш-ключ" \
-H "Content-Type: application/json" \
-d '{
"model": "wan/2-7-videoedit",
"input": {
"prompt": "Заменить фон на вечернюю городскую улицу, свет тёплый",
"video_url": "https://example.com/input.mp4",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 0
}
}' | jq -r '.data.taskId')
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while true; do
RECORD=$(curl -s "https://api.gen202.com/api/v1/jobs/recordInfo?taskId=$TASK" \
-H "Authorization: Bearer sk-ваш-ключ")
STATE=$(echo "$RECORD" | jq -r '.data.state')
case "$STATE" in success|fail) break;; esac
sleep 3
done
# 3. Забрать результат. Ссылка на файл лежит в resultJson — это строка JSON
# внутри JSON, поэтому её разбирают вторым разбором (fromjson)
echo "$RECORD" | jq -r '.data |
if .state == "fail"
then "отказ \(.failCode): \(.failMsg)"
else .resultJson | fromjson | .resultUrls[0]
end'
import json
import time
import requests
headers = {"Authorization": "Bearer sk-ваш-ключ"}
# 1. Поставить задачу — в ответе придёт её номер
created = requests.post(
"https://api.gen202.com/api/v1/jobs/createTask",
headers=headers,
json={
"model": "wan/2-7-videoedit",
"input": {
"prompt": "Заменить фон на вечернюю городскую улицу, свет тёплый",
"video_url": "https://example.com/input.mp4",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 0
}
},
).json()
task_id = created["data"]["taskId"]
# 2. Спрашивать состояние, пока задача не закончится: waiting, queuing и
# generating означают «работа идёт», success и fail — окончательные
while True:
task = requests.get(
"https://api.gen202.com/api/v1/jobs/recordInfo",
headers=headers,
params={"taskId": task_id},
).json()["data"]
if task["state"] in ("success", "fail"):
break
time.sleep(3)
# 3. Разобрать итог. У неудачи причина в failCode и failMsg
if task["state"] == "fail":
raise SystemExit("отказ " + task["failCode"] + ": " + task["failMsg"])
# resultJson — строка JSON внутри JSON, поэтому разбор второй
result = json.loads(task["resultJson"])
print(result["resultUrls"][0])
print("списано кредитов:", task["creditsConsumed"])
Пример проходит весь путь: ставит задачу, повторяет запрос состояния раз в
3 секунды, пока задача не закончится, и разбирает ответ до ссылки
на файл. Разборов два, потому что поле resultJson — строка JSON
внутри JSON. В теле первого запроса стоят обязательные поля модели и значения из её
перечислений, поэтому он проходит проверку шлюза как есть.
Заменить в нём нужно два значения: свой ключ и ссылки на исходные файлы — адреса example.com стоят заполнителями, файлов по ним нет.
Пример на оболочке разбирает ответ через jq; на Python своего
ничего не нужно, кроме requests.
Ответ, когда задача готова
{
"code": 200,
"msg": "success",
"data": {
"taskId": "cm8r4t0vk0001s60p2xq7f9ab",
"model": "wan/2-7-videoedit",
"state": "success",
"resultJson": "{\"resultUrls\":[\"https://file.example/result.mp4\"]}",
"failCode": "",
"failMsg": ""
}
}
Ссылка на файл лежит в resultJson — это строка, внутри которой ещё
один JSON, поэтому разбирать её нужно вторым разбором. Пока задача не завершилась, там пустая
строка, а в state — waiting,
queuing или generating. В настоящем ответе
есть ещё поле creditsConsumed со списанием; здесь его нет намеренно —
сумма зависит от запрошенного варианта, а цены живут в
каталоге. Все поля записи перечислены в разделе
Формат ответа.
Общее для всех моделей: Как устроена задача — чем отправить и как дождаться · Формат ответа — где в ответе ссылка на файл · Загрузка своих файлов — как получить ссылку на свою картинку · Отказы — что означает отказ