Loading README.md 0 → 100644 +199 −0 Original line number Diff line number Diff line # VideoSlice 按固定时间间隔从视频中抽取帧并导出为图片的命令行工具。  - **仓库**: 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 Loading
README.md 0 → 100644 +199 −0 Original line number Diff line number Diff line # VideoSlice 按固定时间间隔从视频中抽取帧并导出为图片的命令行工具。  - **仓库**: 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