# Видео Wan2.1

Генерируйте видеоролики высокого качества с помощью моделей Wan2.1 от Alibaba для преобразования текста в видео и изображения в видео на GPU CLORE.AI.

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

## Почему Wan2.1?

* **Высокое качество** - Современная генерация видео
* **Несколько режимов** - Текст в видео, изображение в видео
* **Разные размеры** - От 1,3B до 14B параметров
* **Длинные видео** - До 81 кадра
* **Открытые веса** - Лицензия Apache 2.0

## Варианты моделей

| Модель          | Параметры | VRAM  | Разрешение | Кадры |
| --------------- | --------- | ----- | ---------- | ----- |
| Wan2.1-T2V-1.3B | 1.3B      | 8GB   | 480p       | 81    |
| Wan2.1-T2V-14B  | 14B       | 24 ГБ | 720p       | 81    |
| Wan2.1-I2V-14B  | 14B       | 24 ГБ | 720p       | 81    |

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

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

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

**Порты:**

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

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

```bash
pip install diffusers transformers accelerate gradio && \
python -c "
import gradio as gr
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video

pipe = WanPipeline.from_pretrained('alibaba-pai/Wan2.1-T2V-1.3B', torch_dtype=torch.float16)
pipe.to('cuda')
pipe.enable_model_cpu_offload()

def generate(prompt, steps, frames, seed):
    generator = torch.Generator('cuda').manual_seed(seed) if seed > 0 else None
    output = pipe(prompt, num_frames=frames, num_inference_steps=steps, generator=generator)
    export_to_video(output.frames[0], 'output.mp4', fps=16)
    return 'output.mp4'

gr.Interface(
    fn=generate,
    inputs=[
        gr.Textbox(label='Prompt'),
        gr.Slider(20, 100, value=50, label='Steps'),
        gr.Slider(16, 81, value=49, step=8, label='Frames'),
        gr.Number(value=-1, label='Seed')
    ],
    outputs=gr.Video(),
    title='Wan2.1 - Text to Video'
).launch(server_name='0.0.0.0', server_port=7860)
"
```

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

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

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

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

## Требования к аппаратному обеспечению

| Модель   | Минимальная GPU | Рекомендуется | Оптимально |
| -------- | --------------- | ------------- | ---------- |
| 1.3B T2V | RTX 3070 8GB    | RTX 3090 24GB | RTX 4090   |
| 14B T2V  | RTX 4090 24GB   | A100 40GB     | A100 80GB  |
| 14B I2V  | RTX 4090 24GB   | A100 40GB     | A100 80GB  |

## Установка

```bash
pip install diffusers transformers accelerate torch
```

## Текст в видео

### Базовое использование (1.3B)

```python
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video

pipe = WanPipeline.from_pretrained(
    "alibaba-pai/Wan2.1-T2V-1.3B",
    torch_dtype=torch.float16
)
pipe.to("cuda")
pipe.enable_model_cpu_offload()

prompt = "Кот играет с мячиком в солнечном саду"

output = pipe(
    prompt=prompt,
    num_frames=49,
    num_inference_steps=50,
    guidance_scale=7.0
)

export_to_video(output.frames[0], "cat_video.mp4", fps=16)
```

### Высокое качество (14B)

```python
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video

pipe = WanPipeline.from_pretrained(
    "alibaba-pai/Wan2.1-T2V-14B",
    torch_dtype=torch.float16
)
pipe.to("cuda")
pipe.enable_model_cpu_offload()
pipe.enable_vae_tiling()

prompt = "Кинематографический кадр: дракон летит над горами на закате, 4K, детализированно"

output = pipe(
    prompt=prompt,
    negative_prompt="размыто, низкое качество, искажено",
    num_frames=81,
    height=720,
    width=1280,
    num_inference_steps=50,
    guidance_scale=7.0
)

export_to_video(output.frames[0], "dragon.mp4", fps=24)
```

## Изображение в видео

### Анимировать изображение

```python
import torch
from diffusers import WanI2VPipeline
from diffusers.utils import load_image, export_to_video

pipe = WanI2VPipeline.from_pretrained(
    "alibaba-pai/Wan2.1-I2V-14B",
    torch_dtype=torch.float16
)
pipe.to("cuda")
pipe.enable_model_cpu_offload()

# Загрузить входное изображение
image = load_image("input.jpg")

prompt = "Человек на изображении начинает идти вперёд"

output = pipe(
    prompt=prompt,
    image=image,
    num_frames=49,
    num_inference_steps=50,
    guidance_scale=7.0
)

export_to_video(output.frames[0], "animated.mp4", fps=16)
```

