> ## Documentation Index
> Fetch the complete documentation index at: https://docs.youka.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Автоматизация лирик-видео

> Выбирайте модели, корректируйте тайминги и экспортируйте выбранную версию проекта

Используйте `@youka/sdk` и `@youka/cli` версии 0.2.0 или новее для этих примеров. Проекты, созданные через API, остаются доступными в вашей библиотеке Youka.

## Выберите рабочий процесс и модель

`kind` выбирает рабочий процесс проекта. `karaoke` разделяет стемы. `lyric-video` использует исходное аудио и не списывает кредиты за разделение. Если `kind` опущен, сохраняется существующее поведение karaoke. Обработка текста — это отдельный выбор: выравнивание, транскрипция или без обработки.

Перед выбором модели определите доступные модели и соответствие аккаунта требованиям.

```sh theme={null}
youka capabilities --json
```

```ts theme={null}
const capabilities = await client.capabilities.get();
const eligibleModels = capabilities.models.filter(
  (model) => model.eligible && model.workflows.includes("lyric-video"),
);
```

Ответ описывает ID моделей, операции, аудиовходы, семантику предоставленного текста, рабочие процессы, поддержку языков и требуемые возможности. `suppliedTextHandling` различает выравнивание, ключевые термины провайдера и корректировку после транскрипции. Соответствие требованиям отражает аутентифицированный аккаунт. Обнаружение описывает настроенную поддержку, а не гарантию доступности провайдера. Проверка запросов и расчёты стоимости остаются определяющими.

Модели, которым нужен изолированный вокал, не могут обрабатывать lyric video без разделения. Используйте их в рабочем процессе karaoke вместе с моделью разделения, которая выдаёт вокал. Wav2Vec2 — модель выравнивания. ElevenLabs Scribe — модель транскрипции. Переданный текст транскрипции — это ориентир, а не гарантия идентичного выходного текста.

## Создание проектов и расчёт стоимости

```ts theme={null}
import { AlignmentModel, YoukaClient } from "@youka/sdk";

const client = new YoukaClient({ apiKey: process.env.YOUKA_API_KEY! });
const operation = await client.projects.create(
  {
    kind: "lyric-video",
    source: { type: "path", path: "./song.wav" },
    title: "Example song",
    lyricsSource: {
      type: "transcribe",
      syncModel: AlignmentModel.ElevenLabsTranscription,
      lyrics: "Optional reference lyrics",
    },
  },
  { idempotencyKey: "example-song-create-v1" },
);
const { project } = await client.projects.wait(operation);
```

Выравнивайте предоставленный текст с моделью, заявленной для lyric videos.

```sh theme={null}
youka project create ./song.wav --kind lyric-video --mode align \
  --sync-model audioshake-alignment --lyrics 'Line one
Line two' --json
```

Сохраняйте разделение для проектов karaoke. Опустите `--kind` или передайте `--kind karaoke` и выберите `--split-model`. Используйте `--mode none`, чтобы создать проект без обработки текста. Запросы lyric-video отклоняют параметры разделения.

Рассчитывайте стоимость для того же источника, рабочего процесса и опций обработки до создания.

```sh theme={null}
youka project quote ./song.wav --kind lyric-video --mode transcribe \
  --sync-model elevenlabs-transcription --json
```

Расчёт стоимости проверяет те же совместимости моделей, языковую политику, возможности аккаунта, длительность и правила хранения, что и создание. В детализации кредитов для lyric videos разделение имеет нулевые кредиты. Расчёт стоимости не резервирует мощности или кредиты; состояние аккаунта может измениться до создания.

## Корректировка таймингов без задач обработки

Считывайте выравнивания через `GET /projects/{projectId}/alignments`, затем получайте выбранный ресурс через `GET /projects/{projectId}/alignments/{alignmentId}`. Список содержит `alignments`, `selectedAlignmentId` и `selectionRevision`. Каждый ресурс включает тайминговую нагрузку, `revision`, `selected` и `selectionRevision`.

Обновления заменяют объект `alignment` целиком. Они не запускают синхронизацию и не создают удержание кредитов на обработку. При редактировании сохраняйте ID, текст, индексы строк/слов/субслов, информацию о певце и переводы. Времена — это абсолютные десятичные секунды. Вносите желаемую корректировку один раз в отправляемых значениях. Не добавляйте ту же корректировку повторно как offset при экспорте.

```ts theme={null}
const snapshot = await client.projects.alignments.list(project.id);
const current = snapshot.alignments.find(
  (alignment) => alignment.id === snapshot.selectedAlignmentId,
);
if (!current) throw new Error("Project has no alignment to edit");

const corrected = structuredClone(current.alignment);
corrected.items[0]!.start = 0.75;
corrected.items[0]!.end = 1.25;

const saved = await client.projects.alignments.update(project.id, current.id, {
  alignment: corrected,
  expectedRevision: current.revision,
  select: true,
  expectedSelectionRevision: snapshot.selectionRevision,
});
```

Используйте `select: true`, чтобы сохранить и выбрать атомарно. Чтобы выбрать существующие тайминги, не заменяя их, вызовите `client.projects.alignments.select(projectId, alignmentId, { expectedRevision, expectedSelectionRevision })`.

Ревизия выравнивания защищает содержимое таймингов. Ревизия выбора защищает то, какое выравнивание активно. Устаревший токен приводит к HTTP 409. Получите актуальный ресурс, сравните правки и отправьте осознанную замену. Не обновляйте токен автоматически, перезаписывая изменения другого редактора.

