# 格温皮肤变身视频 · 完整工作流程与 Prompt 手册

> 目标：用 6 张英雄联盟格温皮肤官方原画，生成一条 2K 横版"连续变身"视频，
> 配国服中文配音 + 官方主题曲，BGM 在台词时自动压低。

---

## 一、整体流程总览

```
① 素材获取（官方完整原画）
        ↓
② （可选）AI 高清化 / 扩图 —— 本项目最终跳过
        ↓
③ MiniMax-H3 首尾帧生成 5 段变形视频（2K）
        ↓
④ ffmpeg 无缝拼接（每段结尾=下一段开头）
        ↓
⑤ 中文配音：bilibili 完整配音视频 + 本地语音识别定位台词
        ↓
⑥ BGM：官方格温主题曲（或 MiniMax 定制纯音乐）
        ↓
⑦ ffmpeg 混音合成（BGM 压低 + 台词 + 淡入淡出）
```

### 工作流图

```mermaid
flowchart TD
    A["① 素材获取：官方完整原画<br/>ddragon splash（1215×717）"] --> B["② 素材检查：是否裁剪/黑边"]
    B --> C{"需要 AI 超分 / 扩图？"}
    C -- "否（优先官方原画）" --> D
    C -- "是" --> C1["阿里云万相 imageedit<br/>超分 / expand 扩图"]
    C1 --> D["③ MiniMax-H3 首尾帧<br/>5 段 × 5 秒 × 2K"]
    D --> E["④ 轮询任务状态<br/>下载 5 段片段"]
    E --> F["⑤ ffmpeg 无缝拼接<br/>concat -c copy"]
    F --> G["⑥ 中文配音提取<br/>yt-dlp 下载合集 + faster-whisper 定位台词"]
    G --> H["⑦ BGM 准备<br/>格温主题曲 或 MiniMax 定制纯音乐"]
    H --> I["⑧ ffmpeg 混音<br/>BGM 压低 + 台词时间点 + 淡入淡出"]
    I --> J["🎬 最终 2K 变身视频"]
```

---

## 二、素材获取

### 2.1 不要用裁剪图

lol-skin.weblog.vc 的 loading 图（`/img/wallpaper/loading/Gwen_X.webp`，308×560）
是**裁剪过的窄竖版**，左右画面缺失，放大后观感"两边是黑的"。

### 2.2 官方完整原画（推荐）

Riot 官方数据源（Data Dragon），横版完整原画：

```
https://ddragon.leagueoflegends.com/cdn/img/champion/splash/Gwen_{皮肤号}.jpg
```

分辨率 1215×717（16:9）。皮肤编号（以格温为例）：

| 编号 | 皮肤 |
|---|---|
| 0 | 基础格温（无皮肤） |
| 1 | 太空律动 |
| 11 | 咖啡甜心 |
| 20 | 斗魂觉醒 |
| 30 | 女帝 |
| 39 | 青蛙雨衣 |

> 查询某英雄全部皮肤编号：
> `https://ddragon.leagueoflegends.com/cdn/{版本}/data/zh_CN/champion/{英雄}.json` → `skins[].num`

个别图源还有 4K 版（如 weblog 的 `/img/wallpaper/splash/Gwen_0.jpg`，4096×2420），
生成视频时用最高清版本即可。

---

## 三、AI 超分 / 扩图（本项目最终未采用，留作参考）

### 3.1 阿里云万相（可用于超分/扩图）

模型：`wanx2.1-imageedit`，接口：`POST /api/v1/services/aigc/image2image/image-synthesis`

**超分（super_resolution）**：

```json
{
  "model": "wanx2.1-imageedit",
  "input": {
    "function": "super_resolution",
    "prompt": "图像超分。",
    "base_image_url": "<图片URL或base64>"
  },
  "parameters": { "upscale_factor": 4, "n": 1, "watermark": false }
}
```

**扩图（expand）**：

```json
{
  "model": "wanx2.1-imageedit",
  "input": {
    "function": "expand",
    "prompt": "将画面左右两侧自然延展补全，延续原画中圣霭、光影与场景氛围，保持格温原画的画风、色调与人物位置，两侧延展出完整的背景场景，画面无缝衔接，构图完整，不要出现黑边、空白或拉伸变形。",
    "base_image_url": "<图片URL或base64>"
  },
  "parameters": { "left_scale": 2.0, "right_scale": 2.0, "n": 1, "watermark": false }
}
```

> 经验：`left_scale=1.5` 表示该侧向外扩 0.5 倍原宽（新宽 = 原宽 × (1 + (L-1) + (R-1))）。
> 竖图扩到 16:9 需要左右各扩约 110%，接近单侧上限，需二次扩图或生成后裁切。

### 3.2 MiniMax 图像（无专门扩图接口）

MiniMax `image-01` 只有文生图 / 图生图（`subject_reference` 人物参考），
用它"扩图"会重绘整张图，**难以自然保真**，实测效果不佳。

