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

# Dubbing projektu

> Dubbing już transkrybowanego projektu na podstawie własnego przetłumaczonego SRT

# Dubbing projektu

Wygeneruj głosy i zmiksuj wynik istniejącego projektu na podstawie przetłumaczonego SRT, który podajesz. VoiceCheap nic nie tłumaczy na tym endpoincie: bez silnika tłumaczenia, bez przeredagowania SmartSync i bez glosariusza. Każdy cue jest odczytywany dosłownie na pasującym segmencie transkrypcji projektu, a następnie miksowany z oryginalnym tłem, napisami i opcjonalną synchronizacją ruchu warg, tak jak zwykłe tłumaczenie.

Użyj go, gdy tłumaczenie powstaje gdzie indziej (tłumacz, własne narzędzia, przepływ automatyzacji), a VoiceCheap ma tylko wygenerować głosy. Przebieg jest asynchroniczny: odpytuj [Pobierz status tłumaczenia](/docs/pl/api-reference/translation-status) albo nasłuchuj [Webhooki](/docs/pl/api-reference/webhooks).

## Wymagania wstępne

* Projekt musi istnieć, a jego transkrypcja musi być ukończona: utwórz go przez [Utwórz projekt](/docs/pl/api-reference/create-project) (sama transkrypcja) albo [Rozpocznij tłumaczenie](/docs/pl/api-reference/translate) i poczekaj na `transcriptionStatus: "success"`.
* SRT musi pokrywać transkrypcję projektu: każdy segment potrzebuje co najmniej jednego cue, a każdy cue musi przypadać na segment. Wyeksportuj transkrypcję przez [Eksportuj transkrypcję projektu](/docs/pl/api-reference/project-transcript) i przetłumacz ją cue po cue, aby zachować kody czasu.
* Żądanie jest rozliczane jak tłumaczenie tego samego materiału, z tym samym sprawdzeniem kredytów. Tryby synchronizacji ust zużywają jak zwykle dodatkowe kredyty.

## Limit współbieżności

Tworzenie projektów, tłumaczenie i dubbing sprawdzają limit aktywnych tłumaczeń na koncie (najwyżej 10, ewentualnie mniej). Miejsca zajmują tylko trwające tłumaczenia lub dubbingi; projekty obejmujące wyłącznie transkrypcję ich nie zajmują. Po osiągnięciu limitu API zwraca `CONCURRENT_TRANSLATION_LIMIT_REACHED` (HTTP 429). Obowiązujący limit znajduje się w `details.limit`.

Druga operacja dla tego samego projektu i języka docelowego również jest odrzucana, gdy pierwsza trwa (`TRANSLATION_ALREADY_IN_PROGRESS`, HTTP 409).

## Żądanie

Ten endpoint przyjmuje treść JSON (`Content-Type: application/json`). Opcje logiczne i liczbowe są wysyłane jako wartości JSON, a nie jako ciągi znaków.

### Nagłówki

