Перенос продукта для преобразования текста в видео от одной инфраструктуры поставщика к другой не должен требовать переписывания каждого хелпера аутентификации, переменной окружения, правила повторных попыток и хука наблюдаемости. Более безопасный подход — отделить части интеграции, которые могут оставаться стабильными, от частей, специфичных для генерации видео.
Для команд, уже использующих клиент в стиле OpenAI, Flatkey предлагает практическую отправную точку: создайте один API-ключ, установите базовый URL клиента на https://router.flatkey.ai/v1, выполните небольшой совместимый запрос и подтвердите его в Usage Logs. Это докажет работу общей коммуникационной прослойки до того, как вы подключите асинхронный рабочий процесс генерации видео, специфичный для Seedance.
Это руководство показывает, как сделать такую миграцию управляемой, обратимой и удобной для проверки.
Краткий ответ
Стабильный базовый URL, совместимый с OpenAI, может сократить объем работ при миграции общих частей интеграции с ИИ:
- внедрение API-ключа
- конфигурация среды
- инициализация клиента
- сопоставление запросов
- политика повторных попыток и таймаутов
- мониторинг использования и затрат
Это не означает, что у каждого поставщика преобразования текста в видео одинаковое тело запроса или одинаковый конечный адрес. Генерация видео обычно требует отдельного асинхронного потока: создать задачу, сохранить ID задачи, выполнять опрос или получать webhook, а затем извлечь итоговый артефакт.
Следовательно, цель реализации не в том, чтобы «заставить Seedance работать в формате chat-completions». Цель — «сохранить стабильность соединения через gateway, а затем изолировать адаптер видеозадач за небольшим интерфейсом».
Почему стабильность базового URL важна для продуктов text-to-video
Миграции между поставщиками обычно ломаются на стыках вокруг вызова модели, а не в одной строке, где указывается модель. Продуктовое приложение может хранить API-ключи в secrets manager, HTTP-клиенты в нескольких сервисах, очереди воркеров, обработчики webhook, audit-логи, оповещения о расходах и настройки отката.
Если каждый поставщик напрямую встроен во все эти уровни, добавление новой видеомодели становится масштабным изменением инфраструктуры. Стабильная граница gateway ограничивает зону воздействия.
| Уровень | Сохранять стабильным | Менять только при необходимости |
|---|---|---|
| Учетные данные | Имя секрета и схема внедрения | Значение ключа и запись о ротации |
| Клиент | Общая инициализация HTTP- или OpenAI-стиля клиента | Видеоадаптер, используемый для выбранного маршрута |
| Базовый URL | Один URL gateway, управляемый через переменную окружения | Только при намеренном откате gateway |
| Наблюдаемость | ID корреляции, логи, задержка, проверка затрат | Поля статуса задачи, специфичные для поставщика |
| Надежность | Бюджеты таймаутов, ответственность за retry, политика circuit-breaker | Интервал опроса и конечные состояния видео |
| Логика продукта | Запрос пользователя, права доступа, квота, жизненный цикл артефакта | Prompt для Seedance и параметры видео |
В результате поверхность миграции становится меньше. Код вашего продукта по-прежнему зависит от стабильного внутреннего интерфейса, а адаптер обрабатывает различия в API для видео.
Самая безопасная последовательность миграции
Используйте две отдельные проверки вместо попытки валидировать весь путь генерации видео одним запросом.
- Проверка соединения: убедитесь в корректности аутентификации, OpenAI-совместимого базового URL, сетевого доступа и журналов использования.
- Проверка видеопотока: убедитесь в текущем маршруте Seedance, принимаемых параметрах, асинхронных переходах состояний, доставке ассетов и поведении биллинга.
Такое разделение упрощает классификацию сбоев. Если не проходит проверка соединения, проблема, вероятно, в учётных данных, конфигурации базового URL, сети или общем обработчике запросов. Если проверка соединения проходит, но видеозадание завершается с ошибкой, сосредоточьтесь на маршруте модели и видеоадаптере.
Шаг 1: вынесите базовый URL в конфигурацию
Не захардкоживайте URL провайдера в логике приложения. Поместите подключение к шлюзу в переменные окружения, чтобы развёртывание и откат не требовали изменений кода.
FLATKEY_API_KEY=sk-fk-replace-me
AI_BASE_URL=https://router.flatkey.ai/v1
AI_SMOKE_TEST_MODEL=gpt-4o-mini
VIDEO_PROVIDER=flatkey
VIDEO_MODEL=replace-with-current-seedance-route
Рассматривайте значение видеомодели как настройку на этапе деплоя. Алиасы моделей и поддерживаемые возможности могут меняться, поэтому перед выкладкой проверяйте текущий маршрут в Flatkey, а не копируйте старый идентификатор из статьи в блоге.
Шаг 2: один раз инициализируйте уже существующий клиент в стиле OpenAI
Если ваше приложение уже использует OpenAI Python SDK, изменение общего подключения намеренно небольшое.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["FLATKEY_API_KEY"],
base_url=os.getenv("AI_BASE_URL", "https://router.flatkey.ai/v1"),
)
Эквивалентная конфигурация TypeScript сохраняет ту же границу:
import OpenAI from "openai";
export const aiClient = new OpenAI({
apiKey: process.env.FLATKEY_API_KEY,
baseURL: process.env.AI_BASE_URL ?? "https://router.flatkey.ai/v1",
});
Важное архитектурное решение состоит в том, что сервисы импортируют настроенный клиент, а не создают собственные клиентские объекты конкретного провайдера по всей кодовой базе.
Шаг 3: выполните проверку соединения перед запуском видеозаданий
В quickstart Flatkey используется запрос chat-completions, совместимый с OpenAI, после чего предлагается проверить вызов в Usage Logs. Используйте этот небольшой тест, чтобы подтвердить работу общего интеграционного слоя.
import os
from app.ai_client import client
def verify_gateway_connection() -> dict:
response = client.chat.completions.create(
model=os.getenv("AI_SMOKE_TEST_MODEL", "gpt-4o-mini"),
messages=[
{"role": "user", "content": "Reply with: gateway connection verified"}
],
max_tokens=20,
)
return {
"request_model": response.model,
"finish_reason": response.choices[0].finish_reason,
"usage": response.usage.model_dump() if response.usage else None,
}
Этот запрос не тестирует генерацию видео Seedance. Он проверяет четыре обязательных условия, от которых зависят оба сценария:
- ключ присутствует и принимается
- базовый URL указан верно
- приложение может достучаться до маршрутизатора
- запрос отображается в панели с данными об использовании
Для подробного пошагового разбора первого запроса используйте краткое руководство по Seedance API для продуктовых команд.
Шаг 4: держите Seedance за асинхронным видеоадаптером
Генерация видео по тексту обычно занимает больше времени, чем обычный синхронный API-запрос. Публичный поток Seedance API описывает создание задачи с последующими проверками статуса или доставкой через webhook. Явно моделируйте этот жизненный цикл.
export type VideoJobState =
| "queued"
| "running"
| "succeeded"
| "failed"
| "cancelled";
export interface VideoJob {
id: string;
state: VideoJobState;
outputUrl?: string;
errorCode?: string;
}
export interface TextToVideoAdapter {
createJob(input: {
prompt: string;
model: string;
idempotencyKey: string;
}): Promise<VideoJob>;
getJob(jobId: string): Promise<VideoJob>;
}
Адаптер должен преобразовывать стабильные внутренние поля вашего продукта в требуемую полезную нагрузку текущей видео-конечной точки. Храните параметры, специфичные для провайдера, внутри этого адаптера, а не протаскивайте их в контроллеры, UI-код или схемы очередей.
Не следует предполагать, что видео-конечная точка — это /chat/completions, и не следует считать, что ответ чата доказывает доступность выбранного маршрута Seedance. Подтверждайте текущую конечную точку, псевдоним модели, параметры и значения статусов в документации продукта или на панели управления во время реализации.
Шаг 5: сделайте опрос безопасным и ограниченным
Видеопроцессу нужны иные правила надежности, чем для чат-запроса. Бесконечный опрос — это не стратегия повторных попыток.
import random
import time
TERMINAL_STATES = {"succeeded", "failed", "cancelled"}
def wait_for_video(adapter, job_id: str, deadline_seconds: int = 600):
started_at = time.monotonic()
attempt = 0
while time.monotonic() - started_at < deadline_seconds:
job = adapter.get_job(job_id)
if job.state in TERMINAL_STATES:
return job
attempt += 1
delay = min(30, 2 ** min(attempt, 4))
time.sleep(delay + random.uniform(0, 1))
raise TimeoutError(f"Video job {job_id} exceeded its processing deadline")
Производственный опрос также должен учитывать рекомендации провайдера и любой заголовок Retry-After. Сохраняйте внешний ID задачи до начала опроса, чтобы перезапуск воркера не создал дубликат видео.
Если доступны webhook, проверяйте подписи, быстро подтверждайте получение и делайте обработчик идемпотентным. Webhook может быть доставлен более одного раза или прийти после того, как worker, выполняющий опрос, уже завершил задачу.
Шаг 6: добавьте наблюдаемость на обоих уровнях
Отслеживайте запрос к gateway и задачу на уровне продукта отдельно.
Поля gateway
- окружение и имя сервиса
- внутренний ID запроса
- маршрут или псевдоним модели
- HTTP-статус
- задержка
- количество повторных попыток
- данные об использовании или стоимости, видимые на панели управления
Поля видео-задачи
- внешний ID задачи
- ID пользователя или рабочей области
- версия промпта, без логирования конфиденциального содержимого промпта по умолчанию
- модель и режим возможностей
- метки времени постановки в очередь, начала и завершения
- терминальное состояние и нормализованный код ошибки
- расположение объекта вывода и политика хранения
Панель управления — это общий операционный контрольный пункт. После smoke-теста и первой управляемой видеозадачи сравните журналы приложения с записями использования Flatkey. До увеличения трафика проверьте отсутствие записей, дублирующиеся задания, неожиданные имена моделей или изменения стоимости.
Step 7: use a reversible rollout plan
Изменение одного базового URL — это просто. Но безопасный поэтапный запуск всё равно требует контролей.
- Запустите smoke-тест из среды разработчика.
- Запустите одну не содержащую чувствительных данных оценочную задачу Seedance.
- Подтвердите обработку статуса задачи, получение артефактов и видимость использования.
- Включите маршрут для внутреннего аккаунта или небольшого процента трафика.
- Сравните процент успешных операций, сквозную задержку и стоимость одного завершённого артефакта.
- Увеличивайте трафик только после того, как бюджет ошибок остаётся приемлемым.
- Сохраняйте предыдущую конфигурацию провайдера доступной, пока не истекут критерии отката.
Определите триггеры отката до запуска. Примеры включают повторяющиеся ошибки аутентификации, повышенную долю неудачных заданий, задачи, застрявшие после крайнего срока обработки, отсутствующие записи об использовании или сбои при получении результата.
Migration checklist
| Check | Pass condition |
|---|---|
| Key ownership | Назначенный владелец может ротировать и отзывать ключ Flatkey |
| Secret handling | Ключ хранится на стороне сервера и отсутствует в исходном коде и браузерных бандлах |
| Stable base URL | Все общие клиенты читают AI_BASE_URL из конфигурации |
| Connection test | Smoke-тест, совместимый с OpenAI, выполняется успешно |
| Dashboard verification | Запрос smoke-теста отображается в Usage Logs |
| Current Seedance route | Псевдоним модели и её возможности подтверждены во время развёртывания |
| Async lifecycle | Создание, опрос или webhook, конечное состояние и получение артефакта протестированы |
| Idempotency | Повторные попытки не могут создавать непреднамеренные дублирующиеся видео |
| Timeout budget | Работники останавливают и эскалируют задачи, которые превышают дедлайн |
| Observability | Запросы шлюза и видеозадачи используют один correlation ID |
| Rollback | Предыдущая конфигурация и владелец решения задокументированы |
Common migration mistakes
Treating OpenAI compatibility as universal endpoint compatibility
Клиент, совместимый с OpenAI, может упростить аутентификацию и поддерживаемые семейства запросов. Но это не гарантирует, что каждая мультимодальная или видеооперация имеет ту же схему. Оставляйте видеоадаптер явным.
Changing the key, base URL, model, and worker logic in one release
Это затрудняет локализацию сбоев. Сначала подтвердите соединение со шлюзом, затем меняйте видеопуть.
Retrying job creation without an idempotency strategy
Тайм-аут сети может произойти уже после того, как провайдер принял задачу. Безусловное создание ещё одной задачи может привести к дублирующемуся артефакту и его оплате.
Using the HTTP request timeout as the video deadline
Запрос на создание задачи и жизненный цикл обработки видео — это разные таймеры. Делайте первый запрос коротким, а затем отслеживайте асинхронный дедлайн в устойчивом состоянии задачи.
Skipping dashboard verification
Успешный ответ приложения — это еще не полная операционная проверка. Убедитесь, что сведения об использовании, модели, задержке и стоимости отображаются там, где команда ожидает их отслеживать.
FAQ
Могу ли я интегрировать Seedance, изменив только базовый URL OpenAI?
Изменение базового URL может упростить общий слой подключения для поддерживаемых запросов, совместимых с OpenAI. Для генерации видео Seedance по-прежнему может требовать выделенную асинхронную конечную точку и параметры, специфичные для провайдера. Перед внедрением проверьте текущий маршрут.
Что должно остаться неизменным во время миграции?
Сохраните неизменными внедрение секретов, именование окружений, correlation ID, логирование, оповещения и ориентированный на продукт видеоинтерфейс. Ограничьте специфичные для провайдера изменения конфигурацией и видеоадаптером.
Зачем запускать smoke-тест чата для видеопродукта?
Smoke-тест быстро изолирует аутентификацию шлюза, базовый URL, сеть и Usage Logs от более долгого видеопроцесса. Это тест соединения, а не тест видеовозможностей.
Следует ли мне опрашивать API или использовать webhooks для завершения видео?
Используйте механизм, поддерживаемый текущим видео API и вашей инфраструктурой. Опрашивание проще, но его нужно ограничивать по времени и применять с экспоненциальной задержкой. Webhooks уменьшают объем опросов, но требуют проверки подписи, идемпотентности и сверки пропущенных событий.
Как предотвратить дублирование видео-задач?
Создайте и сохраните ключ идемпотентности для запроса продукта, немедленно сохраните внешний ID задачи и по возможности делайте так, чтобы повторные попытки возобновляли существующую задачу.
Где следует сравнивать стоимость перед запуском?
Изучите текущую страницу цен Flatkey, затем сравнивайте стоимость за завершенное видео, а не только цену за запрос или за секунду. Учитывайте в расчете неудачные и дублированные задачи.
Сначала выстройте стабильную границу
Самая быстрая миграция — это не та, где в первый день изменено меньше всего строк. Это та, которая сводит будущие изменения провайдера к управляемому обновлению конфигурации и небольшому адаптеру.
Начните с одного ключа Flatkey, переведите общий клиент на стабильный базовый URL, проверьте подключение в Usage Logs, а затем протестируйте текущий рабочий процесс Seedance как систему асинхронных задач. Когда проверки пройдут успешно, получите ключ и выполните развертывание с явными метриками и триггерами отката.



