Deprecate Contentstore for Video Component Preview LMS/CMS
EDUCATOR-1756
This commit is contained in:
@@ -12,6 +12,7 @@ You can then use the CourseFactory and XModuleItemFactory as defined
|
||||
in common/lib/xmodule/xmodule/modulestore/tests/factories.py to create
|
||||
the course, section, subsection, unit, etc.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
import datetime
|
||||
@@ -913,9 +914,11 @@ class VideoDescriptorStudentViewDataTestCase(unittest.TestCase):
|
||||
|
||||
@patch('xmodule.video_module.video_module.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
|
||||
@patch('xmodule.video_module.video_module.is_val_transcript_feature_enabled_for_course', Mock(return_value=False))
|
||||
@patch('xmodule.video_module.transcripts_utils.get_available_transcript_languages', Mock(return_value=['es']))
|
||||
@patch('edxval.api.get_video_info_for_course_and_profiles', Mock(return_value={}))
|
||||
@patch('xmodule.video_module.transcripts_utils.get_video_transcript_content')
|
||||
@patch('edxval.api.get_video_info')
|
||||
def test_student_view_data_with_hls_flag(self, mock_get_video_info):
|
||||
def test_student_view_data_with_hls_flag(self, mock_get_video_info, mock_get_video_transcript_content):
|
||||
mock_get_video_info.return_value = {
|
||||
'url': '/edxval/video/example',
|
||||
'edx_video_id': u'example_id',
|
||||
@@ -931,8 +934,18 @@ class VideoDescriptorStudentViewDataTestCase(unittest.TestCase):
|
||||
]
|
||||
}
|
||||
|
||||
mock_get_video_transcript_content.return_value = {
|
||||
'content': json.dumps({
|
||||
"start": [10],
|
||||
"end": [100],
|
||||
"text": ["Hi, welcome to Edx."],
|
||||
}),
|
||||
'file_name': 'edx.sjson'
|
||||
}
|
||||
|
||||
descriptor = instantiate_descriptor(edx_video_id='example_id', only_on_web=False)
|
||||
descriptor.runtime.course_id = MagicMock()
|
||||
descriptor.runtime.handler_url = MagicMock()
|
||||
student_view_data = descriptor.student_view_data()
|
||||
expected_video_data = {u'hls': {'url': u'http://www.meowmix.com', 'file_size': 25556}}
|
||||
self.assertDictEqual(student_view_data.get('encoded_videos'), expected_video_data)
|
||||
|
||||
@@ -827,7 +827,7 @@ class VideoTranscriptsMixin(object):
|
||||
transcript_language = u'en'
|
||||
return transcript_language
|
||||
|
||||
def get_transcripts_info(self, is_bumper=False, include_val_transcripts=False):
|
||||
def get_transcripts_info(self, is_bumper=False):
|
||||
"""
|
||||
Returns a transcript dictionary for the video.
|
||||
|
||||
@@ -848,9 +848,8 @@ class VideoTranscriptsMixin(object):
|
||||
for language_code, transcript_file in transcripts.items() if transcript_file != ''
|
||||
}
|
||||
|
||||
# For phase 2, removing `include_val_transcripts` will make edx-val
|
||||
# taking over the control for transcripts.
|
||||
if include_val_transcripts:
|
||||
# bumper transcripts are stored in content store so we don't need check them in val
|
||||
if not is_bumper:
|
||||
transcript_languages = get_available_transcript_languages(edx_video_id=self.edx_video_id)
|
||||
# HACK Warning! this is temporary and will be removed once edx-val take over the
|
||||
# transcript module and contentstore will only function as fallback until all the
|
||||
|
||||
@@ -31,6 +31,8 @@ from .transcripts_utils import (
|
||||
TranscriptException,
|
||||
TranscriptsGenerationException,
|
||||
youtube_speed_dict,
|
||||
get_transcript,
|
||||
get_transcript_from_contentstore
|
||||
)
|
||||
from .transcripts_model_utils import (
|
||||
is_val_transcript_feature_enabled_for_course
|
||||
@@ -246,6 +248,36 @@ class VideoStudentViewHandlers(object):
|
||||
self.runtime.publish(self, "completion", data)
|
||||
return {"result": "ok"}
|
||||
|
||||
@staticmethod
|
||||
def make_transcript_http_response(content, filename, language, content_type, add_attachment_header=True):
|
||||
"""
|
||||
Construct `Response` object.
|
||||
|
||||
Arguments:
|
||||
content (unicode): transcript content
|
||||
filename (unicode): transcript filename
|
||||
language (unicode): transcript language
|
||||
mimetype (unicode): transcript content type
|
||||
add_attachment_header (bool): whether to add attachment header or not
|
||||
"""
|
||||
headerlist = [
|
||||
('Content-Language', language),
|
||||
]
|
||||
|
||||
if add_attachment_header:
|
||||
headerlist.append(
|
||||
('Content-Disposition', 'attachment; filename="{}"'.format(filename.encode('utf-8')))
|
||||
)
|
||||
|
||||
response = Response(
|
||||
content,
|
||||
headerlist=headerlist,
|
||||
charset='utf8'
|
||||
)
|
||||
response.content_type = content_type
|
||||
|
||||
return response
|
||||
|
||||
@XBlock.handler
|
||||
def transcript(self, request, dispatch):
|
||||
"""
|
||||
@@ -270,9 +302,8 @@ class VideoStudentViewHandlers(object):
|
||||
For 'en' check if SJSON exists. For non-`en` check if SRT file exists.
|
||||
"""
|
||||
is_bumper = request.GET.get('is_bumper', False)
|
||||
# Currently, we don't handle video pre-load/bumper transcripts in edx-val.
|
||||
feature_enabled = is_val_transcript_feature_enabled_for_course(self.course_id) and not is_bumper
|
||||
transcripts = self.get_transcripts_info(is_bumper, include_val_transcripts=feature_enabled)
|
||||
transcripts = self.get_transcripts_info(is_bumper)
|
||||
|
||||
if dispatch.startswith('translation'):
|
||||
language = dispatch.replace('translation', '').strip('/')
|
||||
|
||||
@@ -288,85 +319,52 @@ class VideoStudentViewHandlers(object):
|
||||
self.transcript_language = language
|
||||
|
||||
try:
|
||||
transcript = self.translation(request.GET.get('videoId', None), transcripts)
|
||||
except (TypeError, TranscriptException, NotFoundError) as ex:
|
||||
# Catching `TranscriptException` because its also getting raised at places
|
||||
# when transcript is not found in contentstore.
|
||||
log.debug(six.text_type(ex))
|
||||
# Try to return static URL redirection as last resort
|
||||
# if no translation is required
|
||||
response = self.get_static_transcript(request, transcripts)
|
||||
if response.status_code == 404 and feature_enabled:
|
||||
# Try to get transcript from edx-val as a last resort.
|
||||
transcript = get_video_transcript_content(self.edx_video_id, self.transcript_language)
|
||||
if transcript:
|
||||
transcript_conversion_props = dict(transcript, output_format=Transcript.SJSON)
|
||||
transcript = convert_video_transcript(**transcript_conversion_props)
|
||||
response = Response(
|
||||
transcript['content'],
|
||||
headerlist=[('Content-Language', self.transcript_language)],
|
||||
charset='utf8',
|
||||
)
|
||||
response.content_type = Transcript.mime_types[Transcript.SJSON]
|
||||
if is_bumper:
|
||||
content, filename, mimetype = get_transcript_from_contentstore(
|
||||
self,
|
||||
self.transcript_language,
|
||||
Transcript.SJSON,
|
||||
transcripts
|
||||
)
|
||||
else:
|
||||
content, filename, mimetype = get_transcript(
|
||||
self,
|
||||
lang=self.transcript_language,
|
||||
output_format=Transcript.SJSON,
|
||||
youtube_id=request.GET.get('videoId'),
|
||||
)
|
||||
|
||||
return response
|
||||
except (UnicodeDecodeError, TranscriptsGenerationException) as ex:
|
||||
log.info(six.text_type(ex))
|
||||
response = Response(status=404)
|
||||
else:
|
||||
response = Response(transcript, headerlist=[('Content-Language', language)])
|
||||
response.content_type = Transcript.mime_types['sjson']
|
||||
response = self.make_transcript_http_response(
|
||||
content,
|
||||
filename,
|
||||
self.transcript_language,
|
||||
mimetype,
|
||||
add_attachment_header=False
|
||||
)
|
||||
except NotFoundError:
|
||||
log.exception('[Translation Dispatch] %s', self.location)
|
||||
response = self.get_static_transcript(request, transcripts)
|
||||
|
||||
elif dispatch == 'download':
|
||||
lang = request.GET.get('lang', None)
|
||||
|
||||
try:
|
||||
transcript_content, transcript_filename, transcript_mime_type = self.get_transcript(
|
||||
transcripts, transcript_format=self.transcript_download_format, lang=lang
|
||||
)
|
||||
except (KeyError, UnicodeDecodeError):
|
||||
content, filename, mimetype = get_transcript(self, lang)
|
||||
except NotFoundError:
|
||||
return Response(status=404)
|
||||
except (ValueError, NotFoundError):
|
||||
response = Response(status=404)
|
||||
# Check for transcripts in edx-val as a last resort if corresponding feature is enabled.
|
||||
if feature_enabled:
|
||||
# Make sure the language is set.
|
||||
if not lang:
|
||||
lang = self.get_default_transcript_language(transcripts)
|
||||
|
||||
transcript = get_video_transcript_content(edx_video_id=self.edx_video_id, language_code=lang)
|
||||
if transcript:
|
||||
transcript_conversion_props = dict(transcript, output_format=self.transcript_download_format)
|
||||
transcript = convert_video_transcript(**transcript_conversion_props)
|
||||
response = Response(
|
||||
transcript['content'],
|
||||
headerlist=[
|
||||
('Content-Disposition', 'attachment; filename="{filename}"'.format(
|
||||
filename=transcript['filename']
|
||||
)),
|
||||
('Content-Language', lang),
|
||||
],
|
||||
charset='utf8',
|
||||
)
|
||||
response.content_type = Transcript.mime_types[self.transcript_download_format]
|
||||
|
||||
return response
|
||||
else:
|
||||
response = Response(
|
||||
transcript_content,
|
||||
headerlist=[
|
||||
('Content-Disposition', 'attachment; filename="{}"'.format(transcript_filename.encode('utf8'))),
|
||||
('Content-Language', self.transcript_language),
|
||||
],
|
||||
charset='utf8'
|
||||
)
|
||||
response.content_type = transcript_mime_type
|
||||
|
||||
response = self.make_transcript_http_response(
|
||||
content,
|
||||
filename,
|
||||
self.transcript_language,
|
||||
mimetype
|
||||
)
|
||||
elif dispatch.startswith('available_translations'):
|
||||
|
||||
feature_enabled = is_val_transcript_feature_enabled_for_course(self.course_id) and not is_bumper
|
||||
available_translations = self.available_translations(
|
||||
transcripts,
|
||||
verify_assets=True,
|
||||
include_val_transcripts=feature_enabled,
|
||||
include_val_transcripts=feature_enabled
|
||||
)
|
||||
if available_translations:
|
||||
response = Response(json.dumps(available_translations))
|
||||
|
||||
@@ -304,8 +304,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
|
||||
if download_video_link and download_video_link.endswith('.m3u8'):
|
||||
download_video_link = None
|
||||
|
||||
feature_enabled = is_val_transcript_feature_enabled_for_course(self.course_id)
|
||||
transcripts = self.get_transcripts_info(include_val_transcripts=feature_enabled)
|
||||
transcripts = self.get_transcripts_info()
|
||||
track_url, transcript_language, sorted_languages = self.get_transcripts_for_student(transcripts=transcripts)
|
||||
|
||||
# CDN_VIDEO_URLS is only to be used here and will be deleted
|
||||
@@ -1099,7 +1098,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
}
|
||||
|
||||
feature_enabled = is_val_transcript_feature_enabled_for_course(self.runtime.course_id.for_branch(None))
|
||||
transcripts_info = self.get_transcripts_info(include_val_transcripts=feature_enabled)
|
||||
transcripts_info = self.get_transcripts_info()
|
||||
available_translations = self.available_translations(transcripts_info, include_val_transcripts=feature_enabled)
|
||||
transcripts = {
|
||||
lang: self.runtime.handler_url(self, 'transcript', 'download', query="lang=" + lang, thirdparty=True)
|
||||
|
||||
Reference in New Issue
Block a user