О чём урок
Прежде чем писать какой-либо код, вызовите навык /text-to-speech, чтобы изучить правильные паттерны ElevenLabs SDK. В этом примере используется Dubbing Projects API (dubbing v2): проект содержит исходный медиафайл и его транскрипцию, а каждый языковой таргет (language target) создает один дублированный output на одном языке. Защищенный POST endpoint, который запускает проект дубляжа из загруженной записи. Считайте ELEVENLABS_API_KEY из process.env. Верните 500, если отсутствует. Принимайте audio (File), targetLang (строка) и опциональный sourceLang (строка, по умолчанию auto) из FormData запроса. Верните 400 при отсутствии или недействительности аудио, или при отсутствии targetLang. Используйте ElevenLabsClient и вызовите client.dubbing.project.create({ file: audio, targetLanguage: targetLang, sourceLanguage: sourceLang === "auto" ? undefined : sourceLang, reference: "Browser dubbing demo" }). Ярлык targetLanguage также ставит в очередь языковой таргет, который начинает генерироваться автоматически, как только проект завершит транскрибирование. Верните JSON { projectId, languageId }, считывая languageId из project.languageIds?.[0] ?? null. Оборачивайте сбои в читаемые JSON-ошибки. Защищенный GET endpoint, который возвращает объединенный статус проекта и языка для polling. Считайте и проверьте projectId из параметров маршрута. Вызовите client.dubbing.project.get(projectId). Статусы проекта: queued, preparing, processing, ready или failed. Если у проекта есть языковой таргет (project.languageIds?.[0]), также вызовите client.dubbing.project.language.get(projectId, languageId). Статусы языка: queued, processing, completed, stale или failed. Верните JSON с projectStatus, languageId и languageStatus. Сохраняйте ответ компактным и удобным для клиентского polling. Защищенный GET endpoint, который проксирует дублированный аудио output. Считайте и проверьте projectId и languageId из параметров маршрута. Вызовите client.dubbing.project.language.get(projectId, languageId). Как только язык будет completed, outputs.losslessAudio содержит подписанный URL для скачивания, который истекает примерно через час; повторный запрос языка вернет новый. Верните 503 с читаемой JSON-ошибкой, если язык еще не completed или не имеет URL output. Запросите подписанный URL на стороне сервера и передайте тело обратно с исходным content type (по умолчанию audio/wav).
План урока
- 1. app/api/dubbing/route.ts
- 2. app/api/dubbing/[projectId]/route.ts
- 3. app/api/dubbing/[projectId]/audio/[languageId]/route.ts
- 4. app/page.tsx
Урок входит в полный доступ. Полный текст и видео открываются после оплаты. Первые уроки каждого курса бесплатны.