# SadTalker

Анимируйте лица с помощью аудио, чтобы создавать реалистичные видеоролики с говорящей головой.

{% hint style="success" %}
Все примеры можно запустить на GPU-серверах, арендуемых через [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Аренда на CLORE.AI

1. Посетите [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Фильтровать по типу GPU, объёму видеопамяти и цене
3. Выберите **По требованию** (фиксированная ставка) или **Spot** (цена заявки)
4. Настройте ваш заказ:
   * Выберите Docker-образ
   * Укажите порты (TCP для SSH, HTTP для веб-интерфейсов)
   * При необходимости добавьте переменные окружения
   * Введите команду запуска
5. Выберите способ оплаты: **CLORE**, **BTC**, или **USDT/USDC**
6. Создайте заказ и дождитесь развертывания

### Доступ к вашему серверу

* Найдите данные для подключения в **Мои заказы**
* Веб-интерфейсы: используйте URL HTTP-порта
* SSH: `ssh -p <port> root@<proxy-address>`

## Что такое SadTalker?

SadTalker генерирует говорящие видео:

* Синхронизация губ с любым аудио
* Естественные движения головы
* Работает с одним изображением
* Контроль выражения лица

## Требования

| Режим            | VRAM | Рекомендуется |
| ---------------- | ---- | ------------- |
| Базовый          | 4 ГБ | RTX 3060      |
| Высокое качество | 6 ГБ | RTX 3080      |
| Полное лицо      | 8 ГБ | RTX 4080      |

## Быстрое развертывание

**Docker-образ:**

```
pytorch/pytorch:2.5.1-cuda12.4-cudnn9-devel
```

**Порты:**

```
22/tcp
7860/http
```

**Команда:**

```bash
cd /workspace && \
git clone https://github.com/OpenTalker/SadTalker.git && \
cd SadTalker && \
pip install -r requirements.txt && \
bash scripts/download_models.sh && \
python app.py
```

## Доступ к вашему сервису

После развертывания найдите ваш `http_pub` URL в **Мои заказы**:

1. Перейдите на **Мои заказы** страницу
2. Кликните по вашему заказу
3. Найдите `http_pub` URL (например, `abc123.clorecloud.net`)

Используйте `https://YOUR_HTTP_PUB_URL` вместо `localhost` в примерах ниже.

## Установка

```bash
git clone https://github.com/OpenTalker/SadTalker.git
cd SadTalker

pip install torch torchvision torchaudio
pip install -r requirements.txt

# Загрузить предобученные модели
bash scripts/download_models.sh
```

## Базовое использование

### Командная строка

```bash
python inference.py \
    --driven_audio audio.wav \
    --source_image face.jpg \
    --result_dir ./results \
    --enhancer gfpgan
```

### Python API

```python
from src.facerender.animate import AnimateFromCoeff
from src.generate_batch import get_data
from src.generate_facerender_batch import get_facerender_data
import torch

class SadTalker:
    def __init__(self):
        self.device = "cuda"
        # Инициализация моделей...

    def generate(self, source_image, driven_audio, **kwargs):
        # Обработка аудио и изображения
        # Генерация анимации
        # Возврат пути к видео
        pass

# Пример использования
sadtalker = SadTalker()
video_path = sadtalker.generate(
    source_image="face.jpg",
    driven_audio="speech.wav"
)
```

## С улучшением лица

```bash

# Использование GFPGAN для улучшения лица
python inference.py \
    --driven_audio audio.wav \
    --source_image face.jpg \
    --enhancer gfpgan \
    --result_dir ./results

# Использование Real-ESRGAN для всего изображения
python inference.py \
    --driven_audio audio.wav \
    --source_image face.jpg \
    --enhancer realesrgan \
    --result_dir ./results
```

## Параметры

```bash
python inference.py \
    --driven_audio audio.wav \
    --source_image face.jpg \
    --pose_style 0 \           # 0-46 стили движений головы
    --expression_scale 1.0 \   # Интенсивность выражения
    --still \                  # Минимальные движения головы
    --preprocess crop \        # crop, resize, full
    --size 256 \               # Размер выхода
    --enhancer gfpgan
```

### Стили поз

| Диапазон | Эффект                 |
| -------- | ---------------------- |
| 0-5      | Тонкие движения        |
| 6-20     | Обычные движения       |
| 21-46    | Выразительные движения |

## Пакетная обработка

```python
import os
import subprocess

def generate_talking_video(image_path, audio_path, output_dir):
    cmd = [
        "python", "inference.py",
        "--driven_audio", audio_path,
        "--source_image", image_path,
        "--result_dir", output_dir,
        "--enhancer", "gfpgan"
    ]
    subprocess.run(cmd, check=True)

# Обработка нескольких изображений с одним и тем же аудио
images = ["person1.jpg", "person2.jpg", "person3.jpg"]
audio = "speech.wav"

for i, img in enumerate(images):
    output = f"./results/video_{i}"
    generate_talking_video(img, audio, output)
```

## Интерфейс Gradio

```python
import gradio as gr
import subprocess
import tempfile
import os

def generate_video(image, audio, pose_style, expression_scale, enhancer):
    with tempfile.TemporaryDirectory() as tmpdir:
        # Сохранить входные данные
        image_path = os.path.join(tmpdir, "input.jpg")
        audio_path = os.path.join(tmpdir, "audio.wav")
        image.save(image_path)

        # Сохранить аудио
        import soundfile as sf
        sf.write(audio_path, audio[1], audio[0])

        # Генерация
        cmd = [
            "python", "inference.py",
            "--driven_audio", audio_path,
            "--source_image", image_path,
            "--result_dir", tmpdir,
            "--pose_style", str(pose_style),
            "--expression_scale", str(expression_scale),
            "--enhancer", enhancer
        ]
        subprocess.run(cmd, check=True)

        # Найти выходное видео
        for f in os.listdir(tmpdir):
            if f.endswith(".mp4"):
                return os.path.join(tmpdir, f)

    return None

demo = gr.Interface(
    fn=generate_video,
    inputs=[
        gr.Image(type="pil", label="Исходное лицо"),
        gr.Audio(label="Ведущее аудио"),
        gr.Slider(0, 46, value=0, step=1, label="Стиль позы"),
        gr.Slider(0.5, 1.5, value=1.0, step=0.1, label="Масштаб выражения"),
        gr.Dropdown(["gfpgan", "realesrgan", "none"], value="gfpgan", label="Улучшение")
    ],
    outputs=gr.Video(label="Сгенерированное видео"),
    title="SadTalker - Генерация говорящей головы"
)

demo.launch(server_name="0.0.0.0", server_port=7860)
```

## API-сервер

```python
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import FileResponse
import tempfile
import subprocess
import os

app = FastAPI()

@app.post("/generate")
async def generate(
    image: UploadFile = File(...),
    audio: UploadFile = File(...),
    pose_style: int = 0,
    expression_scale: float = 1.0
):
    with tempfile.TemporaryDirectory() as tmpdir:
        # Сохранить загруженные файлы
        image_path = os.path.join(tmpdir, "input.jpg")
        audio_path = os.path.join(tmpdir, "audio.wav")

        with open(image_path, "wb") as f:
            f.write(await image.read())
        with open(audio_path, "wb") as f:
            f.write(await audio.read())

        # Генерация
        cmd = [
            "python", "inference.py",
            "--driven_audio", audio_path,
            "--source_image", image_path,
            "--result_dir", tmpdir,
            "--pose_style", str(pose_style),
            "--expression_scale", str(expression_scale),
            "--enhancer", "gfpgan"
        ]
        subprocess.run(cmd, check=True)

        # Вернуть видео
        for f in os.listdir(tmpdir):
            if f.endswith(".mp4"):
                return FileResponse(os.path.join(tmpdir, f), media_type="video/mp4")

# Запуск: uvicorn server:app --host 0.0.0.0 --port 8000
```

## Текст-в-речь + SadTalker

Полный конвейер:

```python
import subprocess
from TTS.api import TTS

def text_to_talking_video(text, image_path, output_path):
    # Сгенерировать речь с помощью TTS
    tts = TTS("tts_models/en/ljspeech/tacotron2-DDC")
    audio_path = "temp_audio.wav"
    tts.tts_to_file(text=text, file_path=audio_path)

    # Сгенерировать говорящие видео
    cmd = [
        "python", "inference.py",
        "--driven_audio", audio_path,
        "--source_image", image_path,
        "--result_dir", output_path,
        "--enhancer", "gfpgan"
    ]
    subprocess.run(cmd, check=True)

# Пример использования
text_to_talking_video(
    "Hello, welcome to our presentation. Today we'll discuss AI.",
    "presenter.jpg",
    "./output"
)
```

## Контроль выражения

```python

# Минимальное выражение (стиль ведущего новостей)
cmd = [
    "python", "inference.py",
    "--driven_audio", "audio.wav",
    "--source_image", "face.jpg",
    "--expression_scale", "0.5",
    "--still"  # Уменьшает движение головы
]

# Выразительное (анимированный персонаж)
cmd = [
    "python", "inference.py",
    "--driven_audio", "audio.wav",
    "--source_image", "face.jpg",
    "--expression_scale", "1.5",
    "--pose_style", "30"
]
```

## Настройки качества

| Параметр              | Скорость        | Качество |
| --------------------- | --------------- | -------- |
| Без улучшителя, 256px | Быстро          | Базовый  |
| GFPGAN, 256px         | Средне          | Хорошо   |
| GFPGAN, 512px         | Медленно        | Лучше    |
| RealESRGAN, 512px     | Самый медленный | Лучшее   |

## Опции предобработки

```bash

# Crop - сосредоточиться на лице (рекомендуется)
--preprocess crop

# Resize - изменить размер всего изображения
--preprocess resize

# Full - использовать всё изображение
--preprocess full
```

## Устранение неполадок

### Лицо не обнаружено

* Используйте четкое фронтальное фото лица
* Хорошее освещение
* Избегайте перекрытий (очки, волосы)

### Проблемы с синхронизацией аудио

* Используйте WAV-файлы 16 кГц
* Избегайте фоновой музыки
* Только четкая речь

### Рывистое движение

* Немного увеличьте expression\_scale
* Попробуйте другой pose\_style
* Используйте более длинное аудио

### Недостаточно памяти

* Уменьшите размер выходного файла
* Отключите улучшитель
* Используйте предобработку crop

## Производительность

| Разрешение     | GPU      | Время (видео 10 с) |
| -------------- | -------- | ------------------ |
| 256px          | RTX 3060 | \~30с              |
| 256px          | RTX 4090 | \~15с              |
| 512px + GFPGAN | RTX 4090 | \~45с              |

## Оценка стоимости

Типичные тарифы на маркетплейсе CLORE.AI (по состоянию на 2024):

| GPU       | Почасовая ставка | Дневная ставка | Сессия 4 часа |
| --------- | ---------------- | -------------- | ------------- |
| RTX 3060  | \~$0.03          | \~$0.70        | \~$0.12       |
| RTX 3090  | \~$0.06          | \~$1.50        | \~$0.25       |
| RTX 4090  | \~$0.10          | \~$2.30        | \~$0.40       |
| A100 40GB | \~$0.17          | \~$4.00        | \~$0.70       |
| A100 80GB | \~$0.25          | \~$6.00        | \~$1.00       |

*Цены варьируются в зависимости от провайдера и спроса. Проверьте* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *для текущих тарифов.*

**Экономьте деньги:**

* Используйте **Spot** рынок для гибких рабочих нагрузок (часто на 30–50% дешевле)
* Платите с помощью **CLORE** токенов
* Сравнивайте цены разных провайдеров

## Следующие шаги

* [Wav2Lip](https://docs.clore.ai/guides/guides_v2-ru/govoryashie-golovy/wav2lip) - Альтернативная синхронизация губ
* [Bark TTS](https://docs.clore.ai/guides/guides_v2-ru/audio-i-golos/bark-tts) - Сгенерировать речь
* [XTTS](https://docs.clore.ai/guides/guides_v2-ru/audio-i-golos/xtts-coqui) - Клонирование голоса + TTS
