Примеры интеграции
Создайте задачу, дождитесь результата и скачайте файл.
Создайте задачу, дождитесь результата и скачайте файл.
Используйте подключение и сохраните JSON из примеров как request.json. Вкладки ниже используют Bun 1.4+ TypeScript, Python 3, Go 1.22+ или Bash. BASE_URL должен быть HTTPS origin, ключ хранится на сервере. Один файл состояния относится к одному заказу; повторный запуск с сохранённым ID выполняет только GET.
Добавьте callback_url в request.json, как в
примере создания. Примеры отправки на cURL,
TypeScript, Python и Go используют этот JSON без изменения метода или пути.
Создайте задачу один раз и сохраните ID. Ваш HTTPS-обработчик принимает
POST со снимком задачи, сохраняет его
и быстро отвечает 200 или 204. Дальнейшая обработка выполняется после
ответа: прочитайте задачу через GET с API-ключом, проверьте статус и скачайте
результат. Не скачивайте видео до HTTP-подтверждения вебхука.
Сохраните периодический GET раз в 60–120 секунд как восстановление при
пропущенном уведомлении. Повторный callback не создаёт новый заказ и не должен
повторять действия приложения. Если callback_url не задан, используйте
обычный polling из примеров ниже.
umask 077
touch result.json content.headers && chmod 600 result.json content.headers || exit 1
[[ "$BASE_URL" =~ ^https://[A-Za-z0-9.-]+(:[0-9]{1,5})?$ &&
-n "$API_KEY" && -r request.json ]] || {
printf 'Задайте HTTPS BASE_URL, API_KEY и request.json\n' >&2
exit 1
}
OUTPUT_FILE=${VIDEO_OUTPUT:-seedance.mp4}
if [[ -f task-id.txt ]]; then
TASK_ID=$(< task-id.txt)
else
(
set -C
printf 'creating\n' > task-id.txt
) || {
printf 'Файл состояния уже существует; проверьте его до нового POST\n' >&2
exit 1
}
if curl --fail --silent --show-error --max-time 120 \
"$BASE_URL/v1/videos" \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @request.json \
-o created.json; then
TASK_ID=$(jq -er '
.id | select(type == "string" and length > 0)
' created.json) || exit 1
printf '%s\n' "$TASK_ID" > task-id.txt
else
printf 'Исход заказа неизвестен; проверьте кабинет до нового POST\n' >&2
exit 1
fi
fi
[[ "$TASK_ID" != creating && "$TASK_ID" =~ ^[A-Za-z0-9_-]+$ ]] || {
printf 'Некорректный ID задачи\n' >&2
exit 1
}
deadline=$((SECONDS + 2700))
completed=0
while ((SECONDS < deadline)); do
if ! http_status=$(curl --silent --show-error --max-time 60 \
--write-out '%{http_code}' \
"$BASE_URL/v1/videos/$TASK_ID" \
-H "Authorization: Bearer $API_KEY" \
-o result.json); then
sleep 30
continue
fi
case "$http_status" in
200) ;;
429 | 5??)
sleep 30
continue
;;
*)
printf 'Ошибка статуса HTTP %s; ID сохранён\n' "$http_status" >&2
exit 1
;;
esac
jq '{id, status, error}' result.json
status=$(jq -r '.status' result.json)
case "$status" in
completed)
completed=1
break
;;
failed)
printf 'Итоговый статус: %s\n' "$status" >&2
exit 1
;;
queued | in_progress) sleep 15 ;;
*)
printf 'Неизвестный статус: %s\n' "$status" >&2
exit 1
;;
esac
done
if ((!completed)); then
printf 'Лимит ожидания; продолжите с %s\n' "$TASK_ID" >&2
exit 1
fi
VIDEO_URL=$(jq -r '.content.video_url // empty' result.json)
if [[ -z "$VIDEO_URL" ]]; then
metadata=$(curl --silent --show-error --max-time 300 \
--dump-header content.headers --write-out '%{http_code} %{content_type}' \
"$BASE_URL/v1/videos/$TASK_ID/content" \
-H "Authorization: Bearer $API_KEY" -o seedance.download) || exit 1
http_status=${metadata%% *}
if [[ "$http_status" == 307 ]]; then
VIDEO_URL=$(awk 'tolower($1)=="location:" {print $2}' content.headers | tr -d '\r' | tail -1)
elif [[ "$http_status" == 200 ]]; then
mime=${metadata#* }
case "$mime" in
video/mp4* | video/quicktime* | application/octet-stream*)
mv seedance.download "$OUTPUT_FILE"
exit 0
;;
esac
fi
[[ "$http_status" == 307 ]] || {
printf 'Content HTTP %s; ID preserved\n' "$http_status" >&2
exit 1
}
fi
[[ "$VIDEO_URL" =~ ^https://[^/@?#]+ ]] \
&& [[ ! "$VIDEO_URL" =~ ^https://[^/?#]*@ ]] || {
printf 'Invalid signed HTTPS media URL\n' >&2
exit 1
}
# The signed URL grants temporary access. Never send the API Bearer to it.
metadata=$(curl --silent --show-error --max-time 300 \
--write-out '%{http_code} %{content_type}' \
"$VIDEO_URL" -o seedance.download) || exit 1
http_status=${metadata%% *}
mime=${metadata#* }
case "$http_status:$mime" in
2??:video/mp4* | 2??:video/quicktime* | 2??:application/octet-stream*)
mv seedance.download "$OUTPUT_FILE"
;;
*)
printf 'Неожиданный HTTP-ответ или тип файла\n' >&2
exit 1
;;
esac
Повторяйте только GET статуса каждые 10–15 секунд до итогового статуса или локального предела 45 минут. При таймауте POST до получения ID проверьте кабинет или поддержку. Для нового заказа используйте новое имя файла состояния. Локальный предел не отменяет удалённую задачу; для MOV задайте VIDEO_OUTPUT=seedance.mov (это имя используется всеми примерами). Защищайте локальные файлы состояния и результата: JSON ответа может содержать подписанную media-ссылку.