CLI принимает JSON-файл или стандартный ввод. Файл импорта содержит `{ "alignment": { "items": [...] }, "expectedRevision": "..." }`. Добавляйте `select` и `expectedSelectionRevision` при атомарном выборе. Экспортированные ресурсы также содержат метаданные ответа, поэтому перед импортом извлеките поля запроса.

```sh theme={null}
youka project timings list proj_example --json
youka project timings get proj_example aln_example --json > timing-resource.json
youka project timings import proj_example aln_example --body corrected-request.json --json
youka project timings select proj_example aln_example \
  --expected-revision "$ALIGNMENT_REVISION" \
  --expected-selection-revision "$SELECTION_REVISION" --json
```

Импорт принимает до 100 000 элементов. Каждое конечное время должно быть строго больше начального. Некорректные числа, отрицательные времена, неверные индексы, нулевые по длине или обратные диапазоны, а также тайминги после известной длительности проекта отклоняются. Корректные перекрытия и дуэтные тайминги по-прежнему поддерживаются. Переоткройте или обновите уже открытый проект в приложении после внешнего редактирования.

## Экспорт выбранной версии

```sh theme={null}
youka project versions proj_example --json
youka export create proj_example --version-id ver_example --local \
  --transparent --mute-all --fps 30 --output ./overlay.mov --json
```

`versionId` необязателен в запросах экспорта и обновлениях настроек, а также в query для GET настроек. Если его опустить, сохраняется поведение основной версии. Выбранное выравнивание относится к проекту, а стили и настройки относятся к выбранной версии.

```ts theme={null}
const versions = await client.projects.versions.list(project.id);
const versionId = versions[0]!.id;
const stemVolumes = Object.fromEntries(
  project.stems.map((stem) => [stem.id, 0]),
);
const payload = await client.exports.prepareLocal(project.id, {
  versionId,
  transparent: true,
  stemVolumes,
  fps: 30,
});
console.log(payload.versionId, payload.alignmentId, payload.alignmentRevision);

await client.exports.create(project.id, {
  target: "local",
  versionId,
  transparent: true,
  stemVolumes,
  fps: 30,
  outputPath: "./overlay.mov",
});
```

Операционные handles облачного экспорта и локальные payloads включают `versionId`, `alignmentId` и `alignmentRevision`. Эти поля идентифицируют снимок таймингов, использованный для этого экспорта или подготовленного payload. Каждая подготовка читает текущее состояние, поэтому отдельный последующий экспорт может увидеть более новые правки. Сохраняйте возвращённый payload, когда внешний рендерер должен отрендерить ровно этот подготовленный снимок, и обновляйте его, когда истекают подписанные URL медиа.

Прозрачный локальный вывод использует ProRes 4444 в контейнере MOV. `--mute-all` сопоставляет всем стемам проекта нулевую громкость. Тишина и отсутствие аудиодорожки — разные свойства результата; проверяйте отрендеренный файл, если нижестоящему инструменту требуется одно из них. Локальный рендеринг не расходует кредиты облачного экспорта и остаётся предметом существующей проверки доступных возможностей.

Тайминги слов, глобальные аудио offset’ы и опережение текста — это отдельные настройки. Существующие макеты управляют видимостью строк. Этот релиз не обещает фиксированный интервал появления для каждой строки и не добавляет отдельный API для прикрепления backing-track.

## Безопасная работа с каталогом

Ведите манифест со стабильным ID элемента, отпечатком источника, настройками операции, ключом идемпотентности, ID проекта/задачи и последним терминальным результатом. Повторно используйте ключ только для повторов одного и того же запроса. Сохраняйте результаты создания до ожидания завершения, чтобы перезапуск мог продолжить опрос. Загрузки и локальная подготовка файлов имеют собственный жизненный цикл; ключ идемпотентности создания не дедуплицирует каждую загрузку.

Исполняемый пример [catalogue example](/examples/catalogue.js) принимает ID заранее загруженных входных файлов и сохраняет по одной контрольной точке на элемент. Манифест выглядит так.

```json theme={null}
[
  {
    "id": "song-001",
    "request": {
      "kind": "lyric-video",
      "inputFileId": "owned-upload-id",
      "title": "Example song",
      "lyricsSource": {
        "type": "transcribe",
        "syncModel": "elevenlabs-transcription"
      }
    }
  }
]
```

Скачайте пример как `catalogue.ts`. Установите его зависимости и задайте `YOUKA_API_KEY`. Используйте проект Node.js с `"type": "module"` в `package.json`.

```sh theme={null}
npm install @youka/sdk@^0.2.0 tsx
npx tsx ./catalogue.ts ./manifest.json ./catalogue-state 1
```

Запустите повторно с тем же манифестом и каталогом состояния, чтобы продолжить опрос принятых задач или повторить неопределённую отправку с её исходным ключом. Завершённые и проваленные задачи записываются и пропускаются. Изменённые запросы требуют новых ID элементов. Блокировка каталога предотвращает одновременную отправку одного и того же манифеста двумя процессами. После жёсткого падения удаляйте устаревший `.lock` только после подтверждения, что PID, записанный в нём, больше не запущен.

Начинайте с одного элемента «в полёте». Увеличивайте ограниченное число воркеров только после измерения задержек обработки и ответов о лимитах для вашего аккаунта. Повторяйте транспортные ошибки и ограничения по rate limit с backoff, учитывая `Retry-After`. Не делайте слепые повторы для ошибок валидации, конфликтов таймингов или терминальных сбоев обработки. Ошибки аутентификации требуют корректных учётных данных; они не означают, что задача обработки провалилась.

Сохраняйте существующий опрос облачных задач и обработку кредитов при неудачах. Здесь не вводятся batch endpoint, обещание webhook’ов, изменение цен, изменение лицензирования или политика хранения.