<ParamField header="x-api-key" type="string" required>
  Twój klucz API VoiceCheap. Pobierz go z [app.voicecheap.ai/page-api](https://app.voicecheap.ai/page-api).
</ParamField>

### Parametry ścieżki

<ParamField path="projectId" type="string" required>
  Identyfikator projektu zwracany przez [Utwórz projekt](/docs/pl/api-reference/create-project) lub [Rozpocznij tłumaczenie](/docs/pl/api-reference/translate).
</ParamField>

### Parametry treści

<ParamField body="targetLanguage" type="string" required>
  Język `translatedSrt`, małymi literami, z tej samej listy co [Rozpocznij tłumaczenie](/docs/pl/api-reference/translate). Jeśli projekt nie ma jeszcze pracy dla tego języka, zostanie ona utworzona, a język dodany do projektu.
</ParamField>

<ParamField body="translatedSrt" type="string" required>
  Końcowa treść SRT w języku docelowym (numer cue, linia czasu, tekst). Maksymalnie 1 000 000 znaków. Cue są dopasowywane do segmentów transkrypcji po znacznikach czasu: cue zaczynający się w ciągu 50 ms od początku segmentu jest przypisywany do tego segmentu, w przeciwnym razie do segmentu o największym nakładaniu. Kilka cue na jednym segmencie jest łączonych spacją. Czas, mówca i kolejność każdego odczytanego segmentu zawsze pochodzą z transkrypcji projektu; Twoje kody czasu służą tylko do dopasowania.
</ParamField>

<ParamField body="webhookUrl" type="string">
  Endpoint https, który od tej chwili odbiera [zdarzenia webhook](/docs/pl/api-reference/webhooks) tego projektu i zastępuje endpoint skonfigurowany na koncie.

  **Domyślnie:** Endpoint już zapisany w projekcie, a następnie endpoint webhook konta.
</ParamField>

<ParamField body="keepBackgroundMusic" type="boolean">
  Zachowaj oryginalne tło audio (muzyka, otoczenie) pod wygenerowanymi głosami.

  **Domyślnie:** `true`
</ParamField>

<ParamField body="keepOriginalVoice" type="boolean">
  Zachowaj cicho oryginalnego mówcę pod wygenerowanym głosem.

  **Domyślnie:** `false`
</ParamField>

<ParamField body="originalVoiceVolume" type="number">
  Głośność oryginalnego głosu od `1` do `70`, gdy `keepOriginalVoice` jest włączone.

  **Domyślnie:** `30`
</ParamField>

<ParamField body="voiceMode" type="string">
  Strategia głosu: `cloning` (klonowanie głosów mówców projektu) lub `custom` (użycie głosu z katalogu albo własnego zapisanego głosu niestandardowego).

  **Domyślnie:** `cloning`
</ParamField>

<ParamField body="voiceId" type="string">
  Wymagane, gdy `voiceMode` ma wartość `custom`. Użyj identyfikatora z `dubbing_voices_list`: głosu z katalogu lub głosu niestandardowego zapisanego
  przez uwierzytelnione konto. Rozliczanie zespołowe nie daje dostępu do głosów zapisanych przez innych członków.
</ParamField>

<ParamField body="voiceIsolatorOption" type="string">
  Tryb izolacji głosu, gdy `keepBackgroundMusic` jest włączone: `studio` albo `realistic`.

  **Domyślnie:** `studio`
</ParamField>

<ParamField body="subtitles" type="boolean">
  Wypal napisy w wideo wynikowym. Wymaga projektu wideo.

  **Domyślnie:** `false`
</ParamField>

<ParamField body="subtitlesSource" type="string">
  Tekst napisów, gdy `subtitles` jest włączone: `translated` (Twój SRT) albo `original` (transkrypcja źródłowa).

  **Domyślnie:** `translated`
</ParamField>

<ParamField body="lipSyncMode" type="string">
  Uruchom synchronizację ust, gdy dubbing będzie gotowy: `standard`, `pro` albo `studio`. Zasady planu, czasu trwania i kredytów są takie same jak w [Rozpocznij tłumaczenie](/docs/pl/api-reference/translate). Wymaga projektu wideo.

  **Domyślnie:** pomiń pole, aby nie uruchamiać synchronizacji ust.
</ParamField>

<ParamField body="activeSpeakerDetectionEnabled" type="boolean">
  Włącz wykrywanie aktywnego mówcy dla żądanej synchronizacji ust.

  **Domyślnie:** `false`
</ParamField>

<ParamField body="voiceCloningSettings" type="object">
  Dostrajanie klonowania głosu jako obiekt JSON z `stability` i `similarity` między `0` a `1`. Tylko z `voiceMode: "cloning"`. Objaśnienie każdej wartości jest w [Rozpocznij tłumaczenie](/docs/pl/api-reference/translate).
</ParamField>

<ParamField body="translationTimeSkips" type="array">
  Zakresy czasu źródła, które zostają w języku oryginalnym, jako `[{ "startTime": 10.2, "endTime": 12.8 }]`. Wymaga projektu wideo i `keepBackgroundMusic: true`, nie można łączyć z `keepOriginalVoice` i nie może nachodzić na segmenty transkrypcji.
</ParamField>

## Odpowiedź

<ResponseField name="success" type="boolean" required>
  Zawsze `true` dla udanych żądań.
</ResponseField>

<ResponseField name="message" type="string" required>
  Czytelne potwierdzenie.
</ResponseField>

<ResponseField name="projectId" type="string" required>
  Projekt, który jest dubbingowany.
</ResponseField>

<ResponseField name="workId" type="string" required>
  Praca tłumaczenia użyta dla `targetLanguage`. Odpowiada `workId` w endpointach statusu, szczegółów i transkrypcji.
</ResponseField>

<ResponseField name="estimatedDuration" type="number" required>
  Przybliżony szacunek przetwarzania w minutach: pięć minut przetwarzania na każdą rozpoczętą minutę materiału źródłowego.
</ResponseField>

```json Response theme={null}
{
  "success": true,
  "message": "Dubbing started successfully from the provided translation. Use the status endpoint to track progress.",
  "projectId": "project_123",
  "workId": "work_456",
  "estimatedDuration": 10
}
```

## Śledzenie przebiegu

Projekt przechodzi do przepływu `translation`, gdy tylko zaczyna się dubbing, więc [Pobierz status tłumaczenia](/docs/pl/api-reference/translation-status) śledzi nowe uruchomienie: `status` przechodzi z `processing` do `success` (z `translatedVideoUrl` i `translatedAudioUrl`) albo `failed` (z `error`). Webhooki `project.translation.completed` i `project.translation.failed` są wysyłane z tym samym `targetLanguage`. W [Pobierz szczegóły projektu](/docs/pl/api-reference/project-details) przetłumaczona wersja zgłasza `settings.dubbingMode: "dub-only"` i `settings.smartSync: false`.

Błędy dopasowania pojawiają się po przyjęciu żądania POST. Endpoint statusu zwraca `status: "failed"` z `error.code` i `error.message`; webhook `project.translation.failed` zawiera ten sam kod i komunikat. Przy `TRANSLATED_SRT_UNMATCHED_CUES` numery niedopasowanych cue znajdują się w komunikacie, a przy `TRANSLATED_SRT_MISSING_SEGMENTS` — indeksy segmentów bez cue. Te odpowiedzi asynchroniczne nie zawierają ustrukturyzowanego pola `details`. Popraw SRT i ponownie wywołaj endpoint: nieudana wersja pozostanie w historii projektu, a zostanie utworzona nowa.

### Sprawdzanie tempa

Wyeksportuj przetłumaczoną transkrypcję jako JSON przez [Eksportuj transkrypcję projektu](/docs/pl/api-reference/project-transcript). Każdy segment ma `finalSpeedFactor`, czyli stosunek wygenerowanej mowy do okna segmentu. Skróć cue powyżej około `1.3`, a potem uruchom dubbing ponownie z poprawionym SRT.

## Przykładowy przebieg

Typowa automatyzacja (na przykład scenariusz n8n lub Make) łączy endpointy w następujący sposób:

1. `POST /v1/projects` z materiałem, `targetLanguage` i jawnym `originalLanguage` (sama transkrypcja).
2. Odpytuj `GET /v1/translate/{projectId}/status`, aż `transcriptionStatus` będzie `success`, albo poczekaj na webhook `project.created`.
3. `POST /v1/projects/{projectId}/transcript` z `{ "source": "original", "outputFormat": "srt" }` i przetłumacz cue, zachowując numerację i kody czasu.
4. `POST /v1/projects/{projectId}/dub` z przetłumaczonym SRT.
5. Odpytuj endpoint statusu, aż `status` będzie `success`, albo poczekaj na `project.translation.completed`.
6. Pobierz `translatedVideoUrl` (albo `lipSync.videoUrl`, jeśli zażądano synchronizacji ust).
7. `DELETE /v1/translate/{projectId}`, gdy wyniki są już zapisane po Twojej stronie.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.voicecheap.ai/v1/projects/project_123/dub" \
    -H "x-api-key: vc_your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "targetLanguage": "english",
      "translatedSrt": "1\n00:00:00,000 --> 00:00:02,400\nWelcome to this lesson.\n\n2\n00:00:02,400 --> 00:00:05,100\nToday we talk about fractions.",
      "keepBackgroundMusic": true,
      "subtitles": true,
      "subtitlesSource": "translated"
    }'
  ```

  ```typescript TypeScript theme={null}
  interface DubProjectResponse {
    success: boolean;
    message: string;
    projectId: string;
    workId: string;
    estimatedDuration: number;
  }

  const API_BASE_URL = 'https://api.voicecheap.ai/v1';
  const headers = { 'x-api-key': 'vc_your-api-key', 'Content-Type': 'application/json' };

  async function waitForStatus(projectId: string, isReady: (status: any) => boolean): Promise<any> {
    while (true) {
      const status = await fetch(`${API_BASE_URL}/translate/${projectId}/status`, { headers }).then((response) => response.json());
      if (status.status === 'failed') throw new Error(`${status.error?.code}: ${status.error?.message}`);
      if (isReady(status)) return status;
      await new Promise((resolve) => setTimeout(resolve, 15_000));
    }
  }

  async function dubExistingProject(projectId: string, translatedSrt: string): Promise<string> {
    // 1. The project was created earlier with POST /v1/projects; wait for its transcript.
    await waitForStatus(projectId, (status) => status.transcriptionStatus === 'success');

    // 2. Send the translation you produced from the exported transcript.
    const dubResponse = await fetch(`${API_BASE_URL}/projects/${projectId}/dub`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ targetLanguage: 'english', translatedSrt, keepBackgroundMusic: true }),
    });
    if (!dubResponse.ok) {
      const error = await dubResponse.json();
      throw new Error(`${error.code}: ${error.message}`);
    }
    const { workId } = (await dubResponse.json()) as DubProjectResponse;
    console.log('Dubbing started on work', workId);

    // 3. Wait for the dubbed output.
    const completed = await waitForStatus(projectId, (status) => status.status === 'success');
    return completed.translatedVideoUrl as string;
  }
  ```

  ```python Python theme={null}
  import time
  import requests

  API_BASE_URL = 'https://api.voicecheap.ai/v1'
  HEADERS = {'x-api-key': 'vc_your-api-key'}


  def wait_for_status(project_id, is_ready):
      while True:
          status = requests.get(f'{API_BASE_URL}/translate/{project_id}/status', headers=HEADERS).json()
          if status['status'] == 'failed':
              raise RuntimeError(f"{status['error']['code']}: {status['error']['message']}")
          if is_ready(status):
              return status
          time.sleep(15)


  def dub_existing_project(project_id, translated_srt):
      wait_for_status(project_id, lambda status: status['transcriptionStatus'] == 'success')

      response = requests.post(
          f'{API_BASE_URL}/projects/{project_id}/dub',
          headers=HEADERS,
          json={'targetLanguage': 'english', 'translatedSrt': translated_srt, 'keepBackgroundMusic': True},
      )
      response.raise_for_status()
      print('Dubbing started on work', response.json()['workId'])

      completed = wait_for_status(project_id, lambda status: status['status'] == 'success')
      return completed['translatedVideoUrl']
  ```
</CodeGroup>

## Błędy

| Status | Kod | Opis |
| - | - | - |
| 400 | `VALIDATION_ERROR` | Pole treści jest brakujące lub nieprawidłowe (`details` wymienia każde pole) |
| 400 | `INVALID_TRANSLATED_SRT` | translatedSrt nie zawiera prawidłowych cue SRT |
| 400 | `INVALID_BOOLEAN_VALUE` | Opcja logiczna nie została wysłana jako wartość logiczna JSON |
| 400 | `INVALID_NUMBER_VALUE` | Opcja liczbowa nie została wysłana jako liczba JSON |
| 400 | `DURATION_DETECTION_FAILED` | Zapisany czas trwania medium projektu jest niedostępny |
| 400 | `VOICE_ID_REQUIRED` | Wybrano tryb niestandardowe głosy bez identyfikatora głosu |
| 400 | `VOICE_ID_NOT_ALLOWED_WITH_CLONING` | Identyfikator głosu został połączony z klonowanie głosu |
| 400 | `VOICE_CLONING_SETTINGS_NOT_ALLOWED` | Ustawienia klonowania zostały połączone z trybem niestandardowe głosy |
| 400 | `TRANSLATION_TIME_SKIP_CONFLICT` | Pominięcia czasu są w konflikcie z inną opcją audio |
| 400 | `TRANSLATION_TIME_SKIP_REQUIRES_BACKGROUND` | Pominięcia czasu wymagają dźwięk w tle |
| 400 | `TRANSLATION_TIME_SKIP_OUT_OF_RANGE` | Pominięcie czasu wykracza poza czas trwania mediów |
| 400 | `SUBTITLES_NOT_AVAILABLE_FOR_AUDIO` | Zażądano wtopione napisy dla wejścia audio |
| 400 | `LIPSYNC_NOT_AVAILABLE_FOR_AUDIO` | Zażądano synchronizacja ruchu ust dla wejścia audio |
| 400 | `TRANSLATION_TIME_SKIP_NOT_AVAILABLE_FOR_AUDIO` | Zażądano pominięcia czasu dla wejścia audio |
| 400 | `LIPSYNC_VIDEO_TOO_LONG` | Zażądano synchronizacja ruchu ust dla mediów dłuższych niż obsługiwany czas trwania |
| 401 | `MISSING_API_KEY` | Wymagany jest klucz API |
| 401 | `INVALID_API_KEY_FORMAT` | Klucz API musi zaczynać się od `vc_` |
| 401 | `INVALID_API_KEY` | Podany klucz API jest nieprawidłowy |
| 403 | `SUBSCRIPTION_REQUIRED` | Dostęp do API wymaga planu Starter lub wyższego |
| 403 | `FORBIDDEN` | Brak uprawnień dostępu do projektu |
| 403 | `INSUFFICIENT_CREDITS` | Za mało kredytów, aby zdubbingować ten projekt |
| 403 | `CUSTOM_VOICE_ACCESS_DENIED` | Wybrany głos nie pochodzi z katalogu ani nie jest głosem niestandardowym zapisanym przez uwierzytelnione konto. |
| 403 | `LIPSYNC_MODE_ACCESS_DENIED` | Tryb premium synchronizacja ruchu ust jest niedostępny w bieżącym planie |
| 404 | `PROJECT_NOT_FOUND` | Projekt nie istnieje |
| 409 | `DUB_ONLY_REQUIRES_TRANSCRIPTION` | Transkrypcja projektu jest nadal przetwarzana albo nie powiodła się |
| 409 | `TRANSLATION_ALREADY_IN_PROGRESS` | Dubbing tego języka jest już w toku w tym projekcie |
| 429 | `RATE_LIMIT_EXCEEDED` | Zbyt wiele żądań (limit: 10 żądań na minutę) |
| 429 | `CONCURRENT_TRANSLATION_LIMIT_REACHED` | Osiągnięto limit równoczesnych tłumaczeń dla konta; zobacz `details.limit` |
| 500 | `INTERNAL_ERROR` | Nieoczekiwany błąd serwera |

Błędy dopasowania wykryte w trakcie uruchomienia (`TRANSLATED_SRT_UNMATCHED_CUES`, `TRANSLATED_SRT_MISSING_SEGMENTS`) zwracają endpoint statusu i webhook niepowodzenia, a nie to żądanie.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.