Commit c23a05b5 by Carson Gee

Merge pull request #3213 from carsongee/cg/video_transcript_static

Add static fallback method for video transcripts
parents e1e87e1a c0644dc9
...@@ -11,6 +11,7 @@ from webob import Response ...@@ -11,6 +11,7 @@ from webob import Response
from xblock.core import XBlock from xblock.core import XBlock
from xmodule.course_module import CourseDescriptor
from xmodule.exceptions import NotFoundError from xmodule.exceptions import NotFoundError
from xmodule.fields import RelativeTime from xmodule.fields import RelativeTime
...@@ -22,6 +23,7 @@ from .transcripts_utils import ( ...@@ -22,6 +23,7 @@ from .transcripts_utils import (
youtube_speed_dict, youtube_speed_dict,
Transcript, Transcript,
save_to_store, save_to_store,
subs_filename
) )
...@@ -171,6 +173,39 @@ class VideoStudentViewHandlers(object): ...@@ -171,6 +173,39 @@ class VideoStudentViewHandlers(object):
return content, filename, Transcript.mime_types[transcript_format] return content, filename, Transcript.mime_types[transcript_format]
def get_static_transcript(self, request):
"""
Courses that are imported with the --nostatic flag do not show
transcripts/captions properly even if those captions are stored inside
their static folder. This adds a last resort method of redirecting to
the static asset path of the course if the transcript can't be found
inside the contentstore and the course has the static_asset_path field
set.
"""
response = Response(status=404)
# Only do redirect for English
if not self.transcript_language == 'en':
return response
video_id = request.GET.get('videoId', None)
if video_id:
transcript_name = video_id
else:
transcript_name = self.sub
if transcript_name:
course_location = CourseDescriptor.id_to_location(self.course_id)
course = self.descriptor.runtime.modulestore.get_item(course_location)
if course.static_asset_path:
response = Response(
status=307,
location='/static/{0}/{1}'.format(
course.static_asset_path,
subs_filename(transcript_name, self.transcript_language)
)
)
return response
@XBlock.handler @XBlock.handler
def transcript(self, request, dispatch): def transcript(self, request, dispatch):
""" """
...@@ -206,13 +241,17 @@ class VideoStudentViewHandlers(object): ...@@ -206,13 +241,17 @@ class VideoStudentViewHandlers(object):
if language != self.transcript_language: if language != self.transcript_language:
self.transcript_language = language self.transcript_language = language
try: try:
transcript = self.translation(request.GET.get('videoId', None)) transcript = self.translation(request.GET.get('videoId', None))
except NotFoundError, ex:
log.info(ex.message)
# Try to return static URL redirection as last resort
# if no translation is required
return self.get_static_transcript(request)
except ( except (
TranscriptException, TranscriptException,
NotFoundError,
UnicodeDecodeError, UnicodeDecodeError,
TranscriptException,
TranscriptsGenerationException TranscriptsGenerationException
) as ex: ) as ex:
log.info(ex.message) log.info(ex.message)
......
...@@ -10,8 +10,9 @@ from datetime import timedelta ...@@ -10,8 +10,9 @@ from datetime import timedelta
from webob import Request from webob import Request
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
from xmodule.modulestore import Location
from xmodule.contentstore.django import contentstore from xmodule.contentstore.django import contentstore
from xmodule.modulestore import Location
from xmodule.modulestore.django import editable_modulestore
from . import BaseTestXmodule from . import BaseTestXmodule
from .test_video_xml import SOURCE_XML from .test_video_xml import SOURCE_XML
from cache_toolbox.core import del_cached_content from cache_toolbox.core import del_cached_content
...@@ -225,6 +226,7 @@ class TestTranscriptDownloadDispatch(TestVideo): ...@@ -225,6 +226,7 @@ class TestTranscriptDownloadDispatch(TestVideo):
DATA = """ DATA = """
<video show_captions="true" <video show_captions="true"
display_name="A Name" display_name="A Name"
sub='OEoXaMPEzfM'
> >
<source src="example.mp4"/> <source src="example.mp4"/>
<source src="example.webm"/> <source src="example.webm"/>
...@@ -402,6 +404,41 @@ class TestTranscriptTranslationGetDispatch(TestVideo): ...@@ -402,6 +404,41 @@ class TestTranscriptTranslationGetDispatch(TestVideo):
response = self.item.transcript(request=request, dispatch='translation/uk') response = self.item.transcript(request=request, dispatch='translation/uk')
self.assertDictEqual(json.loads(response.body), subs) self.assertDictEqual(json.loads(response.body), subs)
def test_translation_static_transcript(self):
"""
Set course static_asset_path and ensure we get redirected to that path
if it isn't found in the contentstore
"""
self.course.static_asset_path = 'dummy/static'
self.course.save()
store = editable_modulestore()
store.update_item(self.course, 'OEoXaMPEzfM')
# Test youtube style en
request = Request.blank('/translation/en?videoId=12345')
response = self.item.transcript(request=request, dispatch='translation/en')
self.assertEqual(response.status, '307 Temporary Redirect')
self.assertIn(
('Location', '/static/dummy/static/subs_12345.srt.sjson'),
response.headerlist
)
# Test HTML5 video style
self.item.sub = 'OEoXaMPEzfM'
request = Request.blank('/translation/en')
response = self.item.transcript(request=request, dispatch='translation/en')
self.assertEqual(response.status, '307 Temporary Redirect')
self.assertIn(
('Location', '/static/dummy/static/subs_OEoXaMPEzfM.srt.sjson'),
response.headerlist
)
# Test different language to ensure we are just ignoring it since we can't
# translate with static fallback
request = Request.blank('/translation/uk')
response = self.item.transcript(request=request, dispatch='translation/uk')
self.assertEqual(response.status, '404 Not Found')
class TestStudioTranscriptTranslationGetDispatch(TestVideo): class TestStudioTranscriptTranslationGetDispatch(TestVideo):
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment