feat: adapt histogram ranges to scanned dataset

This commit is contained in:
kim
2026-04-02 19:00:59 +08:00
parent c5e570f382
commit 915386b778
3 changed files with 155 additions and 45 deletions
+63 -25
View File
@@ -4,23 +4,27 @@ from video_metadata_analyzer.analysis import build_summary
from video_metadata_analyzer.models import ProbeFailure, VideoMetadata
def _build_record(path_name: str, *, size_mb: int, duration_seconds: float, codec: str = "h264") -> VideoMetadata:
return VideoMetadata(
path=Path(path_name),
size_bytes=size_mb * 1024 * 1024,
duration_seconds=duration_seconds,
format_name="mov,mp4,m4a,3gp,3g2,mj2",
bit_rate=1_000_000,
video_codec=codec,
audio_codec="aac",
width=1920,
height=1080,
frame_rate=30.0,
video_stream_count=1,
audio_stream_count=1,
subtitle_stream_count=0,
)
def test_build_summary_computes_totals_and_histograms() -> None:
records = [
VideoMetadata(
path=Path("a.mp4"),
size_bytes=50 * 1024 * 1024,
duration_seconds=30,
format_name="mov,mp4,m4a,3gp,3g2,mj2",
bit_rate=1_000_000,
video_codec="h264",
audio_codec="aac",
width=1920,
height=1080,
frame_rate=30.0,
video_stream_count=1,
audio_stream_count=1,
subtitle_stream_count=0,
),
_build_record("a.mp4", size_mb=50, duration_seconds=30),
VideoMetadata(
path=Path("b.mkv"),
size_bytes=700 * 1024 * 1024,
@@ -59,18 +63,18 @@ def test_build_summary_computes_totals_and_histograms() -> None:
assert summary.total_size_bytes == 2_933_915_648
assert summary.total_duration_seconds == 4830
assert [(item.label, item.count) for item in summary.duration_histogram] == [
("0-1 min", 1),
("1-5 min", 0),
("5-15 min", 1),
("15-60 min", 0),
("60+ min", 1),
("0-15 min", 2),
("15-30 min", 0),
("30-45 min", 0),
("45-60 min", 0),
("60-75 min", 1),
]
assert [(item.label, item.count) for item in summary.size_histogram] == [
("0-100 MB", 1),
("100-500 MB", 0),
("500 MB-1 GB", 1),
("1-4 GB", 1),
("4+ GB", 0),
("0-500 MB", 1),
("500-1000 MB", 1),
("1000-1500 MB", 0),
("1500-2000 MB", 0),
("2000-2500 MB", 1),
]
assert [(item.label, item.count) for item in summary.video_codecs] == [
("h264", 2),
@@ -83,6 +87,40 @@ def test_build_summary_computes_totals_and_histograms() -> None:
]
def test_build_summary_uses_adaptive_buckets_for_compact_ranges() -> None:
records = [
_build_record("a.mp4", size_mb=10, duration_seconds=10),
_build_record("b.mp4", size_mb=25, duration_seconds=20),
_build_record("c.mp4", size_mb=40, duration_seconds=35),
_build_record("d.mp4", size_mb=55, duration_seconds=55),
_build_record("e.mp4", size_mb=80, duration_seconds=75),
_build_record("f.mp4", size_mb=120, duration_seconds=110),
_build_record("g.mp4", size_mb=160, duration_seconds=150),
_build_record("h.mp4", size_mb=240, duration_seconds=220),
_build_record("i.mp4", size_mb=360, duration_seconds=260),
]
summary = build_summary(records)
assert [(item.label, item.count) for item in summary.duration_histogram] == [
("0-1 min", 4),
("1-2 min", 2),
("2-3 min", 1),
("3-4 min", 1),
("4-5 min", 1),
]
assert [(item.label, item.count) for item in summary.size_histogram] == [
("0-50 MB", 3),
("50-100 MB", 2),
("100-150 MB", 1),
("150-200 MB", 1),
("200-250 MB", 1),
("250-300 MB", 0),
("300-350 MB", 0),
("350-400 MB", 1),
]
def test_build_summary_tracks_successful_and_failed_files() -> None:
records = [
VideoMetadata(