Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion bdpl/analyze/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,15 @@ def _detect_special_features(
if pl is None:
continue
category = classifications.get(mpls, "extra")
if category in {"episode", "play_all"}:
if category == "play_all":
continue
# An "episode" playlist not used as an actual episode source
# (episodes came from play_all decomposition) is a commentary
# or alternate-audio track.
if category == "episode":
if mpls in ep_playlists:
continue
category = "commentary"

new_features = _build_chapter_split_features(
pl,
Expand All @@ -379,6 +386,13 @@ def _detect_special_features(
features.extend(new_features)
idx += len(new_features)

# A special whose classification is "episode" (individual playlist that
# was bypassed in favour of play_all decomposition) is really a
# commentary / alternate-audio track, not a distinct episode.
for f in features:
if f.category == "episode":
f.category = "commentary"

return features


Expand Down
16 changes: 12 additions & 4 deletions bdpl/analyze/ordering.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,18 @@ def order_episodes(
if individual_eps and pa_episodes:
avg_indiv = sum(p.duration_ms for p in individual_eps) / len(individual_eps)
avg_pa = sum(e.duration_ms for e in pa_episodes) / len(pa_episodes) if pa_episodes else 0
# If Play All yields more episodes whose average duration is much
# longer, the individual playlists are probably extras, not episodes.
if len(pa_episodes) > len(individual_eps) and avg_pa > avg_indiv * 1.5:
return pa_episodes
if len(pa_episodes) > len(individual_eps):
# If individual episode clips are a strict subset of the
# play_all clips, the individual playlists only cover some
# episodes (the rest are play_all-only). Use play_all.
indiv_clips = {pi.clip_id for p in individual_eps for pi in p.play_items}
pa_clips = {seg.clip_id for ep in pa_episodes for seg in ep.segments}
if indiv_clips <= pa_clips:
return pa_episodes
# If Play All episodes are much longer on average, the
# individual playlists are probably extras, not episodes.
if avg_pa > avg_indiv * 1.5:
return pa_episodes
return _episodes_from_individual(individual_eps)

if individual_eps:
Expand Down
48 changes: 48 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,54 @@ def disc9_analysis(disc9_path):
return _analyze_fixture(disc9_path)


@pytest.fixture(scope="session")
def disc10_path() -> Path:
"""Return path to bundled disc10 fixture."""
return _fixture_path("disc10")


@pytest.fixture(scope="session")
def disc10_analysis(disc10_path):
"""Run and cache full analysis for the bundled disc10 fixture."""
return _analyze_fixture(disc10_path)


@pytest.fixture(scope="session")
def disc11_path() -> Path:
"""Return path to bundled disc11 fixture."""
return _fixture_path("disc11")


@pytest.fixture(scope="session")
def disc11_analysis(disc11_path):
"""Run and cache full analysis for the bundled disc11 fixture."""
return _analyze_fixture(disc11_path)


@pytest.fixture(scope="session")
def disc12_path() -> Path:
"""Return path to bundled disc12 fixture."""
return _fixture_path("disc12")


@pytest.fixture(scope="session")
def disc12_analysis(disc12_path):
"""Run and cache full analysis for the bundled disc12 fixture."""
return _analyze_fixture(disc12_path)


@pytest.fixture(scope="session")
def disc13_path() -> Path:
"""Return path to bundled disc13 fixture."""
return _fixture_path("disc13")


@pytest.fixture(scope="session")
def disc13_analysis(disc13_path):
"""Run and cache full analysis for the bundled disc13 fixture."""
return _analyze_fixture(disc13_path)


@pytest.fixture
def cli_runner() -> Callable[..., subprocess.CompletedProcess[str]]:
"""Return helper to invoke `python -m bdpl.cli` consistently in tests."""
Expand Down
Binary file added tests/fixtures/disc10/CLIPINF/00000.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00001.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00002.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00003.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00004.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00005.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00006.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00007.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00008.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00009.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00010.clpi
Binary file not shown.
Binary file added tests/fixtures/disc10/CLIPINF/00011.clpi
Binary file not shown.
9 changes: 9 additions & 0 deletions tests/fixtures/disc10/META/DL/bdmt_eng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<disclib xmlns="urn:BDA:bdmv;disclib"
xmlns:di="urn:BDA:bdmv;discinfo">
<di:discinfo>
<di:title>
<di:name>TEST DISC 10</di:name>
</di:title>
</di:discinfo>
</disclib>
Binary file added tests/fixtures/disc10/MovieObject.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00000.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00001.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00002.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00003.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00004.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/PLAYLIST/00005.mpls
Binary file not shown.
Binary file added tests/fixtures/disc10/ics_menu.bin
Binary file not shown.
Binary file added tests/fixtures/disc10/index.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00000.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00001.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00002.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00003.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00004.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00005.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00006.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00007.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00008.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00009.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00010.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00011.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00012.clpi
Binary file not shown.
Binary file added tests/fixtures/disc11/CLIPINF/00013.clpi
Binary file not shown.
9 changes: 9 additions & 0 deletions tests/fixtures/disc11/META/DL/bdmt_eng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<disclib xmlns="urn:BDA:bdmv;disclib"
xmlns:di="urn:BDA:bdmv;discinfo">
<di:discinfo>
<di:title>
<di:name>TEST DISC 11</di:name>
</di:title>
</di:discinfo>
</disclib>
Binary file added tests/fixtures/disc11/MovieObject.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc11/PLAYLIST/00000.mpls
Binary file not shown.
Binary file added tests/fixtures/disc11/PLAYLIST/00001.mpls
Binary file not shown.
Binary file added tests/fixtures/disc11/PLAYLIST/00002.mpls
Binary file not shown.
Binary file added tests/fixtures/disc11/PLAYLIST/00003.mpls
Binary file not shown.
Binary file added tests/fixtures/disc11/ics_menu.bin
Binary file not shown.
Binary file added tests/fixtures/disc11/index.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00000.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00001.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00002.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00003.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00004.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00005.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00006.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00007.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00008.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00009.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00010.clpi
Binary file not shown.
Binary file added tests/fixtures/disc12/CLIPINF/00011.clpi
Binary file not shown.
9 changes: 9 additions & 0 deletions tests/fixtures/disc12/META/DL/bdmt_eng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<disclib xmlns="urn:BDA:bdmv;disclib"
xmlns:di="urn:BDA:bdmv;discinfo">
<di:discinfo>
<di:title>
<di:name>TEST DISC 12</di:name>
</di:title>
</di:discinfo>
</disclib>
Binary file added tests/fixtures/disc12/MovieObject.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00000.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00001.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00002.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00003.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00004.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/PLAYLIST/00005.mpls
Binary file not shown.
Binary file added tests/fixtures/disc12/ics_menu.bin
Binary file not shown.
Binary file added tests/fixtures/disc12/index.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00000.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00001.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00002.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00003.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00004.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00005.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00006.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00007.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00008.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00009.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00010.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00011.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00012.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00013.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00014.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00015.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00016.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00017.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00018.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00019.clpi
Binary file not shown.
Binary file added tests/fixtures/disc13/CLIPINF/00020.clpi
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/fixtures/disc13/META/DL/bdmt_eng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<disclib>
<di:discinfo xmlns:di="urn:BDA:bdmv;discinfo">
<di:title><di:name>TEST DISC 13</di:name></di:title>
</di:discinfo>
</disclib>
Binary file added tests/fixtures/disc13/MovieObject.bdmv
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00000.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00001.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00002.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00003.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00004.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00005.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00006.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00007.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00008.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00009.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00010.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/PLAYLIST/00011.mpls
Binary file not shown.
Binary file added tests/fixtures/disc13/ics_menu.bin
Binary file not shown.
Binary file added tests/fixtures/disc13/index.bdmv
Binary file not shown.
77 changes: 77 additions & 0 deletions tests/test_disc10_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Integration tests for the disc10 fixture scan results.

Disc10 is a five-episode bonus disc with commentary specials:
- Play_all (00002.mpls, 6 clips, 31 chapters) decomposes into 5 episodes
at IG chapter marks [0, 6, 12, 18, 24]. Each episode ~24 min.
- Three individual playlists (00003-00005) duplicate episodes 1-3 with
commentary audio; detected as commentary specials via IG page 4 buttons.
- Only episodes 1-3 have individual playlists; episodes 4-5 are
play_all-only, driving the play_all-subset ordering heuristic.
"""

import pytest

from bdpl.model import DiscAnalysis

pytestmark = pytest.mark.integration


class TestDisc10Episodes:
def test_finds_five_episodes(self, disc10_analysis: DiscAnalysis) -> None:
"""Disc10 should infer exactly five episodes from play_all."""
assert len(disc10_analysis.episodes) == 5

def test_episodes_are_ordered(self, disc10_analysis: DiscAnalysis) -> None:
"""Verify inferred episode sequence is [1, 2, 3, 4, 5]."""
assert [ep.episode for ep in disc10_analysis.episodes] == [1, 2, 3, 4, 5]

def test_all_episodes_from_play_all(self, disc10_analysis: DiscAnalysis) -> None:
"""All episodes should come from the play_all playlist."""
for ep in disc10_analysis.episodes:
assert ep.playlist == "00002.mpls"

def test_episode_durations_reasonable(self, disc10_analysis: DiscAnalysis) -> None:
"""Each episode should be ~20–28 min."""
for ep in disc10_analysis.episodes:
dur_min = ep.duration_ms / 60_000
assert 20 < dur_min < 28, f"Ep {ep.episode} duration {dur_min:.1f}min out of range"

def test_episodes_have_scenes(self, disc10_analysis: DiscAnalysis) -> None:
"""Each episode should have at least 1 scene."""
for ep in disc10_analysis.episodes:
assert len(ep.scenes) >= 1, f"Ep {ep.episode} has no scenes"


class TestDisc10Specials:
def test_special_count(self, disc10_analysis: DiscAnalysis) -> None:
"""Disc10 should have 3 specials (commentaries for episodes 1-3)."""
assert len(disc10_analysis.special_features) == 3

def test_all_commentaries(self, disc10_analysis: DiscAnalysis) -> None:
"""All specials should be commentary tracks."""
for sf in disc10_analysis.special_features:
assert sf.category == "commentary", (
f"Special {sf.playlist} has category '{sf.category}', expected 'commentary'"
)

def test_commentary_playlists(self, disc10_analysis: DiscAnalysis) -> None:
"""Commentary tracks should reference individual episode playlists."""
playlists = {sf.playlist for sf in disc10_analysis.special_features}
assert playlists == {"00003.mpls", "00004.mpls", "00005.mpls"}


class TestDisc10Metadata:
def test_disc_title(self, disc10_analysis: DiscAnalysis) -> None:
"""Disc title should be extracted from META/DL/bdmt_eng.xml."""
assert disc10_analysis.disc_title == "TEST DISC 10"

def test_play_all_detected(self, disc10_analysis: DiscAnalysis) -> None:
"""00002.mpls should be classified as play_all."""
classes = disc10_analysis.analysis.get("classifications", {})
assert classes.get("00002.mpls") == "play_all"

def test_ig_chapter_marks(self, disc10_analysis: DiscAnalysis) -> None:
"""IG hints should report 5 chapter marks for episode starts."""
ig = disc10_analysis.analysis.get("disc_hints", {}).get("ig_menu", {})
marks = ig.get("chapter_marks", [])
assert marks == [0, 6, 12, 18, 24]
69 changes: 69 additions & 0 deletions tests/test_disc11_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Integration tests for the disc11 fixture scan results.

Disc11 is a six-episode bonus disc with one short special:
- Play_all (00002.mpls, 7 clips, 37 chapters) decomposes into 6 episodes
at IG chapter marks [0, 6, 12, 18, 24, 30]. Each episode ~24 min.
- One special feature (00003.mpls, clip 00013, ~3.5 min) classified as
extra, detected via title hint (title 1 → playlist 3).
- No individual episode playlists — all episodes come from play_all.
"""

import pytest

from bdpl.model import DiscAnalysis

pytestmark = pytest.mark.integration


class TestDisc11Episodes:
def test_finds_six_episodes(self, disc11_analysis: DiscAnalysis) -> None:
"""Disc11 should infer exactly six episodes from play_all."""
assert len(disc11_analysis.episodes) == 6

def test_episodes_are_ordered(self, disc11_analysis: DiscAnalysis) -> None:
"""Verify inferred episode sequence is [1..6]."""
assert [ep.episode for ep in disc11_analysis.episodes] == [1, 2, 3, 4, 5, 6]

def test_all_episodes_from_play_all(self, disc11_analysis: DiscAnalysis) -> None:
"""All episodes should come from the play_all playlist."""
for ep in disc11_analysis.episodes:
assert ep.playlist == "00002.mpls"

def test_episode_durations_reasonable(self, disc11_analysis: DiscAnalysis) -> None:
"""Each episode should be ~20–28 min."""
for ep in disc11_analysis.episodes:
dur_min = ep.duration_ms / 60_000
assert 20 < dur_min < 28, f"Ep {ep.episode} duration {dur_min:.1f}min out of range"


class TestDisc11Specials:
def test_special_count(self, disc11_analysis: DiscAnalysis) -> None:
"""Disc11 should have 1 special feature."""
assert len(disc11_analysis.special_features) == 1

def test_special_is_short(self, disc11_analysis: DiscAnalysis) -> None:
"""The special should be ~3–5 min."""
sf = disc11_analysis.special_features[0]
dur_min = sf.duration_ms / 60_000
assert 2 < dur_min < 5, f"Special {sf.playlist} duration {dur_min:.1f}min out of range"

def test_special_playlist(self, disc11_analysis: DiscAnalysis) -> None:
"""Special should be on 00003.mpls."""
assert disc11_analysis.special_features[0].playlist == "00003.mpls"


class TestDisc11Metadata:
def test_disc_title(self, disc11_analysis: DiscAnalysis) -> None:
"""Disc title should be extracted from META/DL/bdmt_eng.xml."""
assert disc11_analysis.disc_title == "TEST DISC 11"

def test_play_all_detected(self, disc11_analysis: DiscAnalysis) -> None:
"""00002.mpls should be classified as play_all."""
classes = disc11_analysis.analysis.get("classifications", {})
assert classes.get("00002.mpls") == "play_all"

def test_ig_chapter_marks(self, disc11_analysis: DiscAnalysis) -> None:
"""IG hints should report 6 chapter marks for episode starts."""
ig = disc11_analysis.analysis.get("disc_hints", {}).get("ig_menu", {})
marks = ig.get("chapter_marks", [])
assert marks == [0, 6, 12, 18, 24, 30]
70 changes: 70 additions & 0 deletions tests/test_disc12_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Integration tests for the disc12 fixture scan results.

Disc12 is a five-episode bonus disc with commentary specials (same
structure as disc10):
- Play_all (00002.mpls, 6 clips, 31 chapters) decomposes into 5 episodes
at IG chapter marks [0, 6, 12, 18, 24]. Each episode ~24 min.
- Three individual playlists (00003-00005) duplicate episodes 2-4 with
commentary audio; detected as commentary specials via IG menu.
- Episodes 1 and 5 are play_all-only.
"""

import pytest

from bdpl.model import DiscAnalysis

pytestmark = pytest.mark.integration


class TestDisc12Episodes:
def test_finds_five_episodes(self, disc12_analysis: DiscAnalysis) -> None:
"""Disc12 should infer exactly five episodes from play_all."""
assert len(disc12_analysis.episodes) == 5

def test_episodes_are_ordered(self, disc12_analysis: DiscAnalysis) -> None:
"""Verify inferred episode sequence is [1..5]."""
assert [ep.episode for ep in disc12_analysis.episodes] == [1, 2, 3, 4, 5]

def test_all_episodes_from_play_all(self, disc12_analysis: DiscAnalysis) -> None:
"""All episodes should come from the play_all playlist."""
for ep in disc12_analysis.episodes:
assert ep.playlist == "00002.mpls"

def test_episode_durations_reasonable(self, disc12_analysis: DiscAnalysis) -> None:
"""Each episode should be ~20–28 min."""
for ep in disc12_analysis.episodes:
dur_min = ep.duration_ms / 60_000
assert 20 < dur_min < 28, f"Ep {ep.episode} duration {dur_min:.1f}min out of range"


class TestDisc12Specials:
def test_special_count(self, disc12_analysis: DiscAnalysis) -> None:
"""Disc12 should have 3 commentary specials."""
assert len(disc12_analysis.special_features) == 3

def test_all_commentaries(self, disc12_analysis: DiscAnalysis) -> None:
"""All specials should be commentary tracks."""
for sf in disc12_analysis.special_features:
assert sf.category == "commentary"

def test_commentary_playlists(self, disc12_analysis: DiscAnalysis) -> None:
"""Commentary tracks should reference individual episode playlists."""
playlists = {sf.playlist for sf in disc12_analysis.special_features}
assert playlists == {"00003.mpls", "00004.mpls", "00005.mpls"}


class TestDisc12Metadata:
def test_disc_title(self, disc12_analysis: DiscAnalysis) -> None:
"""Disc title should be extracted from META/DL/bdmt_eng.xml."""
assert disc12_analysis.disc_title == "TEST DISC 12"

def test_play_all_detected(self, disc12_analysis: DiscAnalysis) -> None:
"""00002.mpls should be classified as play_all."""
classes = disc12_analysis.analysis.get("classifications", {})
assert classes.get("00002.mpls") == "play_all"

def test_ig_chapter_marks(self, disc12_analysis: DiscAnalysis) -> None:
"""IG hints should report 5 chapter marks for episode starts."""
ig = disc12_analysis.analysis.get("disc_hints", {}).get("ig_menu", {})
marks = ig.get("chapter_marks", [])
assert marks == [0, 6, 12, 18, 24]
Loading