## Изображение в видео с Wan2.1-I2V-14B

{% hint style="info" %}
Wan2.1-I2V-14B анимирует статичное изображение с помощью текстового промпта для управления движением. Требуется **24GB видеопамяти** (рекомендуется RTX 4090 или A100 40GB).
{% endhint %}

### Данные модели

| Свойство                | Значение                           |
| ----------------------- | ---------------------------------- |
| ID модели               | `Wan-AI/Wan2.1-I2V-14B-480P`       |
| Параметры               | 14 миллиардов                      |
| Требуемая VRAM          | **24 ГБ**                          |
| Максимальное разрешение | 480p (854×480) или 720p (1280×720) |
| Макс. кадров            | 81                                 |
| Лицензия                | Apache 2.0                         |

### Требования к аппаратному обеспечению

| GPU       | VRAM  | Статус            |
| --------- | ----- | ----------------- |
| RTX 4090  | 24 ГБ | ✅ Рекомендуется   |
| RTX 3090  | 24 ГБ | ✅ Поддерживается  |
| A100 40GB | 40GB  | ✅ Оптимально      |
| A100 80GB | 80GB  | ✅ Лучшее качество |
| RTX 3080  | 10GB  | ❌ Недостаточно    |

### Быстрый скрипт CLI

Сохранить как `generate_i2v.py` и запустите:

```bash
python generate_i2v.py --model Wan-AI/Wan2.1-I2V-14B-480P --image input.jpg --prompt "камера медленно отдаляется"
```

### generate\_i2v.py — полный скрипт

