# Wan2.1 Video

Генерируйте видеоролики высокого качества с помощью моделей 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](/guides/guides_v2-ru/generaciya-video/hunyuan-video.md) - Альтернатива T2V
* [OpenSora](/guides/guides_v2-ru/generaciya-video/opensora.md) - Альтернатива Open Sora
* [Stable Video Diffusion](/guides/guides_v2-ru/generaciya-video/stable-video-diffusion.md) - Анимация изображений
* [Интерполяция RIFE](/guides/guides_v2-ru/obrabotka-video/rife-interpolation.md) - Вставка кадров


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-ru/generaciya-video/wan-video.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
