Deprecate Contentstore for Video Component Preview LMS/CMS

EDUCATOR-1756
This commit is contained in:
muhammad-ammar
2018-03-15 11:56:54 +05:00
parent 8c66d86704
commit d0cd247d08
9 changed files with 116 additions and 157 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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))

View File

@@ -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)