Projekt synchronisieren
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
}Übersetzung und Synchronisation
Projekt synchronisieren
Ein bereits transkribiertes Projekt mit Ihrem eigenen übersetzten SRT synchronisieren
Projekt synchronisieren
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
}Projekt synchronisieren
Erzeugen Sie die Stimmen und mischen Sie die Ausgabe eines bestehenden Projekts aus einem übersetzten SRT, das Sie bereitstellen. VoiceCheap übersetzt auf diesem Endpunkt nichts: keine Übersetzungs-Engine, keine SmartSync-Umformulierung, kein Glossar. Jeder Cue wird wörtlich auf dem passenden Segment des Projekttranskripts gesprochen und dann mit dem ursprünglichen Hintergrund, den Untertiteln und dem optionalen Lippensync gemischt, genau wie bei einer normalen Übersetzung. Nutzen Sie ihn, wenn die Übersetzung woanders entsteht (ein menschlicher Übersetzer, Ihre eigenen Werkzeuge, ein Automatisierungsablauf) und Sie VoiceCheap nur für die Stimmenerzeugung brauchen. Der Lauf ist asynchron: fragen Sie Übersetzungsstatus abrufen ab oder hören Sie auf die Webhooks.Voraussetzungen
- Das Projekt muss existieren und seine Transkription muss abgeschlossen sein: erstellen Sie es mit Projekt erstellen (nur Transkription) oder Übersetzung starten und warten Sie auf
transcriptionStatus: "success". - Ihr SRT muss das Projekttranskript abdecken: jedes Transkriptsegment braucht mindestens einen Cue, und jeder Cue muss auf einem Segment liegen. Exportieren Sie das Transkript mit Projekttranskript exportieren und übersetzen Sie es Cue für Cue, damit die Zeitcodes erhalten bleiben.
- Die Anfrage wird wie eine Übersetzung desselben Mediums abgerechnet, mit derselben Credit-Prüfung. Lippensync-Modi verbrauchen wie üblich zusätzliche Credits.
Gleichzeitige Ausführungsgrenze
Projekterstellung, Übersetzung und Vertonung prüfen alle das Limit Ihres Kontos für aktive Übersetzungen (höchstens 10, möglicherweise weniger). Nur laufende Übersetzungs- oder Vertonungsvorgänge belegen Plätze; Projekte mit reiner Transkription nicht. Bei Erreichen des Limits gibt die APICONCURRENT_TRANSLATION_LIMIT_REACHED (HTTP 429) zurück. Das geltende Limit steht in details.limit.
Ein zweiter Lauf für dasselbe Projekt und dieselbe Zielsprache wird ebenfalls abgelehnt, solange einer läuft (TRANSLATION_ALREADY_IN_PROGRESS, HTTP 409).
Anfrage
Dieser Endpunkt akzeptiert einen JSON-Body (Content-Type: application/json). Boolesche und numerische Optionen werden als JSON-Werte gesendet, nicht als Zeichenketten.
Header
string
erforderlich
Ihr VoiceCheap API-Schlüssel. Erhalten Sie einen von app.voicecheap.ai/page-api.
Pfadparameter
string
erforderlich
Die Projektkennung, die Projekt erstellen oder Übersetzung starten zurückgibt.
Body-Parameter
string
erforderlich
Die Sprache von
translatedSrt, in Kleinbuchstaben, aus derselben Liste wie Übersetzung starten. Wenn das Projekt noch keine Arbeit für diese Sprache hat, wird eine erstellt und die Sprache dem Projekt hinzugefügt.string
erforderlich
Der endgültige SRT-Inhalt in der Zielsprache (Cue-Nummer, Zeitzeile, Text). Maximal 1.000.000 Zeichen. Cues werden den Transkriptsegmenten über Zeitstempel zugeordnet: ein Cue, der innerhalb von 50 ms nach einem Segmentstart beginnt, wird diesem Segment zugewiesen, sonst dem Segment mit der größten Überlappung. Mehrere Cues auf einem Segment werden mit einem Leerzeichen verbunden. Zeitpunkt, Sprecher und Reihenfolge jedes gesprochenen Segments kommen immer aus dem Projekttranskript; Ihre Zeitcodes dienen nur der Zuordnung.
string
Ein https-Endpunkt, der ab jetzt die Webhook-Ereignisse für dieses Projekt empfängt und den auf dem Konto konfigurierten Endpunkt überschreibt.Standard: Der bereits im Projekt gespeicherte Endpunkt, danach der Webhook-Endpunkt des Kontos.
boolean
Die ursprüngliche Hintergrundaufnahme (Musik, Ambiente) unter den erzeugten Stimmen behalten.Standard:
trueboolean
Die ursprüngliche Stimme leise unter der erzeugten Stimme behalten.Standard:
falsenumber
Lautstärke der Originalstimme von
1 bis 70, wenn keepOriginalVoice aktiviert ist.Standard: 30string
Stimmstrategie:
cloning (die Sprecher des Projekts klonen) oder custom (eine Katalogstimme oder Ihre gespeicherte benutzerdefinierte Stimme verwenden).Standard: cloningstring
Erforderlich, wenn
voiceMode custom ist. Verwenden Sie eine ID aus dubbing_voices_list: eine Katalogstimme oder eine vom authentifizierten
Konto gespeicherte benutzerdefinierte Stimme. Die Teamabrechnung gewährt keinen Zugriff auf die gespeicherten Stimmen anderer Mitglieder.string
Sprachisolierung, wenn
keepBackgroundMusic aktiviert ist: studio oder realistic.Standard: studioboolean
Untertitel in das Ausgabevideo einbrennen. Erfordert ein Videoprojekt.Standard:
falsestring
Untertiteltext, wenn
subtitles aktiviert ist: translated (Ihr SRT) oder original (das Quelltranskript).Standard: translatedstring
Lippensync starten, sobald die Synchronisation fertig ist:
standard, pro oder studio. Plan-, Dauer- und Credit-Regeln sind dieselben wie bei Übersetzung starten. Erfordert ein Videoprojekt.Standard: Feld weglassen, um den Lippensync zu überspringen.boolean
Aktive-Sprecher-Erkennung für den angeforderten Lippensync-Lauf aktivieren.Standard:
falseobject
Feineinstellung des Stimmklonens als JSON-Objekt mit
stability und similarity zwischen 0 und 1. Nur mit voiceMode: "cloning". Hinweise zu jedem Wert stehen bei Übersetzung starten.array
Zeitbereiche der Quelle, die in der Originalsprache bleiben, als
[{ "startTime": 10.2, "endTime": 12.8 }]. Erfordert ein Videoprojekt und keepBackgroundMusic: true, kann nicht mit keepOriginalVoice kombiniert werden und darf Transkriptsegmente nicht überlappen.Antwort
boolean
erforderlich
Bei erfolgreichen Anfragen immer
true.string
erforderlich
Eine lesbare Bestätigung.
string
erforderlich
Das Projekt, das synchronisiert wird.
string
erforderlich
Die Übersetzungsarbeit für
targetLanguage. Sie entspricht workId in den Endpunkten für Status, Details und Transkript.number
erforderlich
Grobe Verarbeitungsschätzung in Minuten: fünf Minuten Verarbeitung je angefangener Minute des Quellmediums.
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
}
Den Lauf verfolgen
Das Projekt wechselt in den Workflowtranslation, sobald die Synchronisation startet. Übersetzungsstatus abrufen folgt daher dem neuen Lauf: status geht von processing zu success (mit translatedVideoUrl und translatedAudioUrl) oder failed (mit error). Die Webhooks project.translation.completed und project.translation.failed werden mit derselben targetLanguage gesendet. In Projektdetails abrufen meldet die übersetzte Version settings.dubbingMode: "dub-only" und settings.smartSync: false.
Ausrichtungsfehler treten auf, nachdem die POST-Anfrage angenommen wurde. Der Status-Endpunkt gibt status: "failed" mit error.code und error.message zurück; der Webhook project.translation.failed enthält denselben Code und dieselbe Nachricht. TRANSLATED_SRT_UNMATCHED_CUES nennt die nicht zugeordneten Cue-Nummern in der Nachricht, TRANSLATED_SRT_MISSING_SEGMENTS die Segmentindizes ohne Cue. Diese asynchronen Antworten enthalten kein strukturiertes details-Feld. Korrigieren Sie die SRT-Datei und rufen Sie den Endpunkt erneut auf: Die fehlgeschlagene Version bleibt im Projektverlauf, und eine neue wird erstellt.
Tempo prüfen
Exportieren Sie das übersetzte Transkript als JSON mit Projekttranskript exportieren. Jedes Segment trägtfinalSpeedFactor, das Verhältnis zwischen der erzeugten Sprache und dem Segmentfenster. Kürzen Sie die Cues, die ungefähr über 1.3 liegen, und starten Sie die Synchronisation erneut mit dem überarbeiteten SRT.
Beispielablauf
Eine typische Automatisierung (zum Beispiel ein n8n- oder Make-Szenario) verkettet die Endpunkte so:POST /v1/projectsmit dem Medium,targetLanguageund einer explizitenoriginalLanguage(nur Transkription).- Fragen Sie
GET /v1/translate/{projectId}/statusab, bistranscriptionStatussuccessist, oder warten Sie auf den Webhookproject.created. POST /v1/projects/{projectId}/transcriptmit{ "source": "original", "outputFormat": "srt" }und übersetzen Sie die Cues, wobei Nummerierung und Zeitcodes erhalten bleiben.POST /v1/projects/{projectId}/dubmit dem übersetzten SRT.- Fragen Sie den Status-Endpunkt ab, bis
statussuccessist, oder warten Sie aufproject.translation.completed. - Laden Sie
translatedVideoUrlherunter (oderlipSync.videoUrl, wenn Lippensync angefordert wurde). DELETE /v1/translate/{projectId}, sobald die Ausgaben bei Ihnen gespeichert sind.
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']
Fehler
| Status | Code | Beschreibung |
|---|---|---|
| 400 | VALIDATION_ERROR | Ein Body-Feld fehlt oder ist ungültig (details listet jedes Feld) |
| 400 | INVALID_TRANSLATED_SRT | translatedSrt enthält keine gültigen SRT-Cues |
| 400 | INVALID_BOOLEAN_VALUE | Eine boolesche Option wurde nicht als JSON-Boolean gesendet |
| 400 | INVALID_NUMBER_VALUE | Eine numerische Option wurde nicht als JSON-Zahl gesendet |
| 400 | DURATION_DETECTION_FAILED | Die gespeicherte Mediendauer des Projekts ist nicht verfügbar |
| 400 | VOICE_ID_REQUIRED | Der Modus für benutzerdefinierte Stimmen wurde ohne eine Stimmen-ID ausgewählt |
| 400 | VOICE_ID_NOT_ALLOWED_WITH_CLONING | Eine Stimmen-ID wurde mit Stimmklonen kombiniert |
| 400 | VOICE_CLONING_SETTINGS_NOT_ALLOWED | Klon-Einstellungen wurden mit dem Modus für benutzerdefinierte Stimmen kombiniert |
| 400 | TRANSLATION_TIME_SKIP_CONFLICT | Zeitübersprünge stehen im Konflikt mit einer anderen Audio-Option |
| 400 | TRANSLATION_TIME_SKIP_REQUIRES_BACKGROUND | Zeitübersprünge erfordern Hintergrundaudio |
| 400 | TRANSLATION_TIME_SKIP_OUT_OF_RANGE | Ein Zeitübersprung reicht über die Mediendauer hinaus |
| 400 | SUBTITLES_NOT_AVAILABLE_FOR_AUDIO | Eingebrannte Untertitel wurden für Audio-Input angefordert |
| 400 | LIPSYNC_NOT_AVAILABLE_FOR_AUDIO | Lippensynchronisation wurde für Audio-Input angefordert |
| 400 | TRANSLATION_TIME_SKIP_NOT_AVAILABLE_FOR_AUDIO | Zeitübersprünge wurden für Audio-Input angefordert |
| 400 | LIPSYNC_VIDEO_TOO_LONG | Lippensynchronisation wurde für Medien angefordert, die länger als die unterstützte Dauer sind |
| 401 | MISSING_API_KEY | API-Schlüssel ist erforderlich |
| 401 | INVALID_API_KEY_FORMAT | API-Schlüssel muss mit vc_ beginnen |
| 401 | INVALID_API_KEY | Der bereitgestellte API-Schlüssel ist ungültig |
| 403 | SUBSCRIPTION_REQUIRED | API-Zugriff erfordert einen Starter-Plan oder höher |
| 403 | FORBIDDEN | Sie haben keine Berechtigung, auf das Projekt zuzugreifen |
| 403 | INSUFFICIENT_CREDITS | Nicht genügend Credits, um dieses Projekt zu synchronisieren |
| 403 | CUSTOM_VOICE_ACCESS_DENIED | Die ausgewählte Stimme ist weder eine Katalogstimme noch eine vom authentifizierten Konto gespeicherte benutzerdefinierte Stimme. |
| 403 | LIPSYNC_MODE_ACCESS_DENIED | Der Premium-Lippensynchronisationsmodus ist im aktuellen Plan nicht verfügbar |
| 404 | PROJECT_NOT_FOUND | Das Projekt existiert nicht |
| 409 | DUB_ONLY_REQUIRES_TRANSCRIPTION | Die Projekttranskription wird noch verarbeitet oder ist fehlgeschlagen |
| 409 | TRANSLATION_ALREADY_IN_PROGRESS | Für diese Sprache läuft im Projekt bereits eine Synchronisation |
| 429 | RATE_LIMIT_EXCEEDED | Zu viele Anfragen (Limit: 10 Anfragen pro Minute) |
| 429 | CONCURRENT_TRANSLATION_LIMIT_REACHED | Kontolimit für gleichzeitige Übersetzungen erreicht; siehe details.limit |
| 500 | INTERNAL_ERROR | Unerwarteter Serverfehler |
TRANSLATED_SRT_UNMATCHED_CUES, TRANSLATED_SRT_MISSING_SEGMENTS), liefert der Status-Endpunkt und der fehlgeschlagene Webhook, nicht diese Anfrage.War diese Seite hilfreich?

