1. Аутентификация

Получите персональный ключ в разделе API (требуется аккаунт и подтверждённый email).

Передавайте ключ в каждом запросе:

X-API-Key: dpk_ваш_ключ

Альтернатива: Authorization: Bearer dpk_ваш_ключ

2. Схема работы

  1. POST /api/v1/dub — отправить видео и параметры, получить job id
  2. GET /api/v1/jobs/<id> — опрашивать статус (queued → running → done)
  3. GET /api/v1/jobs/<id>/download — скачать готовый MP4
GET /health — без ключа

3. Запуск дубляжа

POST /api/v1/dub

multipart/form-data — загрузка файла (основной способ):

curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "voice_gender=female" \ -F "voice_age=32" \ -F "video=@/path/to/video.mp4"

Обязательные поля: project_name, source_language, target_language, и video или video_url.

Форматы: MP4, MKV, MOV, AVI, WebM, WAV, MP3, M4A. Максимум 150 МБ.

Ссылка вместо файла (YouTube и др. через yt-dlp на стороне Dpunk):

curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "video_url=https://www.youtube.com/watch?v=VIDEO_ID"

Ответ при успехе: HTTP 202 с полем id — сохраните его для опроса.

4. Опциональные параметры

ПараметрОписание
voice_promptПромпт VoiceDesign для голоса
voice_gendermale | female
voice_ageВозраст голоса (5–90)
voice_design_temperatureКреативность TTS (0–1)
voice_design_by_keyJSON: промпт по полу и возрастной группе
dub_volume_percentГромкость дубляжа, % (по умолчанию 100)
original_audio_ratioДоля оригинала (0–1, по умолчанию 0.3)
video_urlСсылка на медиа (YouTube и др.) вместо файла — скачивается через yt-dlp
cast_voiceОдин встроенный голос: loki / tom_hardy / thor (или Локи / Том Харди / Тор)
cast_modespeakers — три голоса раздаются спикерам по кругу

Плейсхолдеры в voice_prompt: {lang}, {gender_hint}, {age_hint}

5. Клонирование голоса из сэмпла

Короткий аудио-сэмпл (MP3/WAV, до 10 МБ, 3–10 сек) задаёт голос для выбранных возрастных групп. Можно комбинировать: сэмпл для male, VoiceDesign-промпт для female.

Поле multipartОписание
voice_sample_maleФайл сэмпла мужского голоса
voice_sample_femaleФайл сэмпла женского голоса
voice_sample_male_ageschild,teenager,mature,elderly (через запятую)
voice_sample_female_agesТо же для женского пола
voice_sample_male_ref_textТочный текст из мужского сэмпла (рекомендуется)
voice_sample_female_ref_textТочный текст из женского сэмпла
curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "voice_sample_male=@voice_male.wav" \ -F "voice_sample_male_ages=mature,elderly" \ -F "voice_sample_male_ref_text=Hello, this is my reference voice." \ -F "video=@video.mp4"
Через прокси недоступна передача video_path и серверных путей в JSON — только загрузка файлов через multipart.

6. Встроенные cast-голоса

На сервере лежат 3 готовых эталона. Их не нужно загружать файлом — укажите id или имя.

idИмя
lokiЛоки
tom_hardyТом Харди
thorТор
GET /api/v1/cast-voices
curl -H "X-API-Key: dpk_ваш_ключ" \ "https://dpunk.online/api/v1/cast-voices"

Два режима (взаимоисключающие):

  • cast_voice=loki — один голос на весь дубляж
  • cast_mode=speakers — SPEAKER_00→Локи, SPEAKER_01→Том Харди, SPEAKER_02→Тор, …
curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "cast_voice=loki" \ -F "video=@video.mp4"
curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "cast_mode=speakers" \ -F "video=@video.mp4"

Свои voice_sample_* по-прежнему доступны и имеют приоритет на пересекающихся слотах.

7. Silero TTS — готовые русские голоса

Альтернатива Qwen3-TTS для русского дубляжа: фиксированные спикеры Silero v5_ru (быстрее, меньше нагрузка на GPU).

Работает только при target_language = ru. Для других языков параметры silero_* вернут ошибку 400.
ПараметрОписание
silero_speakeraidar, eugene (♂) · baya, kseniya, xenia (♀)
silero_all_replicastrue — один спикер на все реплики (Qwen не используется)
silero_age_groupschild,teenager,mature,elderly — фильтр по возрасту
silero_voicesJSON-массив слотов для разных пол × возраст

