feat(bilibili-analyzer): 支持字幕区域裁剪

- 新增 --crop-ratio 参数,提取底部1/N区域(默认1/4)
- 新增 --no-crop 参数,禁用裁剪提取完整帧
- 优化字幕识别效率,只处理字幕区域
This commit is contained in:
OpenClaw Agent
2026-02-09 23:51:42 +08:00
parent 732dfb6549
commit 2f5a269866
2 changed files with 41 additions and 5 deletions
+9 -1
View File
@@ -118,7 +118,7 @@ python3 -m venv .venv
### 使用方法
```bash
# 基本用法
# 基本用法(默认裁剪底部1/4,用于提取字幕)
dotnet run scripts/prepare.cs "<视频URL>" -o <输出目录>
# 示例
@@ -126,6 +126,12 @@ dotnet run scripts/prepare.cs "https://www.bilibili.com/video/BV1xx411c7mD" -o .
# 长视频(降低帧率)
dotnet run scripts/prepare.cs "https://www.bilibili.com/video/BV1xx411c7mD" -o ./output --fps 0.5
# 提取全帧(不裁剪)
dotnet run scripts/prepare.cs "https://www.bilibili.com/video/BV1xx411c7mD" -o ./output --no-crop
# 调整裁剪比例(底部1/2)
dotnet run scripts/prepare.cs "https://www.bilibili.com/video/BV1xx411c7mD" -o ./output --crop-ratio 2
```
### 参数说明
@@ -137,6 +143,8 @@ dotnet run scripts/prepare.cs "https://www.bilibili.com/video/BV1xx411c7mD" -o .
| `--fps` | 每秒提取帧数 | 1.0 |
| `--similarity` | 相似度阈值(0-1),超过此值的相邻帧会被去重 | 0.80 |
| `--no-dedup` | 禁用相似帧去重 | false |
| `--crop-ratio` | 裁剪比例(提取底部1/N) | 4(底部1/4) |
| `--no-crop` | 禁用裁剪,提取完整帧 | false |
| `--video-only` | 只下载视频,不提取帧 | false |
| `--frames-only` | 只提取帧(需已有video.mp4) | false |
+32 -4
View File
@@ -27,6 +27,13 @@ if (!double.TryParse(fpsStr, NumberStyles.Float, CultureInfo.InvariantCulture, o
Console.WriteLine($"[ERROR] Invalid fps value: {fpsStr}");
Environment.Exit(1);
}
var cropRatioStr = GetArgValue(args, "--crop-ratio") ?? "4";
if (!int.TryParse(cropRatioStr, out var cropRatio) || cropRatio < 2 || cropRatio > 10)
{
Console.WriteLine($"[ERROR] Invalid crop-ratio value: {cropRatioStr} (must be 2-10)");
Environment.Exit(1);
}
var noCrop = args.Contains("--no-crop");
var similarityStr = GetArgValue(args, "--similarity") ?? "0.80";
if (!double.TryParse(similarityStr, NumberStyles.Float, CultureInfo.InvariantCulture, out var similarityThreshold))
{
@@ -51,6 +58,7 @@ Console.WriteLine($"Output: {outputDir}");
Console.WriteLine($"FPS: {fps}");
Console.WriteLine($"Similarity Threshold: {similarityThreshold:P0}");
Console.WriteLine($"Deduplication: {(noDedup ? "Disabled" : "Enabled")}");
Console.WriteLine($"Crop: {(noCrop ? "Disabled" : $"Bottom 1/{cropRatio}")}");
Console.WriteLine(new string('=', 50));
// Download video
@@ -71,7 +79,7 @@ if (!videoOnly)
Environment.Exit(1);
}
if (!await ExtractFramesAsync(videoPath, imagesDir, fps))
if (!await ExtractFramesAsync(videoPath, imagesDir, fps, !noCrop, cropRatio))
{
Environment.Exit(1);
}
@@ -237,9 +245,9 @@ HttpClient CreateHttpClient()
return client;
}
async Task<bool> ExtractFramesAsync(string videoPath, string outputDir, double fps)
async Task<bool> ExtractFramesAsync(string videoPath, string outputDir, double fps, bool useCrop, int cropRatio)
{
Console.WriteLine($"[INFO] Extracting frames (fps={fps})");
Console.WriteLine($"[INFO] Extracting frames (fps={fps}, crop={(useCrop ? $"bottom 1/{cropRatio}" : "disabled")})");
var ffmpeg = FindExecutable("ffmpeg", "ffmpeg.exe");
if (ffmpeg == null)
@@ -258,10 +266,20 @@ async Task<bool> ExtractFramesAsync(string videoPath, string outputDir, double f
{
Console.WriteLine($"[INFO] Running ffmpeg: {ffmpeg}");
// Build filter string
var filter = $"fps={fps.ToString(CultureInfo.InvariantCulture)}";
if (useCrop)
{
// Crop bottom portion using FFmpeg's crop filter
// crop=w=iw:h=ih/{cropRatio}:x=0:y=ih-h/ih-{cropRatio}
// This crops the bottom 1/cropRatio of the frame
filter = $"fps={fps.ToString(CultureInfo.InvariantCulture)},crop=iw:ih/{cropRatio}:0:ih-ih/{cropRatio}";
}
var psi = new ProcessStartInfo
{
FileName = ffmpeg,
Arguments = $"-i \"{videoPath}\" -vf \"fps={fps.ToString(CultureInfo.InvariantCulture)}\" -q:v 2 -y \"{outputPattern}\"",
Arguments = $"-i \"{videoPath}\" -vf \"{filter}\" -q:v 2 -y \"{outputPattern}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
@@ -576,6 +594,8 @@ Options:
--fps <value> Frames per second (default: 1.0)
--similarity <value> Similarity threshold for deduplication (default: 0.80)
--no-dedup Disable frame deduplication
--crop-ratio <value> Crop to bottom 1/N of frame (default: 4, N=4 means bottom 1/4)
--no-crop Disable cropping (extract full frame)
--video-only Only download video, skip frame extraction
--frames-only Only extract frames (requires existing video.mp4)
-h, --help Show this help
@@ -586,6 +606,14 @@ Examples:
dotnet run prepare.cs ""https://www.bilibili.com/video/BV1xx411c7mD"" -o ./output
dotnet run prepare.cs ""https://www.bilibili.com/video/BV1xx411c7mD"" --similarity 0.85
dotnet run prepare.cs ""https://www.bilibili.com/video/BV1xx411c7mD"" --no-dedup
dotnet run prepare.cs ""https://www.bilibili.com/video/BV1xx411c7mD"" --crop-ratio 4
dotnet run prepare.cs ""https://www.bilibili.com/video/BV1xx411c7mD"" --no-crop
Cropping (for subtitle extraction):
By default, only the bottom 1/4 of the frame is extracted (--crop-ratio 4)
This is useful for capturing subtitles without the main video content
Use --no-crop to extract the full frame
Use --crop-ratio 2 for bottom half, --crop-ratio 8 for bottom 1/8, etc.
Deduplication:
Consecutive frames with similarity >= threshold will be deduplicated.