> ## 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.

# Automatizar vídeos de letras

> Escolha modelos, corrija timings e exporte uma versão escolhida do projeto

Use `@youka/sdk` e `@youka/cli` versão 0.2.0 ou posterior para estes exemplos. Projetos criados pela API permanecem disponíveis na sua biblioteca do Youka.

## Escolha um workflow e um modelo

`kind` seleciona o workflow do projeto. `karaoke` separa stems. `lyric-video` usa o áudio original e não cobra pela separação. Ao omitir `kind`, mantém-se o comportamento existente de karaoke. O processamento de letras é uma escolha separada entre alinhamento, transcrição ou nenhum processamento.

Descubra os modelos e a elegibilidade da conta antes de escolher um modelo.

```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"),
);
```

A resposta descreve IDs de modelos, operações, entradas de áudio, semântica de texto fornecido, workflows, suporte de idiomas e recursos exigidos. `suppliedTextHandling` distingue alinhamento, termos-chave do provedor e correção após a transcrição. A elegibilidade reflete a conta autenticada. A descoberta descreve o suporte configurado, não uma garantia de disponibilidade do provedor. A validação da requisição e as cotações de preço continuam sendo a autoridade.

Modelos que exigem vocais isolados não conseguem processar um lyric video sem separação. Use-os em um workflow de karaoke com um modelo de separação que produza vocais. Wav2Vec2 é um modelo de alinhamento. ElevenLabs Scribe é um modelo de transcrição. Um texto de transcrição fornecido serve como orientação, não como garantia de saída textual idêntica.

## Criar e cotar projetos

```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);
```

Alinhe letras fornecidas com um modelo anunciado para 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
```

Mantenha a separação para projetos de karaoke. Omita `--kind` ou passe `--kind karaoke` e escolha `--split-model`. Use `--mode none` para criar sem processamento de letras. Requisições de lyric-video rejeitam opções de separação.

Cote a mesma fonte, workflow e opções de processamento antes de criar.

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

Uma cotação verifica a mesma compatibilidade de modelo, política de idioma, recursos da conta, duração e regras de armazenamento que a criação. O detalhamento de créditos tem zero créditos de separação para lyric videos. Uma cotação não reserva capacidade nem créditos; o estado da conta pode mudar antes da criação.

## Corrigir timings sem jobs de processamento

Leia alinhamentos via `GET /projects/{projectId}/alignments`, depois obtenha o recurso escolhido via `GET /projects/{projectId}/alignments/{alignmentId}`. A lista contém `alignments`, `selectedAlignmentId` e `selectionRevision`. Cada recurso inclui o payload de timing, `revision`, `selected` e `selectionRevision`.

Atualizações substituem o objeto `alignment` completo. Elas não executam sincronização nem criam uma retenção de créditos de processamento. Ao editar, mantenha IDs, texto, índices de linha/palavra/subpalavra, informações do cantor e traduções. Os tempos são segundos decimais absolutos. Aplique qualquer correção desejada uma única vez nos valores enviados. Não adicione a mesma correção novamente como um offset de exportação.

```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,
});
```

Use `select: true` para salvar e selecionar de forma atômica. Para selecionar timings existentes sem substituí-los, chame `client.projects.alignments.select(projectId, alignmentId, { expectedRevision, expectedSelectionRevision })`.

A revisão do alinhamento protege o conteúdo dos timings. A revisão de seleção protege qual alinhamento está ativo. Um token desatualizado produz HTTP 409. Busque o recurso mais recente, compare as edições e envie uma substituição deliberada. Não atualize automaticamente o token e sobrescreva as alterações de outro editor.

A CLI aceita um arquivo JSON ou a entrada padrão. Um arquivo de importação contém `{ "alignment": { "items": [...] }, "expectedRevision": "..." }`. Inclua `select` e `expectedSelectionRevision` ao selecionar de forma atômica. Recursos exportados também contêm metadados de resposta, então extraia os campos de requisição antes de importar.

```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
```

Importações aceitam até 100.000 itens. Cada tempo de término deve ser estritamente maior que o de início. Números inválidos, tempos negativos, índices inválidos, intervalos de comprimento zero ou invertidos e timings além de uma duração conhecida do projeto são rejeitados. Sobreposições legítimas e timing de dueto continuam suportados. Reabra ou atualize um projeto já aberto no app após uma edição externa.

## Exportar uma versão escolhida

```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` é opcional em requisições de exportação e atualizações de configurações, e na query do GET de configurações. Ao omiti-lo, mantém-se o comportamento de versão primária. O alinhamento selecionado pertence ao projeto, enquanto o estilo e as configurações pertencem à versão escolhida.

```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 de operações de exportação na nuvem e payloads locais incluem `versionId`, `alignmentId` e `alignmentRevision`. Esses campos identificam o snapshot de timing usado para aquela exportação ou payload preparado. Cada preparação lê o estado atual, então uma exportação posterior separada pode observar edições mais novas. Salve o payload retornado quando um renderizador externo precisar renderizar exatamente aquele snapshot preparado e atualize-o quando URLs de mídia assinadas expirarem.

A saída local transparente usa ProRes 4444 em um contêiner MOV. `--mute-all` mapeia todos os stems do projeto para volume zero. Silêncio e a ausência de um stream de áudio são propriedades de saída diferentes; inspecione o arquivo renderizado se uma ferramenta downstream exigir uma delas. A renderização local não consome créditos de exportação na nuvem e continua sujeita à elegibilidade de recursos existente.

Timing de palavras, offsets globais de áudio e antecipação de letras são configurações separadas. Layouts existentes controlam a visibilidade das linhas. Esta versão não promete um intervalo fixo de revelação para cada linha nem adiciona uma API separada de anexação de backing track.

## Operar um catálogo com segurança

Mantenha um manifesto com um ID de item estável, fingerprint da fonte, configurações da operação, chave de idempotência, IDs de projeto/tarefa e o último resultado terminal. Reutilize uma chave apenas para retries da mesma requisição. Persista os resultados de criação antes de esperar a conclusão, para que um restart possa retomar o polling. Uploads e preparação de arquivos locais têm seu próprio ciclo de vida; uma chave de idempotência de criação não deduplica todo upload.

O executável [exemplo de catálogo](/examples/catalogue.js) aceita IDs de arquivos de entrada pré-enviados e persiste um checkpoint por item. Um manifesto se parece com isto.

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

Baixe o exemplo como `catalogue.ts`. Instale suas dependências e defina `YOUKA_API_KEY`. Use um projeto Node.js com `"type": "module"` no seu `package.json`.

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

Execute novamente com o mesmo manifesto e diretório de estado para retomar o polling de jobs aceitos ou repetir um envio incerto com sua chave original. Jobs concluídos e com falha são registrados e ignorados. Requisições alteradas exigem novos IDs de item. O lock de diretório impede que dois processos enviem o mesmo manifesto simultaneamente. Após um crash brusco, remova um `.lock` obsoleto apenas depois de confirmar que o PID armazenado nele não está mais em execução.

Comece com um item em andamento. Aumente um número de workers limitado somente após medir a latência de processamento e as respostas de rate-limit da sua conta. Faça retry de erros de transporte e rate limits com backoff, respeitando `Retry-After`. Não faça retry cegamente de erros de validação, conflitos de timing ou falhas terminais de processamento. Erros de autenticação exigem credenciais válidas; eles não significam que um job de processamento falhou.

Mantenha o polling existente de tarefas na nuvem e o tratamento de créditos em falhas. Nenhum endpoint em lote, promessa de webhook, mudança de preços, mudança de licenciamento ou política de retenção é introduzido aqui.