```
POST https://api.minimaxi.com/v1/image_generation
{
  "model": "image-01",
  "prompt": "扩图：保持画面中央的格温形象与造型完全一致，将画布向左右两侧自然延展…",
  "subject_reference": [{ "type": "character", "image_file": "<图片URL或base64>" }],
  "aspect_ratio": "16:9"
}
```

**结论：优先找官方完整原画，比任何 AI 扩图都自然。**

---

## 四、视频生成（核心：MiniMax-H3 首尾帧）

### 4.1 接口

```
创建任务：POST https://api.minimaxi.com/v2/video_generation
查询任务：GET  https://api.minimaxi.com/v2/query/video_generation/{task_id}
```

请求体：

```json
{
  "model": "MiniMax-H3",
  "content": [
    { "type": "text", "text": "<视频提示词>" },
    { "type": "image_url", "image_url": { "url": "<首帧图>" }, "role": "first_frame" },
    { "type": "image_url", "image_url": { "url": "<尾帧图>" }, "role": "last_frame" }
  ],
  "duration": 5,
  "resolution": "2K"
}
```

- 图片支持公网 URL 或 `data:image/jpeg;base64,...`
- 时长 4–15 秒（整数）；分辨率 768P / 2K；输出比例跟随输入图（自适应）
- 成功返回 `task_id`；轮询 `task.status`，`succeeded` 后取 `task.content.url`

### 4.2 提示词（踩坑后的最终版）

**视频提示词（每个皮肤对一段，内容相同）：**

```
全程画面持续缓慢运动，任何时刻都不能静止：从第一帧开始镜头缓慢向后退、视野逐渐变宽，
画面左右两侧的场景持续向外延展补全（自然的扩图效果），背景圣霭与光雾不断流淌；
与此同时格温的造型全程渐进变化——发型、发色、服装、武器从第一张图均匀过渡为第二张图，
每一刻都能看到明显的变形进展，最后平稳落定为第二张图的完整画面，无黑边，无突然跳变。
```

**关键经验（很重要）：**

1. 不要写"最终画面完整定格为第二张图的模样"这类强收尾指令，模型会**前面静止、最后跳变**。
2. 必须明确"**全程持续运动、每一刻都在变、禁止突然跳变**"。
3. 变化主体要写清是**角色本体**（发型/发色/服装/武器/场景细节）连续变形，
   而不是叠化、溶解、雾气光效覆盖（那会被判定为"换图"）。
4. 首尾帧之间人物姿态相近时，模型倾向"静→跳"；把运动要求前置可显著改善。
5. 每段结尾帧 = 下一段首帧，5 段拼接后是天然无缝的连续变身。

### 4.3 价格

| 分辨率 | 单价 |
|---|---|
| 768P | 0.50 元/秒 |
| 2K | 0.80 元/秒 |

5 段 × 5 秒 × 2K = 20 元。

---

## 五、无缝拼接（ffmpeg）

因为每段结尾精确等于下一段开头，直接 concat（无需转场特效）：

```bash
ffmpeg -y -f concat -safe 0 -i list.txt -c copy joined.mp4
```

`list.txt`：

```
file 'Gwen_0__Gwen_1.mp4'
file 'Gwen_1__Gwen_11.mp4'
file 'Gwen_11__Gwen_20.mp4'
file 'Gwen_20__Gwen_30.mp4'
file 'Gwen_30__Gwen_39.mp4'
```

---

## 六、国服中文配音提取

### 6.1 素材来源

- 布锅锅联盟宇宙语音站（voice.buguoguo.cn）有官方单句，但**需要关注 B 站解锁**，音频 CDN 也有路径限制 → 不推荐自动化。
- 方案：bilibili 完整配音合集视频（如 `BV12U4y1a7Ge` 格温全语音），**音频可免登录下载**：

```bash
yt-dlp -f 'bestaudio/best' -o gwen_zh_vo.m4a 'https://www.bilibili.com/video/BV12U4y1a7Ge/'
```

### 6.2 语音识别定位台词（faster-whisper）

```python
from faster_whisper import WhisperModel
model = WhisperModel("small", device="cpu", compute_type="int8")
segments, _ = model.transcribe("gwen_zh_vo.m4a", language="zh",
                               word_timestamps=True, vad_filter=True)
```

在带词级时间戳的结果里搜索目标台词，得到起止秒数；个别识别不准的片段，
先裁出小段再用 `initial_prompt`（写入目标台词文本）重新识别。

### 6.3 截取 + 剪静音

```bash
ffmpeg -ss 466.8 -t 2.9 -i gwen_zh_vo.m4a -ar 44100 -ac 2 line1_raw.wav
ffmpeg -i line1_raw.wav -af "silenceremove=start_periods=1:start_threshold=-30dB,areverse,silenceremove=start_periods=1:start_threshold=-30dB,areverse" line1.wav
```

### 6.4 本项目使用的 5 句台词（含时间点）