```python
#!/usr/bin/env python3
"""
CLI-скрипт Wan2.1 для преобразования изображения в видео.
Использование: python generate_i2v.py --model Wan-AI/Wan2.1-I2V-14B-480P \
           --image input.jpg --prompt "камера медленно отдаляется"
"""

import argparse
import os
import sys
import torch
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
from PIL import Image


def parse_args():
    parser = argparse.ArgumentParser(description="Генератор Wan2.1 Image-to-Video")
    parser.add_argument(
        "--model",
        type=str,
        default="Wan-AI/Wan2.1-I2V-14B-480P",
        help="ID модели на Hugging Face (по умолчанию: Wan-AI/Wan2.1-I2V-14B-480P)",
    )
    parser.add_argument(
        "--image",
        type=str,
        required=True,
        help="Путь к входному изображению (JPEG или PNG)",
    )
    parser.add_argument(
        "--prompt",
        type=str,
        required=True,
        help='Текстовый промпт, описывающий желаемое движение (например, "камера медленно отдаляется")',
    )
    parser.add_argument(
        "--negative-prompt",
        type=str,
        default="размыто, низкое качество, искажено, дерганое движение, артефакты",
        help="Негативный промпт, чтобы избежать нежелательных артефактов",
    )
    parser.add_argument(
        "--frames",
        type=int,
        default=49,
        help="Количество кадров видео для генерации (по умолчанию: 49, макс.: 81)",
    )
    parser.add_argument(
        "--steps",
        type=int,
        default=50,
        help="Количество шагов диффузии (по умолчанию: 50)",
    )
    parser.add_argument(
        "--guidance",
        type=float,
        default=7.0,
        help="Масштаб classifier-free guidance (по умолчанию: 7.0)",
    )
    parser.add_argument(
        "--seed",
        type=int,
        default=-1,
        help="Случайное зерно для воспроизводимости (-1 = случайное)",
    )
    parser.add_argument(
        "--fps",
        type=int,
        default=16,
        help="FPS выходного видео (по умолчанию: 16)",
    )
    parser.add_argument(
        "--output",
        type=str,
        default="output_i2v.mp4",
        help="Путь к файлу выходного видео (по умолчанию: output_i2v.mp4)",
    )
    parser.add_argument(
        "--height",
        type=int,
        default=480,
        help="Высота выходного видео в пикселях (по умолчанию: 480)",
    )
    parser.add_argument(
        "--width",
        type=int,
        default=854,
        help="Ширина выходного видео в пикселях (по умолчанию: 854)",
    )
    parser.add_argument(
        "--cpu-offload",
        action="store_true",
        default=True,
        help="Включить выгрузку модели на CPU для экономии видеопамяти (по умолчанию: True)",
    )
    parser.add_argument(
        "--vae-tiling",
        action="store_true",
        default=False,
        help="Включить tiling VAE для высоких разрешений",
    )
    return parser.parse_args()


def load_and_resize_image(image_path: str, width: int, height: int) -> Image.Image:
    """Загрузить изображение по пути и изменить размер до целевых размеров."""
    if not os.path.exists(image_path):
        print(f"[ERROR] Изображение не найдено: {image_path}", file=sys.stderr)
        sys.exit(1)

    img = Image.open(image_path).convert("RGB")
    original_size = img.size
    img = img.resize((width, height), Image.LANCZOS)
    print(f"[INFO] Загружено изображение: {image_path} ({original_size[0]}x{original_size[1]}) → изменён размер до {width}x{height}")
    return img


def load_pipeline(model_id: str, cpu_offload: bool, vae_tiling: bool):
    """Загрузить конвейер Wan I2V с оптимизациями памяти."""
    print(f"[INFO] Загрузка модели: {model_id}")
    print(f"[INFO] CUDA доступна: {torch.cuda.is_available()}")
    if torch.cuda.is_available():
        vram_gb = torch.cuda.get_device_properties(0).total_memory / 1e9
        print(f"[INFO] GPU: {torch.cuda.get_device_name(0)} ({vram_gb:.1f} GB VRAM)")
        if vram_gb < 23:
            print("[WARN] Обнаружено менее 24GB VRAM — включите --cpu-offload или используйте модель 1.3B")

    pipe = WanImageToVideoPipeline.from_pretrained(
        model_id,
        torch_dtype=torch.float16,
    )

    if cpu_offload:
        print("[INFO] Включена выгрузка модели на CPU")
        pipe.enable_model_cpu_offload()
    else:
        pipe.to("cuda")

    if vae_tiling:
        print("[INFO] Включён VAE tiling для генерации в высоком разрешении")
        pipe.enable_vae_tiling()

    return pipe


def generate_video(pipe, args) -> None:
    """Запустить I2V конвейер и сохранить выходное видео."""
    image = load_and_resize_image(args.image, args.width, args.height)

    generator = None
    if args.seed >= 0:
        generator = torch.Generator("cuda").manual_seed(args.seed)
        print(f"[INFO] Используемое зерно: {args.seed}")
    else:
        print("[INFO] Используется случайное зерно")

    print(f"[INFO] Генерация {args.frames} кадров при {args.width}x{args.height}")
    print(f"[INFO] Шаги: {args.steps} | Guidance: {args.guidance} | FPS: {args.fps}")
    print(f"[INFO] Промпт: {args.prompt}")

    output = pipe(
        prompt=args.prompt,
        negative_prompt=args.negative_prompt,
        image=image,
        num_frames=args.frames,
        height=args.height,
        width=args.width,
        num_inference_steps=args.steps,
        guidance_scale=args.guidance,
        generator=generator,
    )

    export_to_video(output.frames[0], args.output, fps=args.fps)
    print(f"[INFO] Видео сохранено в: {os.path.abspath(args.output)}")
    duration = args.frames / args.fps
    print(f"[INFO] Длительность: {duration:.1f}s при {args.fps}fps ({args.frames} кадров)")


def main():
    args = parse_args()

    if not torch.cuda.is_available():
        print("[ERROR] CUDA GPU не найден. Wan2.1-I2V-14B требует GPU с поддержкой CUDA.", file=sys.stderr)
        sys.exit(1)

    pipe = load_pipeline(args.model, args.cpu_offload, args.vae_tiling)
    generate_video(pipe, args)
    print("[DONE] Генерация из изображения в видео завершена!")


if __name__ == "__main__":
    main()
```

### Расширенный I2V конвейер (Python API)

```python
import torch
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
from PIL import Image

# ── Загрузка конвейера ──────────────────────────────────────────────────────────────
pipe = WanImageToVideoPipeline.from_pretrained(
    "Wan-AI/Wan2.1-I2V-14B-480P",
    torch_dtype=torch.float16,
)
pipe.enable_model_cpu_offload()   # держит VRAM ниже 24GB
pipe.enable_vae_tiling()          # опционально: помогает для 720p

# ── Загрузить и подготовить входное изображение ─────────────────────────────────────
image = load_image("input.jpg").resize((854, 480))

# ── Генерация ───────────────────────────────────────────────────────────────────
prompt = "камера медленно отдаляется, открывая весь пейзаж"
negative_prompt = "размыто, низкое качество, искажено, мерцание, артефакты"

generator = torch.Generator("cuda").manual_seed(42)

output = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    image=image,
    num_frames=49,          # ~3 секунды при 16fps
    height=480,
    width=854,
    num_inference_steps=50,
    guidance_scale=7.5,
    generator=generator,
)

export_to_video(output.frames[0], "i2v_output.mp4", fps=16)
print("Сохранено: i2v_output.mp4")
```

