Commit 549759e6 authored by shrabbit's avatar shrabbit
Browse files

更新自述文件。

parent 597597eb
Loading
Loading
Loading
Loading

README.md

0 → 100644
+199 −0
Original line number Diff line number Diff line
# VideoSlice

按固定时间间隔从视频中抽取帧并导出为图片的命令行工具。

![Release](https://img.shields.io/badge/release-1.0.0-blue)

- **仓库**: https://org.shrabbit.com:3000/shrabbit/VideoSlice
- **Releases**: https://org.shrabbit.com:3000/shrabbit/VideoSlice/releases
- **许可证**: MIT(见 [LICENSE](LICENSE)

## 功能

- 按固定时间间隔从视频中抽取帧,导出为 PNG / JPG 等图片
- **逐点快速定位**:每个时间点通过 `-ss` 输入快速寻址,只读取目标点附近的数据,间隔再大(如 30 分钟)也不用解码整段视频
- **NVIDIA 硬件解码加速**`-a cuda` 时自动按编码器选用对应的 cuvid 解码器(h264/hevc/av1/vp9/mpeg2)
- 目录批量处理,支持多种视频格式(`mp4,mkv` 等)
- 并行执行,按 `-p` 控制同时运行的 ffmpeg 进程数
- `-n` 只打印命令不执行,便于先预览再运行
- 自动探测视频时长与编码器,自动创建输出目录

## 环境要求

| 依赖 | 说明                                                                                                                                   |
|------|--------------------------------------------------------------------------------------------------------------------------------------|
| .NET 10 运行时 | 运行程序必需,[下载地址](https://dotnet.microsoft.com/download/dotnet/10.0) ,或通过下文的安装命令。                                                        |
| ffmpeg | 程序通过命令行调用 ffmpeg;需在 `PATH` 中或通过 `-m` 指定路径。NVIDIA 硬件加速需要带 cuvid/nvdec 的构建(如 [gyan.dev](https://www.gyan.dev/ffmpeg/builds/) 的 full 版) |

## 安装 .NET 10
通用的方法是访问前文的链接进行下载,其中包含所有平台的下载方式。

如果没有安装,按此方法进行
### Windows 10+
如果有 WinGet,使用 WinGet 进行安装。
```
winget install Microsoft.DotNet.SDK.10
```

### Ubuntu
```
sudo apt-get update && \
  sudo apt-get install -y dotnet-runtime-10.0
```

## 下载与发布
新版本发布时,将编译Windows x64版本,可直接下载。

下载`self-contained`后缀的版本可无需安装运行时,但软件体积会变得非常大。

下载`aot`后缀的版本为提取编译版,可无需安装运行时,并且速度最快且体积最小。

- Releases 页面:https://org.shrabbit.com:3000/shrabbit/VideoSlice/releases

## 用法

```bash
videoslice.cli -d <视频目录> [-v mp4,mkv] [-l 30m] [-a cuda] [-p 4] [-s output] [-i png] [-m ffmpeg] [-n]
```

### 示例

```bash
# 从 D:\Videos 中所有 mp4/mkv 视频,每 30 分钟抽一帧,导出到 D:\Videos\output
videoslice.cli -d D:\Videos -v mp4,mkv -l 30m

# 启用 NVIDIA 硬件解码,并行 8 个进程,每 10 秒抽一帧
videoslice.cli -d D:\Videos -v mp4,mkv -l 10s -a cuda -p 8

# 只打印将执行的 ffmpeg 命令,不实际运行
videoslice.cli -d D:\Videos -v mp4 -l 30m -n
```

### 选项

| 短选项 | 长选项 | 说明 | 默认 |
|--------|--------|------|------|
| `-f` | `--file` | 指定单个视频文件 | 无 |
| `-d` | `--dir` | 视频目录 | 空 |
| `-s` | `--disc` | 图片输出目录(自动创建) | `output` |
| `-i` | `--image-format` | 图片格式 | `png` |
| `-v` | `--video-format` | 视频格式,可用 `,` 分隔多个 | `mp4` |
| `-p` | `--parallel` | 并行运行的 ffmpeg 进程数 | `4` |
| `-m` | `--ffmpeg` | ffmpeg 可执行文件路径 | `ffmpeg` |
| `-l` | `--slice` | 抽取帧的时间间隔 | `30m` |
| `-a` | `--hwaccel` | 硬件解码加速名称(`cuda`/`dxva2`/`qsv` 等) | 不启用 |
| `-n` | `--no-exec` | 只输出命令列表,不运行命令 | `false` |

### 时间间隔(`-l`)

由数字 + 单位组成,支持 `d`(天)、`h`(时)、`m`(分)、`s`(秒)、`ms`(毫秒)、`us`(微秒),可组合:

- `30m` — 30 分钟
- `1h30m` — 1 小时 30 分
- `10s` — 10 秒

间隔必须大于 0。

### 硬件加速(`-a`)

- `cuda`:自动按视频编码器选择对应 cuvid 解码器(`h264_cuvid``hevc_cuvid``av1_cuvid``vp9_cuvid``mpeg2_cuvid`),编码器无对应 cuvid 解码器时退化为 `-hwaccel cuda`
- 其他值(如 `dxva2``qsv`):直接作为 `-hwaccel <值>` 传入 ffmpeg

### 输出文件

`{原文件名}_{序号}.{格式}` 命名,例如 `2026-07-30 20-49-18.mkv_000.png``..._001.png`

## 自行编译

需要 [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)(含 SDK,不只是运行时)。

```bash
git clone https://org.shrabbit.com:3000/shrabbit/VideoSlice.git
cd VideoSlice

# 还原并编译
dotnet restore VideoSlice.slnx
dotnet build VideoSlice.slnx -c Release

# 发布为单目录产物(以 Windows x64 为例)
dotnet publish src/VideoSlice.Cli/VideoSlice.Cli.csproj -c Release -r win-x64 --self-contained false

# 运行单元测试
dotnet test src/VideoSlice.Tests/VideoSlice.Tests.csproj
```

- 编译产物:`src/VideoSlice.Cli/bin/Release/net10.0/`
- 发布产物:`src/VideoSlice.Cli/bin/Release/net10.0/win-x64/publish/`(包含 `VideoSlice.Cli.exe`,可自行改名为 `videoslice.cli`
- 说明:`dotnet publish` 产物依赖目标机器上的 .NET 10 运行时(`--self-contained false`)。如需单文件无依赖,去掉 `-r win-x64` 限制或改用 `--self-contained true` 按需配置

## 问题排除

### 未安装 .NET 10 运行时

运行时报错示例:

```
You must install or update .NET to run this application.
The framework 'Microsoft.NETCore.App', version '10.0.0' was not found.
```

**解决**:安装 [.NET 10 运行时](https://dotnet.microsoft.com/download/dotnet/10.0)(自行编译则需要 .NET 10 SDK)。

### 找不到 / 无法启动 ffmpeg

报错 `无法启动 ffmpeg:...`

**解决**
1. 确认已安装 ffmpeg:终端执行 `ffmpeg -version`
2. 未加入 `PATH` 时,用 `-m` 指定完整路径:`-m C:\ffmpeg\bin\ffmpeg.exe`

### NVIDIA 硬件加速不生效

现象:`-a cuda` 后 ffmpeg 输出仍显示 `(native)` 软件解码,或 GPU 解码器占用很低。

**原因与解决**
1. ffmpeg 构建不含 NVDEC/cuvid —— 换用带 `--enable-nvdec --enable-cuvid --enable-ffnvcodec` 的构建(如 gyan.dev full 版)
2. GPU 不支持对应编码的硬解 —— AV1 硬解需要 NVIDIA RTX 30 系列及以上显卡
3. 程序已按编码器自动选择 `-c:v av1_cuvid` 等解码器,此时 stream mapping 应显示如 `av1 (av1_cuvid)`;若仍显示 `native`,请检查 ffmpeg 构建

### ffmpeg 报 `No such filter` 或语法错误

ffmpeg 版本过旧。请升级到较新的 ffmpeg(建议 6.x 及以上)。

### 间隔很大时仍然很慢

程序已采用逐点 `-ss` 快速定位,不再解码整段视频。若仍慢:
- 视频位于网络驱动器时,瓶颈在随机读取,可检查网络质量
- 开启硬件加速 `-a cuda`
- 调大并行度 `-p`

### 编译报 MSB3027(文件被锁定)

```
error MSB3027: 无法将“...”复制到“...”。文件被“.NET Host (PID)”锁定。
```

这是 Rider / ReSharper 后台编译占用文件导致,**实际编译已通过**。等待或重启 Rider 后重新编译即可。

## 项目结构

```
VideoSlice.slnx                     # 解决方案(SLNX 格式)
src/
├── VideoSlice.Cli/                 # 控制台程序(net10.0)
│   ├── Program.cs                  # 入口
│   ├── MainCommand.cs              # 命令主逻辑:探测/生成/执行
│   ├── SimpleTimeSpanExpress.cs    # 时间表达式解析与格式化(30m、1h30m 等)
│   └── ProcessManager.cs           # ffmpeg 进程跟踪与退出清理
└── VideoSlice.Tests/               # xUnit 单元测试
LICENSE                             # MIT
```

## 技术栈与相关项目

- **.NET 10****Spectre.Console.Cli**(命令行解析与界面)、**xUnit**(测试)
- **[shRabbit.Base](https://org.shrabbit.com:3000/shRabbit.Toolkits/shRabbit.Base)**:文件/目录抽象桥接(IFile/IDirectory),便于测试替换

## 许可证

[MIT](LICENSE) © 2026 shRabbit