feat: initialize video metadata analyzer
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
# Video Metadata Analyzer Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 构建一个基于 Python + uv 的命令行视频元数据分析器,递归扫描一个或多个目录,调用 ffprobe/ffmpeg 汇总视频元数据,并输出 JSON、CSV 和静态 HTML 可视化报告。
|
||||
|
||||
**Architecture:** 项目采用 `src/` 布局的 CLI 应用。扫描层负责发现视频文件;探测层调用 ffprobe 获取结构化元数据,并调用 ffmpeg 记录运行环境能力;分析层负责做总量统计、分布分箱和类别汇总;报告层输出机器可读 JSON/CSV 以及带内嵌 SVG 图表的 HTML 报告,避免引入浏览器端框架依赖。
|
||||
|
||||
**Tech Stack:** Python 3.11+、uv、pytest、ffprobe、ffmpeg、标准库 `argparse/json/csv/pathlib/subprocess/statistics/html`
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 建立 uv 项目基础
|
||||
|
||||
**Files:**
|
||||
- Create: `pyproject.toml`
|
||||
- Create: `src/video_metadata_analyzer/__init__.py`
|
||||
- Create: `tests/__init__.py`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_package_version_is_exposed():
|
||||
from video_metadata_analyzer import __version__
|
||||
assert __version__
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_package.py::test_package_version_is_exposed -v`
|
||||
Expected: FAIL with `ModuleNotFoundError` or missing `__version__`
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
__version__ = "0.1.0"
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest tests/test_package.py::test_package_version_is_exposed -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add pyproject.toml src/video_metadata_analyzer/__init__.py tests/test_package.py
|
||||
git commit -m "chore: initialize uv project skeleton"
|
||||
```
|
||||
|
||||
### Task 2: 实现视频文件发现
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_discovery.py`
|
||||
- Create: `src/video_metadata_analyzer/discovery.py`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_discover_video_files_recursively_filters_supported_extensions(tmp_path):
|
||||
...
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_discovery.py::test_discover_video_files_recursively_filters_supported_extensions -v`
|
||||
Expected: FAIL with missing function
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
def discover_video_files(inputs: list[Path]) -> list[Path]:
|
||||
...
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest tests/test_discovery.py::test_discover_video_files_recursively_filters_supported_extensions -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/test_discovery.py src/video_metadata_analyzer/discovery.py
|
||||
git commit -m "feat: add recursive video discovery"
|
||||
```
|
||||
|
||||
### Task 3: 实现 ffprobe 元数据解析
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_probe.py`
|
||||
- Create: `src/video_metadata_analyzer/models.py`
|
||||
- Create: `src/video_metadata_analyzer/probe.py`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_probe_video_metadata_parses_primary_streams():
|
||||
...
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_probe.py::test_probe_video_metadata_parses_primary_streams -v`
|
||||
Expected: FAIL with missing class or parser
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class VideoMetadata:
|
||||
...
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest tests/test_probe.py::test_probe_video_metadata_parses_primary_streams -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/test_probe.py src/video_metadata_analyzer/models.py src/video_metadata_analyzer/probe.py
|
||||
git commit -m "feat: parse metadata from ffprobe output"
|
||||
```
|
||||
|
||||
### Task 4: 实现聚合分析与图表数据
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_analysis.py`
|
||||
- Create: `src/video_metadata_analyzer/analysis.py`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_build_summary_computes_totals_and_histograms():
|
||||
...
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_analysis.py::test_build_summary_computes_totals_and_histograms -v`
|
||||
Expected: FAIL with missing function
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
def build_summary(records: list[VideoMetadata]) -> AnalysisSummary:
|
||||
...
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest tests/test_analysis.py::test_build_summary_computes_totals_and_histograms -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/test_analysis.py src/video_metadata_analyzer/analysis.py
|
||||
git commit -m "feat: add aggregate analysis summaries"
|
||||
```
|
||||
|
||||
### Task 5: 实现报告输出与 CLI
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_report.py`
|
||||
- Create: `tests/test_cli.py`
|
||||
- Create: `src/video_metadata_analyzer/reporting.py`
|
||||
- Create: `src/video_metadata_analyzer/cli.py`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_write_reports_creates_json_csv_and_html(tmp_path):
|
||||
...
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_report.py::test_write_reports_creates_json_csv_and_html -v`
|
||||
Expected: FAIL with missing writer
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```python
|
||||
def write_report_bundle(output_dir: Path, ...):
|
||||
...
|
||||
```
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest tests/test_report.py::test_write_reports_creates_json_csv_and_html -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add tests/test_report.py tests/test_cli.py src/video_metadata_analyzer/reporting.py src/video_metadata_analyzer/cli.py
|
||||
git commit -m "feat: add report writers and CLI entrypoint"
|
||||
```
|
||||
|
||||
### Task 6: 文档与验收
|
||||
|
||||
**Files:**
|
||||
- Create: `README.md`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```python
|
||||
def test_readme_mentions_uv_run_command():
|
||||
...
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `uv run pytest tests/test_cli.py::test_readme_mentions_uv_run_command -v`
|
||||
Expected: FAIL because README or command example is absent
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
补充中文 README,写明依赖、安装、运行方式、输出文件说明和常见问题。
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `uv run pytest -q`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add README.md
|
||||
git commit -m "docs: add usage guide for video metadata analyzer"
|
||||
```
|
||||
Reference in New Issue
Block a user