### Советы по промптам для I2V

| Цель                 | Пример промпта                                              |
| -------------------- | ----------------------------------------------------------- |
| Движение камеры      | `"камера медленно отдаляется от объекта"`                   |
| Параллакс эффект     | `"тонкое параллаксное движение, смещение глубины резкости"` |
| Анимация персонажа   | `"фигура поворачивает голову и улыбается"`                  |
| Анимация природы     | `"листья шелестят в лёгком ветерке, свет меняется"`         |
| Абстрактное движение | `"цвета закручиваются и смешиваются, плавное движение"`     |

### Советы по памяти для I2V (GPU 24GB)

```python
# Обязательно на GPU 24GB
pipe.enable_model_cpu_offload()

# Опционально: уменьшает пиковое использование VRAM примерно на 10%
pipe.enable_vae_tiling()
pipe.enable_vae_slicing()

# Очищать между запусками
import gc
gc.collect()
torch.cuda.empty_cache()
```

## Примеры промптов

### Природа и пейзажи

```python
prompts = [
    "Таймлапс облаков над горными пиками, драматическое освещение",
    "Океанские волны, разбивающиеся о скалы, замедленная съёмка, кинематографично",
    "Северное сияние, танцующее в ночном небе, насыщенные цвета",
    "Осенний лес с падающими листьями, спокойная атмосфера"
]
```

### Животные и персонажи

```python
prompts = [
    "Золотистый ретривер, бегущий по полю с цветами",
    "Бабочка, вылезающая из куколки, макросъёмка",
    "Самурай, вытягивающий меч, драматическое освещение",
    "Робот, гуляющий по улицам футуристического города"
]
```

### Абстрактное и художественное

```python
prompts = [
    "Яркие краски, закручивающиеся в воде, абстрактное искусство",
    "Геометрические формы трансформируются и морфируются, неоновые цвета",
    "Чернильные капли, распространяющиеся в молоке, макрофотография"
]
```

## Расширенные настройки

### Качество vs Скорость

```python
# Быстрый предпросмотр
output = pipe(
    prompt=prompt,
    num_frames=17,
    num_inference_steps=25,
    guidance_scale=5.0
)

# Сбалансировано
output = pipe(
    prompt=prompt,
    num_frames=49,
    num_inference_steps=50,
    guidance_scale=7.0
)

# Максимальное качество
output = pipe(
    prompt=prompt,
    num_frames=81,
    num_inference_steps=100,
    guidance_scale=7.5
)
```

### Варианты разрешения

```python
# 480p (модель 1.3B)
output = pipe(prompt, height=480, width=854, num_frames=49)

# 720p (модель 14B)
output = pipe(prompt, height=720, width=1280, num_frames=49)

# 1080p (модель 14B, большая VRAM)
output = pipe(prompt, height=1080, width=1920, num_frames=33)
```

## Пакетная генерация

```python
import os
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video

pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B", torch_dtype=torch.float16)
pipe.to("cuda")
pipe.enable_model_cpu_offload()

prompts = [
    "Ракета, стартующая в космос",
    "Рыбы, плавающие в коралловом рифе",
    "Дождь, падающий на городскую улицу ночью"
]

output_dir = "./videos"
os.makedirs(output_dir, exist_ok=True)

for i, prompt in enumerate(prompts):
    print(f"Генерируется {i+1}/{len(prompts)}: {prompt[:40]}...")

    output = pipe(
        prompt=prompt,
        num_frames=49,
        num_inference_steps=50
    )

    export_to_video(output.frames[0], f"{output_dir}/video_{i:03d}.mp4", fps=16)
    torch.cuda.empty_cache()
```

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

