Merge branch 'codec-prio-from-cookie'
Addresses the desire to prefer codecs from the client. Some clients perform better with particular codecs put above, for instance the device has hardware decoding capabilities for it. Unfortunately there is no reliable way to query this in the frontend. Now we can set a cookie 'video_codecs_prio' with strings of codecs we want the order of importance. The cookie can contain codecs separated by a space. For instance 'vp8 h.264' to get those codecs first for an old 2014 laptop that has only hw support for these codecs. Supported codecs are the distinct ones in short_name in models.transcoding_types: vp9 vp8 h.264 After this works well in production, I can deside to build a user- friendly settings page.
This commit is contained in:
@@ -245,52 +245,6 @@ class VideoTestCase(UploadMixin, TestCase):
|
|||||||
content,
|
content,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_video_view_renders_transcoding_types_in_correct_order(self):
|
|
||||||
|
|
||||||
video = factories.create(
|
|
||||||
models.Video,
|
|
||||||
title='Vid 1',
|
|
||||||
slug='vid-1',
|
|
||||||
default_quality='480p',
|
|
||||||
)
|
|
||||||
factories.create(
|
|
||||||
models.Transcoding,
|
|
||||||
video=video,
|
|
||||||
quality='480p',
|
|
||||||
type='video/mp4; codecs="avc1.64001e,mp4a.40.2"',
|
|
||||||
url='http://480p.mp4',
|
|
||||||
)
|
|
||||||
factories.create(
|
|
||||||
models.Transcoding,
|
|
||||||
video=video,
|
|
||||||
quality='480p',
|
|
||||||
type='video/webm; codecs="vp9, opus"',
|
|
||||||
url='http://480p.vp9.webm',
|
|
||||||
)
|
|
||||||
factories.create(
|
|
||||||
models.Transcoding,
|
|
||||||
video=video,
|
|
||||||
quality='480p',
|
|
||||||
type='video/webm; codecs="vp8, vorbis"',
|
|
||||||
url='http://480p.vp8.webm',
|
|
||||||
)
|
|
||||||
|
|
||||||
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
|
||||||
|
|
||||||
self.assertEqual(resp.status_code, 200)
|
|
||||||
|
|
||||||
content:str = resp.content.decode(resp.charset)
|
|
||||||
|
|
||||||
self.assertInHTML(
|
|
||||||
"""<video width="853" height="480" controls="controls">
|
|
||||||
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
|
||||||
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
|
||||||
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
|
||||||
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
|
||||||
</video>""",
|
|
||||||
content,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class VideoWithTrackTestCase(UploadMixin, TestCase):
|
class VideoWithTrackTestCase(UploadMixin, TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -480,3 +434,228 @@ class VideoWithTrackTestCase(UploadMixin, TestCase):
|
|||||||
</video>""",
|
</video>""",
|
||||||
content,
|
content,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class VideoWithCodecOrderCookieTestCase(UploadMixin, TestCase):
|
||||||
|
""" Test the order of the codecs """
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.client = Client()
|
||||||
|
|
||||||
|
self.video = factories.create(
|
||||||
|
models.Video,
|
||||||
|
title='Vid 1',
|
||||||
|
slug='vid-1',
|
||||||
|
default_quality='480p',
|
||||||
|
)
|
||||||
|
factories.create(
|
||||||
|
models.Transcoding,
|
||||||
|
video=self.video,
|
||||||
|
quality='480p',
|
||||||
|
type='video/mp4; codecs="avc1.64001e,mp4a.40.2"',
|
||||||
|
url='http://480p.mp4',
|
||||||
|
)
|
||||||
|
factories.create(
|
||||||
|
models.Transcoding,
|
||||||
|
video=self.video,
|
||||||
|
quality='480p',
|
||||||
|
type='video/webm; codecs="vp9, opus"',
|
||||||
|
url='http://480p.vp9.webm',
|
||||||
|
)
|
||||||
|
factories.create(
|
||||||
|
models.Transcoding,
|
||||||
|
video=self.video,
|
||||||
|
quality='480p',
|
||||||
|
type='video/webm; codecs="vp8, vorbis"',
|
||||||
|
url='http://480p.vp8.webm',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_without_cookie(self):
|
||||||
|
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_empty_cookie(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = ''
|
||||||
|
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_only_vp8_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'vp8'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_only_h264_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'h.264'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_vp8_and_h264_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'vp8 h.264'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_h264_and_vp8_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'h.264 vp8'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_h264_and_vp9_and_vp8_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'h.264 vp9 vp8'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_h264_and_vp8_and_vp9_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'h.264 vp8 vp9'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_ignores_garbage_in_cookie(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'bwarpblergh crap bla'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_video_view_renders_transcoding_types_in_correct_order_with_h264_and_vp8_and_crap_and_vp9_mentioned(self):
|
||||||
|
|
||||||
|
self.client.cookies['video_codecs_prio'] = 'h.264 vp8 nonexistent-thing vp9'
|
||||||
|
resp:HttpResponse = self.client.get(reverse('video', args=['vid-1']))
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
content:str = resp.content.decode(resp.charset)
|
||||||
|
|
||||||
|
self.assertInHTML(
|
||||||
|
"""<video width="853" height="480" controls="controls">
|
||||||
|
<source src="http://480p.mp4" type='video/mp4; codecs="avc1.64001e,mp4a.40.2"' />
|
||||||
|
<source src="http://480p.vp8.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://480p.vp9.webm" type='video/webm; codecs="vp9, opus"' />
|
||||||
|
You need a browser that understands HTML5 video and supports h.264 or vp8 or vp9 codecs.
|
||||||
|
</video>""",
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|||||||
@@ -44,9 +44,12 @@ def video(request: HttpRequest, slug: str) -> HttpResponse:
|
|||||||
}
|
}
|
||||||
for transcoding in quality
|
for transcoding in quality
|
||||||
]
|
]
|
||||||
# sort by transcoding type priority
|
|
||||||
|
client_codec_prios = _get_codec_prios_from_client(request.COOKIES.get('video_codecs_prio', ''))
|
||||||
|
# sort by client desired order, or transcoding type priority
|
||||||
sources.sort(
|
sources.sort(
|
||||||
key=lambda i: models.get_transcoding_type_by_name(i['type']).priority,
|
key=lambda i: client_codec_prios.get(models.get_transcoding_type_by_name(i['type']).short_name) or \
|
||||||
|
models.get_transcoding_type_by_name(i['type']).priority,
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
template_data['sources'] = sources
|
template_data['sources'] = sources
|
||||||
@@ -92,3 +95,17 @@ def _url_for(transcoding: models.Transcoding) -> str:
|
|||||||
return transcoding.url
|
return transcoding.url
|
||||||
elif transcoding.upload:
|
elif transcoding.upload:
|
||||||
return transcoding.upload.file.url
|
return transcoding.upload.file.url
|
||||||
|
|
||||||
|
def _get_codec_prios_from_client(prio_string: str) -> Dict[str, int]:
|
||||||
|
"""
|
||||||
|
Get prios from prio string.
|
||||||
|
For they are more important than build-in prios, they have
|
||||||
|
values higher than the max value of the build-in prios.
|
||||||
|
"""
|
||||||
|
max_prio = max(tt.priority for tt in models.transcoding_types) + 1
|
||||||
|
client_codecs_prio = prio_string.split(' ')
|
||||||
|
client_codecs_prio.reverse()
|
||||||
|
return {
|
||||||
|
v: max_prio + i
|
||||||
|
for i, v in enumerate(client_codecs_prio)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user