Metadata-Version: 2.4
Name: fible
Version: 0.3.0
Summary: 一句话生成视频 — AI 文案 + 配音 + 素材 + 合成的视频创作 CLI
Author: mx
License: MIT
Requires-Python: >=3.10
Requires-Dist: edge-tts>=6.1.0
Requires-Dist: moviepy>=2.0.0
Requires-Dist: openai>=1.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pywebview>=5.0
Requires-Dist: requests>=2.31.0
Requires-Dist: rich>=13.0.0
Description-Content-Type: text/markdown

# AI 视频创作 CLI

一段文案 → 一个带配音和字幕的视频。全链路本地化，免费开源。

## 管线流程

```
文案.txt → DeepSeek V4 Pro 分镜 → edge-tts 配音 → Pexels 素材匹配 → FFmpeg 合成 → 输出.mp4
```

## 环境要求

- Python 3.10+
- [uv](https://docs.astral.sh/uv/)（Python 包管理器，自动管理虚拟环境）
- FFmpeg（macOS: `brew install ffmpeg`）
- 两个 API Key：
  - [DeepSeek API Key](https://platform.deepseek.com/) — 用于文案分镜
  - [Pexels API Key](https://www.pexels.com/api/) — 用于搜索视频素材（免费注册）

## 安装

```bash
# 1. 安装 uv（如已安装可跳过）
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env

# 2. 进入项目目录
cd video-creator

# 3. 一键同步依赖 + 创建虚拟环境
uv sync
```

## 配置

```bash
# 复制配置模板
cp .env.example .env
```

编辑 `.env` 文件，填入你的 API Key：

```
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx
PEXELS_API_KEY=xxxxxxxxxxxxxxxx
```

## 使用

### 基本用法

```bash
# 从文案文件生成视频
uv run python cli.py -i 文案.txt

# 指定输出文件名和音色
uv run python cli.py -i 文案.txt -o 我的视频.mp4 -v zh-CN-YunyangNeural

# 仅配音+字幕，不使用视频素材
uv run python cli.py -i 文案.txt --no-material
```

### 查看可用音色

```bash
uv run python cli.py --list-voices
```

输出示例：

```
zh-CN-XiaoxiaoNeural  —  晓晓（女，温柔）
zh-CN-YunxiNeural     —  云希（男，温暖）
zh-CN-YunjianNeural   —  云健（男，沉稳）
zh-CN-XiaoyiNeural    —  晓伊（女，活泼）
zh-CN-YunyangNeural   —  云扬（男，新闻感）
zh-CN-XiaochenNeural  —  晓辰（女，自然）
```

不指定音色时默认使用 `YunyangNeural`（云扬，适合知识类内容）。

### 运行示例

```bash
# 使用内置测试文案
uv run python cli.py -i test_story.txt -o output/test.mp4
```

执行过程输出：

```
AI 视频创作
输入: test_story.txt
输出: output/test.mp4
音色: zh-CN-YunyangNeural

▸ Step 1/4: AI 分镜分析
┌──────┬────────────────┬──────┬────────────┐
│ 序号 │ 旁白摘要       │ 时长 │ 关键词     │
├──────┼────────────────┼──────┼────────────┤
│ 1    │ 人工智能正以... │ 10s  │ AI, daily. │
│ 2    │ 在医疗领域...  │ 9s   │ medical,.. │
│ 3    │ 然而技术进...  │ 10s  │ privacy,.. │
│ 4    │ 未来随着技...  │ 8s   │ future, AI │
└──────┴────────────────┴──────┴────────────┘

▸ Step 2/4: 生成配音
  ✓ 完成 4 段配音

▸ Step 3/4: 匹配素材
  搜索并下载素材...
    分镜 1: material_01.mp4
    分镜 2: material_02.mp4
    分镜 3: material_03.mp4
    分镜 4: material_04.mp4

▸ Step 4/4: 合成视频
    分镜 1: 渲染完成 (10.2s)
    分镜 2: 渲染完成 (9.5s)
    分镜 3: 渲染完成 (10.0s)
    分镜 4: 渲染完成 (8.3s)

  成品输出: /path/to/output/test.mp4

✓ 视频创作完成！
文件: /path/to/output/test.mp4
耗时: 45.3s
```

## 产出质量

- 分辨率：1920×1080（1080p）
- 帧率：30fps
- 编码：H.264 + AAC
- 字幕：硬字幕，白字黑边，居中显示

## 项目结构

```
video-creator/
├── cli.py                  # 命令行入口
├── config.py               # 配置管理（API Key、输出路径）
├── pyproject.toml          # 项目元数据与依赖声明
├── uv.lock                 # 依赖锁定文件
├── pipeline/
│   ├── __init__.py
│   ├── segmenter.py        # DeepSeek V4 Pro 文案分镜
│   ├── tts.py              # edge-tts 语音合成
│   ├── matcher.py          # Pexels 素材搜索与下载
│   └── composer.py         # FFmpeg 视频合成
├── output/                 # 生成文件存放目录
├── .env.example            # API Key 配置模板
└── test_story.txt          # 测试文案
```

## 模块说明

### segmenter.py — AI 分镜

调用 DeepSeek API 将输入文案拆分为分镜脚本。

- **模型：** `deepseek-chat`
- **输入：** 原始文案文本
- **输出：** 结构化 JSON，包含每个分镜的旁白、画面描述、中英文关键词、预估时长

DeepSeek 的系统提示词会引导模型：
- 将文案拆分为 8-15 秒/个的分镜
- 提供具体有画面感的视觉描述
- 生成英文关键词用于 Pexels 素材搜索
- 估算每个分镜的时长（约 4 字/秒）

### tts.py — 语音合成

使用微软 edge-tts 将旁白文本转为语音。

- **方案：** edge-tts（免费，无调用限制）
- **音色：** 6 种中文神经网络音色可选
- **格式：** MP3
- **输出：** 自动探测音频实际时长，回填到分镜数据中

### matcher.py — 素材匹配

通过 Pexels API 搜索并下载视频素材。

- **API：** Pexels Videos Search（免费，每月 200 次请求）
- **搜索策略：** 按英文关键词逐个搜索，取前 5 个结果
- **筛选逻辑：**
  1. 过滤 720p 以下低分辨率素材
  2. 按"时长匹配度（70%）+ 创作者可信度（30%）"评分
  3. 选最高分的素材片段下载
- **下载格式：** 原始分辨率 MP4

### composer.py — 视频合成

使用 FFmpeg 将素材、配音、字幕合成为最终视频。

- **处理步骤：**
  1. 素材裁剪到分镜时长 → 缩放居中为 1920×1080
  2. 叠加配音音频（自动截取对应时长）
  3. 添加硬字幕（drawtext 滤镜，白字黑边）
  4. 所有分镜拼接为完整视频
- **字幕处理：** 长文本自动换行，最多显示 2-3 行，逐行叠加
- **中文字体：** 使用 macOS 系统字体 `STHeiti Medium`

## 故障排查

### 分镜阶段报错

```
ValueError: DeepSeek 返回的分镜脚本无法解析为 JSON
```

原因：DeepSeek 返回格式异常。重试即可，模型偶有输出不稳定。

### 配音阶段无声音或报错

```bash
# 手动测试 edge-tts 是否正常
uv run python -c "
import asyncio, edge_tts
async def test():
    c = edge_tts.Communicate('测试语音', 'zh-CN-YunyangNeural')
    await c.save('test.mp3')
    print('OK')
asyncio.run(test())
"
```

如果失败，检查网络连接（edge-tts 需访问微软服务）。

### 素材搜索返回空

- 确认 Pexels API Key 正确配置在 `.env` 中
- Pexels 免费账户每月限额 200 次请求，超出会返回 429
- 某些中文概念的英文关键词可能匹配度低，可尝试使用 `--no-material` 跳过素材

### 合成阶段中文乱码

确认系统中存在中文字体：
```bash
ls /System/Library/Fonts/STHeiti\ Medium.ttc
```

Linux 系统需修改 `composer.py` 中的 `FONT_PATH`。

### FFmpeg not found

```bash
# macOS
brew install ffmpeg

# Ubuntu/Debian
sudo apt install ffmpeg

# Windows
# 下载 https://ffmpeg.org/download.html，解压后加入 PATH
```

## 许可证

MIT