| # | 台词 | 源音频位置 |
|---|---|---|
| 1 | 还是很难相信，我可以自己活动起来。 | 466.8–469.6s |
| 2 | 比起眼下，我忍受过更加糟糕的事情。 | 422.3–425.4s |
| 3 | 多么诡异又神奇的世界，我得用心维护，让它一直保持这样。 | 310.8–320.3s |
| 4 | 佛耶戈，她并没有忘记你，我也没有原谅你。 | 51.2–58.1s |
| 5 | 当下才是最美。 | 329.1–330.6s |

> 注：旧版本有"佛耶戈，你根本不配被爱"一句，现行国服配音已改为上面这版。

---

## 七、BGM

### 7.1 官方格温主题曲（本项目最终采用）

QQ 音乐分享链接解析流程：

1. 短链 302 → `songid=305539861`；
2. 歌曲信息：`POST https://u.y.qq.com/cgi-bin/musicu.fcg`（`music.pf_song_detail_svr`）→ 拿 `songmid`；
3. 播放地址：同接口 `vkey.GetVkeyServer` → `sip[0] + purl` 即可下载。

```
歌曲：Gwen Champion Theme（专辑《Echoes of Light - 光明回音》）
```

### 7.2 MiniMax 定制纯音乐（备选，1 元/首）

```
POST https://api.minimaxi.com/v1/music_generation
{
  "model": "music-3.0",
  "prompt": "史诗电影级游戏CG配乐，英雄联盟风格，魔法变身主题：神秘空灵的弦乐开场，逐渐展开，中段加入强劲的电子节拍和交响乐，高潮气势恢宏、能量充沛，节奏感强、非常带感，适合皮肤展示和变身视频，纯音乐无歌词。",
  "is_instrumental": true,
  "output_format": "url",
  "audio_setting": { "format": "mp3", "sample_rate": 44100, "bitrate": 128000 }
}
```

---

## 八、混音合成（ffmpeg 一条命令）

输入：视频（无音轨）、BGM、5 条台词 wav。
要点：BGM 裁剪到视频长度 → loudnorm 标准化 → 台词时段压低（duck）→ 台词按时间点延迟 → amix → 限幅 → 44.1kHz → 淡入淡出。

```bash
ffmpeg -y -i video.mp4 -i bgm.mp3 \
  -i line1.wav -i line2.wav -i line3.wav -i line4.wav -i line5.wav \
  -filter_complex \
  "[1:a]atrim=0:26,loudnorm=I=-16:TP=-1.5:LRA=11,volume='if(between(t,0.8,3.50)+between(t,4.1,6.68)+between(t,7.3,16.80)+between(t,17.4,23.81)+between(t,24.5,25.68),0.10,1)':eval=frame[bgm];[2:a]adelay=800|800,volume=1.6[v1];[3:a]adelay=7300|7300,volume=1.6[v2];[4:a]adelay=17400|17400,volume=1.6[v3];[5:a]adelay=4100|4100,volume=1.6[v4];[6:a]adelay=24500|24500,volume=1.7[v5];[bgm][v1][v2][v3][v4][v5]amix=inputs=6:normalize=0,alimiter=limit=0.95,aresample=44100,afade=t=in:st=0:d=0.8,afade=t=out:st=24.37:d=1.5[aout]" \
  -map 0:v -map "[aout]" -c:v copy -c:a aac -b:a 192k -ar 44100 \
  -shortest -movflags +faststart final.mp4
```

各台词的延迟毫秒数（`adelay`）：

| 台词 | 起点 | adelay(ms) |
|---|---|---|
| 1 | 0.8s | 800 |
| 2 | 4.1s | 4100 |
| 3 | 7.3s | 7300 |
| 4 | 17.4s | 17400 |
| 5 | 24.5s | 24500 |

---

## 九、成本参考（本项目实际发生）

| 项目 | 数量 | 费用 |
|---|---|---|
| 阿里云 HappyHorse 图生视频（早期探索） | 30s 1080P | 约 36 元 |
| 阿里云万相 2.7 首尾帧（早期探索） | 65s 1080P | 约 65 元 |
| 阿里云图像编辑（超分+扩图） | 6 张 | 约 0.8 元 |
| MiniMax-H3 首尾帧（正式版） | 20s 2K | 16 元 |
| MiniMax-H3 测试片段 | 5s 2K | 4 元 |
| MiniMax 定制 BGM | 1 首 | 1 元 |

> 正式路线若重来：6 张原画 + 5 段 2K（20s）+ 配音 + 主题曲，约 **20 元**。

---

## 十、环境变量与依赖

```bash
export MINIMAX_API_KEY=sk-api-...        # MiniMax 开放平台
export DASHSCOPE_API_KEY=sk-...          # 阿里云百炼（仅早期方案用）
```

工具：`yt-dlp`（下载配音视频）、`faster-whisper`（台词定位）、`ffmpeg`（拼接/混音）、
`ego-browser`（需要人工解锁的网页场景）。