Мужские реплики через Silero, женские — Qwen:

curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "silero_speaker=eugene" \ -F "video=@video.mp4"

Все реплики одним голосом:

curl -X POST "https://dpunk.online/api/v1/dub" \ -H "X-API-Key: dpk_ваш_ключ" \ -F "project_name=demo" \ -F "source_language=en" \ -F "target_language=ru" \ -F "silero_speaker=baya" \ -F "silero_all_replicas=true" \ -F "video=@video.mp4"

Можно комбинировать Silero с voice_prompt и voice_sample_* — Silero для выбранных реплик, Qwen для остальных.

8. Статус и список задач

GET /api/v1/jobs/<job_id>

Статусы: queued, running, done, error.

curl -H "X-API-Key: dpk_ваш_ключ" \ "https://dpunk.online/api/v1/jobs/JOB_ID"
GET /api/v1/jobs

Список ваших задач (до 50 последних). Чужие задачи недоступны.

9. Скачивание результата

GET /api/v1/jobs/<job_id>/download

Доступно только при status = done.

curl -H "X-API-Key: dpk_ваш_ключ" \ -o demo_dubbed.mp4 \ "https://dpunk.online/api/v1/jobs/JOB_ID/download"

10. Коды ответов

КодЗначение
200OK — GET, скачивание
202Accepted — задача создана
400Неверные поля; silero_* при target_language ≠ ru
401Неверный или отсутствующий API key
404Задача не найдена (или не ваша)
409Результат ещё не готов
413Файл слишком большой
503GPU занят другой задачей

11. Пример на Python

Полный сценарий: запуск дубляжа с клонированием голоса, ожидание и скачивание MP4.

Подготовка
import time
import requests

BASE = "https://dpunk.online"
HEADERS = {"X-API-Key": "dpk_ваш_ключ"}
Шаг 1 — Запуск (вариант A: VoiceDesign + клон)
with open("video.mp4", "rb") as video, \
     open("voice.wav", "rb") as sample:

    r = requests.post(
        f"{BASE}/api/v1/dub",
        headers=HEADERS,
        data={
            "project_name": "demo",
            "source_language": "en",
            "target_language": "ru",
            "voice_sample_male_ages": "mature,elderly",
            "voice_sample_male_ref_text": "Hello, this is my reference voice.",
            "voice_design_temperature": "0.72",
        },
        files={
            "video": ("video.mp4", video, "video/mp4"),
            "voice_sample_male": ("voice.wav", sample, "audio/wav"),
        },
        timeout=600,
    )

r.raise_for_status()
job_id = r.json()["id"]
print("job:", job_id)
Шаг 1 — вариант B: Silero (только target_language=ru)
with open("video.mp4", "rb") as video:
    r = requests.post(
        f"{BASE}/api/v1/dub",
        headers=HEADERS,
        data={
            "project_name": "demo",
            "source_language": "en",
            "target_language": "ru",
            "silero_speaker": "eugene",
            "silero_all_replicas": "true",
        },
        files={"video": ("video.mp4", video, "video/mp4")},
        timeout=600,
    )

r.raise_for_status()
job_id = r.json()["id"]
print("job:", job_id)
Шаг 1 — вариант C: cast_mode=speakers
with open("video.mp4", "rb") as video:
    r = requests.post(
        f"{BASE}/api/v1/dub",
        headers=HEADERS,
        data={
            "project_name": "demo",
            "source_language": "en",
            "target_language": "ru",
            "cast_mode": "speakers",
        },
        files={"video": ("video.mp4", video, "video/mp4")},
        timeout=600,
    )
r.raise_for_status()
job_id = r.json()["id"]
Шаг 2 — Ожидание завершения
while True:
    st = requests.get(
        f"{BASE}/api/v1/jobs/{job_id}",
        headers=HEADERS,
        timeout=60,
    )
    st.raise_for_status()
    data = st.json()

    print("status:", data["status"])

    if data["status"] == "done":
        break
    if data["status"] == "error":
        raise RuntimeError(data.get("error"))

    time.sleep(60)
Шаг 3 — Скачивание MP4
out = requests.get(
    f"{BASE}/api/v1/jobs/{job_id}/download",
    headers=HEADERS,
    stream=True,
    timeout=600,
)
out.raise_for_status()

with open("demo_dubbed.mp4", "wb") as f:
    for chunk in out.iter_content(chunk_size=1024 * 1024):
        if chunk:
            f.write(chunk)

print("saved: demo_dubbed.mp4")

12. Управление ключами

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

Создать аккаунт