Dubbing projektu
curl --request POST \
--url https://api.voicecheap.ai/v1/projects/{projectId}/dub \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"targetLanguage": "<string>",
"translatedSrt": "<string>",
"webhookUrl": "<string>",
"keepBackgroundMusic": true,
"keepOriginalVoice": true,
"originalVoiceVolume": 123,
"voiceMode": "<string>",
"voiceId": "<string>",
"voiceIsolatorOption": "<string>",
"subtitles": true,
"subtitlesSource": "<string>",
"lipSyncMode": "<string>",
"activeSpeakerDetectionEnabled": true,
"voiceCloningSettings": {},
"translationTimeSkips": [
{}
]
}
'import requests
url = "https://api.voicecheap.ai/v1/projects/{projectId}/dub"
payload = {
"targetLanguage": "<string>",
"translatedSrt": "<string>",
"webhookUrl": "<string>",
"keepBackgroundMusic": True,
"keepOriginalVoice": True,
"originalVoiceVolume": 123,
"voiceMode": "<string>",
"voiceId": "<string>",
"voiceIsolatorOption": "<string>",
"subtitles": True,
"subtitlesSource": "<string>",
"lipSyncMode": "<string>",
"activeSpeakerDetectionEnabled": True,
"voiceCloningSettings": {},
"translationTimeSkips": [{}]
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
targetLanguage: '<string>',
translatedSrt: '<string>',
webhookUrl: '<string>',
keepBackgroundMusic: true,
keepOriginalVoice: true,
originalVoiceVolume: 123,
voiceMode: '<string>',
voiceId: '<string>',
voiceIsolatorOption: '<string>',
subtitles: true,
subtitlesSource: '<string>',
lipSyncMode: '<string>',
activeSpeakerDetectionEnabled: true,
voiceCloningSettings: {},
translationTimeSkips: [{}]
})
};
fetch('https://api.voicecheap.ai/v1/projects/{projectId}/dub', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.voicecheap.ai/v1/projects/{projectId}/dub",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'targetLanguage' => '<string>',
'translatedSrt' => '<string>',
'webhookUrl' => '<string>',
'keepBackgroundMusic' => true,
'keepOriginalVoice' => true,
'originalVoiceVolume' => 123,
'voiceMode' => '<string>',
'voiceId' => '<string>',
'voiceIsolatorOption' => '<string>',
'subtitles' => true,
'subtitlesSource' => '<string>',
'lipSyncMode' => '<string>',
'activeSpeakerDetectionEnabled' => true,
'voiceCloningSettings' => [
],
'translationTimeSkips' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.voicecheap.ai/v1/projects/{projectId}/dub"
payload := strings.NewReader("{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.voicecheap.ai/v1/projects/{projectId}/dub")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.voicecheap.ai/v1/projects/{projectId}/dub")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"projectId": "<string>",
"workId": "<string>",
"estimatedDuration": 123
}Tłumaczenie i dubbing
Dubbing projektu
Dubbing już transkrybowanego projektu na podstawie własnego przetłumaczonego SRT
Dubbing projektu
curl --request POST \
--url https://api.voicecheap.ai/v1/projects/{projectId}/dub \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"targetLanguage": "<string>",
"translatedSrt": "<string>",
"webhookUrl": "<string>",
"keepBackgroundMusic": true,
"keepOriginalVoice": true,
"originalVoiceVolume": 123,
"voiceMode": "<string>",
"voiceId": "<string>",
"voiceIsolatorOption": "<string>",
"subtitles": true,
"subtitlesSource": "<string>",
"lipSyncMode": "<string>",
"activeSpeakerDetectionEnabled": true,
"voiceCloningSettings": {},
"translationTimeSkips": [
{}
]
}
'import requests
url = "https://api.voicecheap.ai/v1/projects/{projectId}/dub"
payload = {
"targetLanguage": "<string>",
"translatedSrt": "<string>",
"webhookUrl": "<string>",
"keepBackgroundMusic": True,
"keepOriginalVoice": True,
"originalVoiceVolume": 123,
"voiceMode": "<string>",
"voiceId": "<string>",
"voiceIsolatorOption": "<string>",
"subtitles": True,
"subtitlesSource": "<string>",
"lipSyncMode": "<string>",
"activeSpeakerDetectionEnabled": True,
"voiceCloningSettings": {},
"translationTimeSkips": [{}]
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
targetLanguage: '<string>',
translatedSrt: '<string>',
webhookUrl: '<string>',
keepBackgroundMusic: true,
keepOriginalVoice: true,
originalVoiceVolume: 123,
voiceMode: '<string>',
voiceId: '<string>',
voiceIsolatorOption: '<string>',
subtitles: true,
subtitlesSource: '<string>',
lipSyncMode: '<string>',
activeSpeakerDetectionEnabled: true,
voiceCloningSettings: {},
translationTimeSkips: [{}]
})
};
fetch('https://api.voicecheap.ai/v1/projects/{projectId}/dub', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.voicecheap.ai/v1/projects/{projectId}/dub",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'targetLanguage' => '<string>',
'translatedSrt' => '<string>',
'webhookUrl' => '<string>',
'keepBackgroundMusic' => true,
'keepOriginalVoice' => true,
'originalVoiceVolume' => 123,
'voiceMode' => '<string>',
'voiceId' => '<string>',
'voiceIsolatorOption' => '<string>',
'subtitles' => true,
'subtitlesSource' => '<string>',
'lipSyncMode' => '<string>',
'activeSpeakerDetectionEnabled' => true,
'voiceCloningSettings' => [
],
'translationTimeSkips' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.voicecheap.ai/v1/projects/{projectId}/dub"
payload := strings.NewReader("{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.voicecheap.ai/v1/projects/{projectId}/dub")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.voicecheap.ai/v1/projects/{projectId}/dub")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"targetLanguage\": \"<string>\",\n \"translatedSrt\": \"<string>\",\n \"webhookUrl\": \"<string>\",\n \"keepBackgroundMusic\": true,\n \"keepOriginalVoice\": true,\n \"originalVoiceVolume\": 123,\n \"voiceMode\": \"<string>\",\n \"voiceId\": \"<string>\",\n \"voiceIsolatorOption\": \"<string>\",\n \"subtitles\": true,\n \"subtitlesSource\": \"<string>\",\n \"lipSyncMode\": \"<string>\",\n \"activeSpeakerDetectionEnabled\": true,\n \"voiceCloningSettings\": {},\n \"translationTimeSkips\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"projectId": "<string>",
"workId": "<string>",
"estimatedDuration": 123
}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 albo nasłuchuj Webhooki.Wymagania wstępne
- Projekt musi istnieć, a jego transkrypcja musi być ukończona: utwórz go przez Utwórz projekt (sama transkrypcja) albo Rozpocznij tłumaczenie 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 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 zwracaCONCURRENT_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
string
wymagane
Twój klucz API VoiceCheap. Pobierz go z app.voicecheap.ai/page-api.
Parametry ścieżki
string
wymagane
Identyfikator projektu zwracany przez Utwórz projekt lub Rozpocznij tłumaczenie.
Parametry treści
string
wymagane
Język
translatedSrt, małymi literami, z tej samej listy co Rozpocznij tłumaczenie. Jeśli projekt nie ma jeszcze pracy dla tego języka, zostanie ona utworzona, a język dodany do projektu.string
wymagane
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.
string
Endpoint https, który od tej chwili odbiera zdarzenia webhook tego projektu i zastępuje endpoint skonfigurowany na koncie.Domyślnie: Endpoint już zapisany w projekcie, a następnie endpoint webhook konta.
boolean
Zachowaj oryginalne tło audio (muzyka, otoczenie) pod wygenerowanymi głosami.Domyślnie:
trueboolean
Zachowaj cicho oryginalnego mówcę pod wygenerowanym głosem.Domyślnie:
falsenumber
Głośność oryginalnego głosu od
1 do 70, gdy keepOriginalVoice jest włączone.Domyślnie: 30string
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: cloningstring
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.string
Tryb izolacji głosu, gdy
keepBackgroundMusic jest włączone: studio albo realistic.Domyślnie: studioboolean
Wypal napisy w wideo wynikowym. Wymaga projektu wideo.Domyślnie:
falsestring
Tekst napisów, gdy
subtitles jest włączone: translated (Twój SRT) albo original (transkrypcja źródłowa).Domyślnie: translatedstring
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. Wymaga projektu wideo.Domyślnie: pomiń pole, aby nie uruchamiać synchronizacji ust.boolean
Włącz wykrywanie aktywnego mówcy dla żądanej synchronizacji ust.Domyślnie:
falseobject
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.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.Odpowiedź
boolean
wymagane
Zawsze
true dla udanych żądań.string
wymagane
Czytelne potwierdzenie.
string
wymagane
Projekt, który jest dubbingowany.
string
wymagane
Praca tłumaczenia użyta dla
targetLanguage. Odpowiada workId w endpointach statusu, szczegółów i transkrypcji.number
wymagane
Przybliżony szacunek przetwarzania w minutach: pięć minut przetwarzania na każdą rozpoczętą minutę materiału źródłowego.
Response
{
"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ływutranslation, gdy tylko zaczyna się dubbing, więc Pobierz status tłumaczenia ś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 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. Każdy segment mafinalSpeedFactor, 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:POST /v1/projectsz materiałem,targetLanguagei jawnymoriginalLanguage(sama transkrypcja).- Odpytuj
GET /v1/translate/{projectId}/status, ażtranscriptionStatusbędziesuccess, albo poczekaj na webhookproject.created. POST /v1/projects/{projectId}/transcriptz{ "source": "original", "outputFormat": "srt" }i przetłumacz cue, zachowując numerację i kody czasu.POST /v1/projects/{projectId}/dubz przetłumaczonym SRT.- Odpytuj endpoint statusu, aż
statusbędziesuccess, albo poczekaj naproject.translation.completed. - Pobierz
translatedVideoUrl(albolipSync.videoUrl, jeśli zażądano synchronizacji ust). DELETE /v1/translate/{projectId}, gdy wyniki są już zapisane po Twojej stronie.
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"
}'
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;
}
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']
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 |
TRANSLATED_SRT_UNMATCHED_CUES, TRANSLATED_SRT_MISSING_SEGMENTS) zwracają endpoint statusu i webhook niepowodzenia, a nie to żądanie.Czy ta strona była pomocna?

