Skip to content

Commit e235419

Browse files
committed
feat: load video poster from Educast videos
Load the video poster for videos that are stored from Educast. So the migration to use the desktop mp4 migration to use the real stream m3u8 format will continue to show the video poster (preview, thumbnail). fccn/nau-technical#708
1 parent 7ba3c39 commit e235419

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

nau_openedx_extensions/apps.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,17 @@ def ready(self):
4040
"""
4141
Method to perform actions after apps registry is ended
4242
"""
43+
# Override the default Video xBlock the _poster private function.
44+
# Override the class was giving more work because of the html dependencies
45+
# was being loaded from the new package. So it was more easy just replace the
46+
# method implementation.
47+
from xmodule.video_block.video_block import \
48+
VideoBlock # pylint: disable=import-error,import-outside-toplevel # noqa
49+
4350
from nau_openedx_extensions import signals # pylint: disable=import-outside-toplevel,unused-import # noqa
51+
from nau_openedx_extensions.xblocks.video_block import \
52+
get_educast_poster_factory # pylint: disable=import-outside-toplevel # noqa
53+
54+
# Replace the method in the original VideoBlock class
55+
prev_poster_func = VideoBlock._poster # pylint: disable=protected-access
56+
VideoBlock._poster = get_educast_poster_factory(prev_poster_func) # pylint: disable=protected-access

nau_openedx_extensions/xblocks/__init__.py

Whitespace-only changes.

nau_openedx_extensions/xblocks/tests/__init__.py

Whitespace-only changes.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""
2+
Test cases for the customized VideoBlock _poster method for Educast videos.
3+
"""
4+
from django.test import TestCase
5+
6+
from nau_openedx_extensions.xblocks.video_block import get_educast_poster_factory
7+
8+
9+
class FakeVideoBlock():
10+
"""
11+
A fake VideoBlock XBlock class for testing
12+
"""
13+
def __init__(self):
14+
self.html5_sources = {}
15+
16+
17+
class TestVideoBlock(TestCase):
18+
"""
19+
Test cases for the customized VideoBlock _poster method for Educast videos.
20+
"""
21+
def test_get_educast_poster_https(self):
22+
"""
23+
Test the customized _poster method for VideoBlock.
24+
"""
25+
# Create a mock previous _poster method
26+
def mock_prev_poster(self): # pylint: disable=unused-argument
27+
return None
28+
29+
# Create the customized _poster method
30+
customized_poster_method = get_educast_poster_factory(mock_prev_poster)
31+
32+
# Create an instance of VideoBlock and set html5_sources
33+
video_block = FakeVideoBlock()
34+
video_block.html5_sources = ['https://dev.educast.fccn.pt/vod/clips/bum66sthd/streaming.m3u8']
35+
36+
# Call the customized _poster method
37+
poster_url = customized_poster_method(video_block)
38+
39+
# Verify the poster URL is as expected
40+
expected_url = 'https://dev.educast.fccn.pt/img/clips/bum66sthd/delivery/cover'
41+
self.assertEqual(poster_url, expected_url)
42+
43+
def test_get_educast_poster_http(self):
44+
"""
45+
Test the customized _poster method for VideoBlock.
46+
"""
47+
# Create a mock previous _poster method
48+
def mock_prev_poster(self): # pylint: disable=unused-argument
49+
return None
50+
51+
# Create the customized _poster method
52+
customized_poster_method = get_educast_poster_factory(mock_prev_poster)
53+
54+
# Create an instance of VideoBlock and set html5_sources
55+
video_block = FakeVideoBlock()
56+
video_block.html5_sources = ['http://educast.fccn.pt/vod/clips/fdgfdgfdgfdg/streaming.m3u8']
57+
58+
# Call the customized _poster method
59+
poster_url = customized_poster_method(video_block)
60+
61+
# Verify the poster URL is as expected
62+
expected_url = 'http://educast.fccn.pt/img/clips/fdgfdgfdgfdg/delivery/cover'
63+
self.assertEqual(poster_url, expected_url)
64+
65+
def test_get_educast_poster_no_protocol(self):
66+
"""
67+
Test the customized _poster method for VideoBlock.
68+
"""
69+
# Create a mock previous _poster method
70+
def mock_prev_poster(self): # pylint: disable=unused-argument
71+
return None
72+
73+
# Create the customized _poster method
74+
customized_poster_method = get_educast_poster_factory(mock_prev_poster)
75+
76+
# Create an instance of VideoBlock and set html5_sources
77+
video_block = FakeVideoBlock()
78+
video_block.html5_sources = ['//educast.fccn.pt/vod/clips/aaaaaa/streaming.m3u8']
79+
80+
# Call the customized _poster method
81+
poster_url = customized_poster_method(video_block)
82+
83+
# Verify the poster URL is as expected
84+
expected_url = '//educast.fccn.pt/img/clips/aaaaaa/delivery/cover'
85+
self.assertEqual(poster_url, expected_url)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Custom video block extensions for NAU Open edX.
3+
"""
4+
import re
5+
6+
7+
def get_educast_poster_factory(prev_poster_func):
8+
"""
9+
Factory to create a customized _poster method for VideoBlock.
10+
This allows us to inject custom logic while retaining access to the original method.
11+
"""
12+
13+
def get_educast_poster(self):
14+
"""
15+
Override the default poster URL logic to customize the poster image.
16+
"""
17+
poster_url = prev_poster_func(self)
18+
if not poster_url and self.html5_sources:
19+
video_src = next(iter(self.html5_sources), None)
20+
is_educast = 'educast.fccn.pt' in video_src # to work for both educast staging and production
21+
if is_educast:
22+
# from video src like https://staging.educast.fccn.pt/vod/clips/bum66sthd/streaming.m3u8
23+
# extract the server base url https://educast.fccn.pt or http://educast.fccn.pt or //educast.fccn.pt
24+
server_base_url = re.match(r'^(https?://[^/]+|//[^/]+)', video_src).group(1)
25+
# extract the educast video id like bumu66sthd
26+
educast_video_id = re.search(r'/clips/([^/]+)/', video_src).group(1)
27+
# construct poster url like https://educast.fccn.pt/img/clips/jpojtray/delivery/cover
28+
poster_url = f"{server_base_url}/img/clips/{educast_video_id}/delivery/cover"
29+
return poster_url
30+
31+
return get_educast_poster

0 commit comments

Comments
 (0)