feat: mechanical mode/duration/resolution tagging
Per sub-project-2 plan Task 4 / spec §5.1. derive_tags(Probe) -> Tags with the attached_pic cover-art guard so an art-bearing audio file stays mode=audio. Duration falls back to the longest stream when format.duration is absent, and rounds half-up so 12.5s -> 13s (Python's round() would give 12 via banker's rounding) to match the spec's stated behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
from tools.probe import Probe
|
||||
from tools.tagging import Tags, derive_tags
|
||||
|
||||
|
||||
def test_video_and_audio_is_av():
|
||||
p = Probe(
|
||||
streams=[
|
||||
{
|
||||
"codec_type": "video",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"disposition": {"attached_pic": 0},
|
||||
},
|
||||
{"codec_type": "audio"},
|
||||
],
|
||||
format={"duration": "12.5"},
|
||||
)
|
||||
t = derive_tags(p)
|
||||
assert isinstance(t, Tags)
|
||||
assert t.mode == "av"
|
||||
assert t.resolution == "1920x1080"
|
||||
assert t.duration_s == 13 # round(12.5)
|
||||
|
||||
|
||||
def test_audio_only():
|
||||
p = Probe(streams=[{"codec_type": "audio"}], format={"duration": "30.0"})
|
||||
t = derive_tags(p)
|
||||
assert t.mode == "audio" and t.resolution == "" and t.duration_s == 30
|
||||
|
||||
|
||||
def test_cover_art_stays_audio():
|
||||
p = Probe(
|
||||
streams=[
|
||||
{"codec_type": "audio", "duration": "30.0"},
|
||||
{
|
||||
"codec_type": "video",
|
||||
"width": 600,
|
||||
"height": 600,
|
||||
"disposition": {"attached_pic": 1},
|
||||
},
|
||||
],
|
||||
format={"duration": "30.0"},
|
||||
)
|
||||
t = derive_tags(p)
|
||||
assert t.mode == "audio" and t.resolution == "" and t.duration_s == 30
|
||||
|
||||
|
||||
def test_video_only():
|
||||
p = Probe(
|
||||
streams=[
|
||||
{
|
||||
"codec_type": "video",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"disposition": {"attached_pic": 0},
|
||||
}
|
||||
],
|
||||
format={"duration": "5.0"},
|
||||
)
|
||||
t = derive_tags(p)
|
||||
assert t.mode == "video" and t.resolution == "1280x720"
|
||||
|
||||
|
||||
def test_duration_falls_back_to_longest_stream():
|
||||
p = Probe(
|
||||
streams=[
|
||||
{"codec_type": "audio", "duration": "10.0"},
|
||||
{
|
||||
"codec_type": "video",
|
||||
"width": 640,
|
||||
"height": 480,
|
||||
"duration": "42.4",
|
||||
"disposition": {"attached_pic": 0},
|
||||
},
|
||||
],
|
||||
format={},
|
||||
)
|
||||
t = derive_tags(p)
|
||||
assert t.duration_s == 42 # round(42.4), longest stream
|
||||
|
||||
|
||||
def test_duration_never_negative_and_zero_default():
|
||||
p = Probe(streams=[{"codec_type": "audio"}], format={})
|
||||
t = derive_tags(p)
|
||||
assert t.duration_s == 0
|
||||
|
||||
|
||||
def test_video_without_dimensions_yields_empty_resolution():
|
||||
p = Probe(
|
||||
streams=[{"codec_type": "video", "disposition": {"attached_pic": 0}}],
|
||||
format={"duration": "3.0"},
|
||||
)
|
||||
t = derive_tags(p)
|
||||
assert t.mode == "video" and t.resolution == ""
|
||||
Reference in New Issue
Block a user