stream.dash: ContentProtection in Representation

This commit is contained in:
bastimeyer 2023-02-24 02:24:02 +01:00 committed by Forrest
parent 11de140658
commit e2e41987ae
3 changed files with 117 additions and 106 deletions

View File

@ -261,8 +261,10 @@ class DASHStream(Stream):
# Search for suitable video and audio representations
for aset in mpd.periods[0].adaptationSets:
if aset.contentProtection:
raise PluginError("{} is protected by DRM".format(url))
raise PluginError(f"{url} is protected by DRM")
for rep in aset.representations:
if rep.contentProtection:
raise PluginError(f"{url} is protected by DRM")
if rep.mimeType.startswith("video"):
video.append(rep)
elif rep.mimeType.startswith("audio"):

View File

@ -803,6 +803,7 @@ class Representation(MPDNode):
self.segmentBase = self.only_child(SegmentBase)
self.segmentList = self.children(SegmentList)
self.segmentTemplate = self.only_child(SegmentTemplate)
self.contentProtection = self.children(ContentProtection)
@property
def bandwidth_rounded(self) -> float:

View File

@ -18,15 +18,14 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_video_only(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -35,15 +34,14 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_only(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="audio/mp4", bandwidth=128.0, lang="en"),
Mock(id=2, mimeType="audio/mp4", bandwidth=256.0, lang="en"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="audio/mp4", bandwidth=128.0, lang="en"),
Mock(id="2", contentProtection=None, mimeType="audio/mp4", bandwidth=256.0, lang="en"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -52,16 +50,15 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_single(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="en"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="en"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -70,17 +67,16 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_multi(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id=4, mimeType="audio/aac", bandwidth=256.0, lang="en"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id="4", contentProtection=None, mimeType="audio/aac", bandwidth=256.0, lang="en"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -89,17 +85,16 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_multi_lang(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang="es"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id="4", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="es"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -111,17 +106,16 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_multi_lang_alpha3(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="eng"),
Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang="spa"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="eng"),
Mock(id="4", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="spa"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -133,16 +127,15 @@ class TestDASHStream(unittest.TestCase):
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_audio_invalid_lang(self, mpdClass):
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="en_no_voice"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="en_no_voice"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -157,17 +150,16 @@ class TestDASHStream(unittest.TestCase):
self.session.localization.language.alpha2 = "es"
self.session.localization.explicit = True
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=720),
Mock(id=2, mimeType="video/mp4", height=1080),
Mock(id=3, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id=4, mimeType="audio/aac", bandwidth=128.0, lang="es"),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=720),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080),
Mock(id="3", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="en"),
Mock(id="4", contentProtection=None, mimeType="audio/aac", bandwidth=128.0, lang="es"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -178,8 +170,26 @@ class TestDASHStream(unittest.TestCase):
assert streams["1080p"].audio_representation.lang == "es"
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_drm(self, mpdClass):
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[Mock(contentProtection="DRM")])])
def test_parse_manifest_drm_adaptationset(self, mpdClass):
adaptationset = Mock(
contentProtection="DRM",
representations=[],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
with pytest.raises(PluginError):
DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@patch("streamlink.stream.dash.MPD")
def test_parse_manifest_drm_representation(self, mpdClass):
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection="DRM"),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
with pytest.raises(PluginError):
DASHStream.parse_manifest(self.session, self.test_url)
@ -238,17 +248,16 @@ class TestDASHStream(unittest.TestCase):
"""
Verify the fix for https://github.com/streamlink/streamlink/issues/3365
"""
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=1080, bandwidth=128.0),
Mock(id=2, mimeType="video/mp4", height=1080, bandwidth=64.0),
Mock(id=3, mimeType="video/mp4", height=1080, bandwidth=32.0),
Mock(id=4, mimeType="video/mp4", height=720),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=128.0),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=64.0),
Mock(id="3", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=32.0),
Mock(id="4", contentProtection=None, mimeType="video/mp4", height=720),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")
@ -260,16 +269,15 @@ class TestDASHStream(unittest.TestCase):
"""
Verify the fix for https://github.com/streamlink/streamlink/issues/4217
"""
mpdClass.return_value = Mock(periods=[
Mock(adaptationSets=[
Mock(contentProtection=None,
representations=[
Mock(id=1, mimeType="video/mp4", height=1080, bandwidth=64.0),
Mock(id=2, mimeType="video/mp4", height=1080, bandwidth=128.0),
Mock(id=3, mimeType="video/mp4", height=1080, bandwidth=32.0),
]),
]),
])
adaptationset = Mock(
contentProtection=None,
representations=[
Mock(id="1", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=64.0),
Mock(id="2", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=128.0),
Mock(id="3", contentProtection=None, mimeType="video/mp4", height=1080, bandwidth=32.0),
],
)
mpdClass.return_value = Mock(periods=[Mock(adaptationSets=[adaptationset])])
streams = DASHStream.parse_manifest(self.session, self.test_url)
mpdClass.assert_called_with(ANY, base_url="http://test.bar", url="http://test.bar/foo.mpd")