AI-система AI-дубляжа и lip-sync для кино

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1566 услуг
AI-система AI-дубляжа и lip-sync для кино
Сложный
~2-4 недели
Часто задаваемые вопросы

Направления AI-разработки

Этапы разработки AI-решения

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1120
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    588
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    855

Разработка AI-системы кинодубляжа с синхронизацией губ

Lip-sync дубляж — наиболее технически сложная задача аудиолокализации: синтезированная речь должна совпадать с артикуляцией актёра по форме рта, темпу и эмоции. Применяется в кино, сериалах, рекламе, обучающих видео с «говорящей головой».

Компоненты системы

Wav2Lip — нейросеть для синтеза синхронизированных движений губ:

import subprocess
import os

class LipSyncDubber:
    def __init__(self, wav2lip_path: str = "./Wav2Lip"):
        self.wav2lip_path = wav2lip_path

    def sync_lips_to_audio(
        self,
        video_path: str,
        audio_path: str,
        output_path: str,
        quality: str = "high"  # high = Wav2Lip_GAN, standard = Wav2Lip
    ) -> None:
        checkpoint = "wav2lip_gan.pth" if quality == "high" else "wav2lip.pth"

        subprocess.run([
            "python", f"{self.wav2lip_path}/inference.py",
            "--checkpoint_path", f"{self.wav2lip_path}/checkpoints/{checkpoint}",
            "--face", video_path,
            "--audio", audio_path,
            "--outfile", output_path,
            "--resize_factor", "1",
            "--pads", "0 10 0 0",  # отступы вокруг лица
            "--nosmooth"
        ], check=True)

LatentSync (2024) — более современная модель, лучше справляется с профилями и экстремальными ракурсами:

from latentsync.pipeline import LatentSyncPipeline

pipeline = LatentSyncPipeline.from_pretrained("ByteDance/LatentSync-1.5")

def latentsync_dub(video_path: str, audio_path: str, output_path: str):
    result = pipeline(
        video=video_path,
        audio=audio_path,
        num_inference_steps=20,
        guidance_scale=2.5,
    )
    result.video[0].save(output_path)

Полный pipeline кинодубляжа

import asyncio
from pathlib import Path

class FilmDubbingPipeline:
    def __init__(self):
        self.stt = WhisperModel("large-v3", device="cuda")
        self.translator = GPT4Translator()
        self.tts = ElevenLabsTTS()          # лучшая эмоциональная TTS
        self.lip_sync = LipSyncDubber()
        self.voice_cloner = VoiceCloner()  # клонирование голоса актёра

    async def dub_scene(
        self,
        video_path: str,
        target_language: str,
        output_path: str,
        clone_voices: bool = True
    ) -> dict:
        work_dir = Path(f"/tmp/dub_{hash(video_path)}")
        work_dir.mkdir(exist_ok=True)

        # 1. Диаризация — кто говорит когда
        diarization = await self.diarize(video_path)

        # 2. STT для каждого говорящего отдельно
        segments = await self.transcribe_segments(video_path, diarization)

        # 3. Перевод с учётом длительностей
        translated = await self.translate_for_lipsync(segments, target_language)

        # 4. Клонирование голосов (если нужно)
        voice_profiles = {}
        if clone_voices:
            for speaker_id in set(s["speaker"] for s in diarization):
                speaker_audio = self.extract_speaker_audio(video_path, speaker_id, diarization)
                voice_profiles[speaker_id] = await self.voice_cloner.create_profile(speaker_audio)

        # 5. TTS каждого сегмента с нужным голосом
        dubbed_segments = []
        for seg in translated:
            voice_id = voice_profiles.get(seg["speaker"], "default")
            audio = await self.tts.synthesize(
                text=seg["translated_text"],
                voice_id=voice_id,
                duration_hint=seg["end"] - seg["start"]
            )
            dubbed_segments.append({**seg, "audio": audio})

        # 6. Сборка трека дубляжа
        dubbing_track = self.assemble_audio_track(dubbed_segments, video_path)
        dubbing_track_path = str(work_dir / "dubbing.wav")
        with open(dubbing_track_path, "wb") as f:
            f.write(dubbing_track)

        # 7. Lip-sync
        lipsync_output = str(work_dir / "lipsync.mp4")
        self.lip_sync.sync_lips_to_audio(video_path, dubbing_track_path, lipsync_output)

        # 8. Финальная сборка с субтитрами
        await self.finalize(lipsync_output, dubbed_segments, output_path)

        return {
            "output": output_path,
            "segments_count": len(translated),
            "speakers": len(voice_profiles)
        }

Обработка нескольких говорящих

class MultiSpeakerVoiceCloner:
    """ElevenLabs Voice Cloning API для клонирования голосов персонажей"""

    async def create_character_voices(
        self,
        video_path: str,
        diarization: list[dict]
    ) -> dict[str, str]:
        """Создаём отдельный клонированный голос для каждого персонажа"""
        import elevenlabs
        from elevenlabs.client import ElevenLabs

        client = ElevenLabs()
        voice_ids = {}

        for speaker_id in set(s["speaker"] for s in diarization):
            # Извлекаем чистые фрагменты речи этого актёра (мин. 30 сек)
            speaker_segments = [s for s in diarization if s["speaker"] == speaker_id]
            audio_samples = self.extract_clean_segments(video_path, speaker_segments, min_duration=30)

            if not audio_samples:
                continue

            voice = client.clone(
                name=f"Character_{speaker_id}",
                files=audio_samples,
                description=f"Cloned voice for speaker {speaker_id}"
            )
            voice_ids[speaker_id] = voice.voice_id

        return voice_ids

Метрики качества lip-sync

Метрика Описание Хорошее значение
LSE-D (Lip Sync Error Distance) Расстояние между аудио и видео < 7.0
LSE-C (Lip Sync Error Confidence) Уверенность детектора > 7.5
FID (Frechet Inception Distance) Визуальное качество лица < 15
SSIM Структурное сходство кадров > 0.85
# Оценка LSE метрик через SyncNet
def evaluate_lipsync_quality(video_path: str) -> dict:
    result = subprocess.run([
        "python", "SyncNet/run_pipeline.py",
        "--videofile", video_path,
        "--reference", "synchronization"
    ], capture_output=True, text=True)

    # Парсим LSE-D и LSE-C из stdout
    lines = result.stdout.split("\n")
    metrics = {}
    for line in lines:
        if "LSE-D" in line:
            metrics["lse_d"] = float(line.split(":")[-1].strip())
        if "LSE-C" in line:
            metrics["lse_c"] = float(line.split(":")[-1].strip())
    return metrics

Ограничения текущих моделей

Wav2Lip и LatentSync работают хуже при:

  • Профильный ракурс (> 45°): артикуляция неточная
  • Частичное перекрытие лица (руки, микрофон): маска теряется
  • Быстрые движения головы: размытие и артефакты
  • Несколько лиц в кадре: нужна предварительная детекция и track

Для профессионального кинодубляжа Wav2Lip используется как основа, а результат дополнительно проходит ручную коррекцию в ключевых сценах.

Инфраструктурные требования

Обработка 1 минуты видео:

  • Wav2Lip: ~8 мин на RTX 3090 (1080p), ~2 мин на A100
  • LatentSync: ~15 мин на RTX 3090 (медленнее, выше качество)
  • GPU VRAM: минимум 8 GB, рекомендуется 24 GB

Сроки: proof-of-concept pipeline для одного видео — 1–2 недели. Production-система с очередью, веб-интерфейсом, мультиспикер поддержкой — 2–3 месяца.