```python
import gradio as gr
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video
import tempfile

pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B", torch_dtype=torch.float16)
pipe.to("cuda")
pipe.enable_model_cpu_offload()

def generate_video(prompt, negative_prompt, frames, steps, guidance, seed):
    generator = torch.Generator("cuda").manual_seed(seed) if seed > 0 else None

    output = pipe(
        prompt=prompt,
        negative_prompt=negative_prompt,
        num_frames=frames,
        num_inference_steps=steps,
        guidance_scale=guidance,
        generator=generator
    )

    with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f:
        export_to_video(output.frames[0], f.name, fps=16)
        return f.name

demo = gr.Interface(
    fn=generate_video,
    inputs=[
        gr.Textbox(label="Prompt", lines=2),
        gr.Textbox(label="Negative Prompt", value="размыто, низкое качество"),
        gr.Slider(17, 81, value=49, step=8, label="Frames"),
        gr.Slider(20, 100, value=50, step=5, label="Steps"),
        gr.Slider(3, 12, value=7, step=0.5, label="Guidance"),
        gr.Number(value=-1, label="Seed")
    ],
    outputs=gr.Video(label="Сгенерированное видео"),
    title="Wan2.1 - Генерация из текста в видео",
    description="Генерируйте видео по текстовым промптам. Запуск на CLORE.AI."
)

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

## Оптимизация памяти

```python
# Включить все оптимизации
pipe.enable_model_cpu_offload()
pipe.enable_vae_tiling()
pipe.enable_vae_slicing()

# Для очень низкой видеопамяти
pipe.enable_sequential_cpu_offload()

# Очищать кэш между генерациями
torch.cuda.empty_cache()
```

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

| Модель | Разрешение | Кадры | GPU       | Время     |
| ------ | ---------- | ----- | --------- | --------- |
| 1.3B   | 480p       | 49    | RTX 4090  | \~2 мин   |
| 1.3B   | 480p       | 49    | A100 40GB | \~1.5 мин |
| 14B    | 720p       | 49    | A100 40GB | \~5 мин   |
| 14B    | 720p       | 81    | A100 80GB | \~8 мин   |

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

Типичные расценки на маркетплейсе CLORE.AI:

| GPU           | Почасовая ставка | \~49-кадровые видео/час      |
| ------------- | ---------------- | ---------------------------- |
| RTX 3090 24GB | \~$0.06          | \~20 (1.3B)                  |
| RTX 4090 24GB | \~$0.10          | \~30 (1.3B)                  |
| A100 40GB     | \~$0.17          | \~40 (1.3B) / \~12 (14B)     |
| A100 80GB     | \~$0.25          | \~8 (14B высокое разрешение) |

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

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

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

```python
# Используйте меньшую модель
pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B")

# Включить все оптимизации
pipe.enable_model_cpu_offload()
pipe.enable_vae_tiling()

# Уменьшить количество кадров
output = pipe(prompt, num_frames=17)

# Уменьшить разрешение
output = pipe(prompt, height=480, width=854)
```

### Плохое качество

* Увеличьте шаги (75-100)
* Пишите более подробные промпты
* Используйте негативные промпты
* Попробуйте модель 14B для лучшего качества

### Видео слишком короткое

* Увеличьте `num_frames` (макс. 81)
* Используйте интерполяцию RIFE для вставки кадров
* Объединяйте несколько генераций

### Артефакты / Мерцание

* Увеличьте масштаб guidance
* Используйте фиксированное зерно для согласованности
* Постобработка стабилизацией видео

## Wan2.1 vs Другие

| Функция       | Wan2.1     | Hunyuan  | SVD      | CogVideoX |
| ------------- | ---------- | -------- | -------- | --------- |
| Качество      | Отлично    | Отлично  | Хорошо   | Отлично   |
| Скорость      | Быстро     | Средне   | Быстро   | Медленно  |
| Макс. кадров  | 81         | 129      | 25       | 49        |
| Разрешение    | 720p       | 720p     | 576p     | 720p      |
| Поддержка I2V | Да         | Да       | Да       | Да        |
| Лицензия      | Apache 2.0 | Откройте | Откройте | Откройте  |

**Используйте Wan2.1 когда:**

* Требуется генерация видео с открытым исходным кодом
* Нужна быстрая скорость генерации
* Требуется лицензия Apache 2.0
* Требуется сбалансированное качество/скорость

## Дальнейшие шаги

* [Hunyuan Video](https://docs.clore.ai/guides/guides_v2-ru/generaciya-video/hunyuan-video) - Альтернатива T2V
* [OpenSora](https://docs.clore.ai/guides/guides_v2-ru/generaciya-video/opensora) - Альтернатива Open Sora
* [Stable Video Diffusion](https://docs.clore.ai/guides/guides_v2-ru/generaciya-video/stable-video-diffusion) - Анимация изображений
* [Интерполяция RIFE](https://docs.clore.ai/guides/guides_v2-ru/obrabotka-video/rife-interpolation) - Вставка кадров
