Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
3893f3f0
Commit
3893f3f0
authored
Mar 17, 2016
by
Sanford Student
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MA-2164 add youtube when mobile video encoding missing
parent
6ad750a1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
97 additions
and
23 deletions
+97
-23
common/lib/xmodule/xmodule/video_module/video_module.py
+25
-5
common/test/acceptance/pages/studio/video/video.py
+1
-1
lms/djangoapps/courseware/tests/test_video_mongo.py
+71
-17
No files found.
common/lib/xmodule/xmodule/video_module/video_module.py
View file @
3893f3f0
...
@@ -589,6 +589,20 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -589,6 +589,20 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
return
xml
return
xml
def
create_youtube_url
(
self
,
youtube_id
):
"""
Args:
youtube_id: The ID of the video to create a link for
Returns:
A full youtube url to the video whose ID is passed in
"""
if
youtube_id
:
return
'https://www.youtube.com/watch?v={0}'
.
format
(
youtube_id
)
else
:
return
''
def
get_context
(
self
):
def
get_context
(
self
):
"""
"""
Extend context by data for transcript basic tab.
Extend context by data for transcript basic tab.
...
@@ -612,10 +626,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -612,10 +626,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
if
val_youtube_id
:
if
val_youtube_id
:
video_id
=
val_youtube_id
video_id
=
val_youtube_id
if
video_id
:
return
self
.
create_youtube_url
(
video_id
)
return
'http://youtu.be/{0}'
.
format
(
video_id
)
else
:
return
''
_
=
self
.
runtime
.
service
(
self
,
"i18n"
)
.
ugettext
_
=
self
.
runtime
.
service
(
self
,
"i18n"
)
.
ugettext
video_url
.
update
({
video_url
.
update
({
...
@@ -848,7 +859,8 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -848,7 +859,8 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
val_video_data
=
edxval_api
.
get_video_info
(
self
.
edx_video_id
)
val_video_data
=
edxval_api
.
get_video_info
(
self
.
edx_video_id
)
# Unfortunately, the VAL API is inconsistent in how it returns the encodings, so remap here.
# Unfortunately, the VAL API is inconsistent in how it returns the encodings, so remap here.
for
enc_vid
in
val_video_data
.
pop
(
'encoded_videos'
):
for
enc_vid
in
val_video_data
.
pop
(
'encoded_videos'
):
encoded_videos
[
enc_vid
[
'profile'
]]
=
{
key
:
enc_vid
[
key
]
for
key
in
[
"url"
,
"file_size"
]}
if
enc_vid
[
'profile'
]
in
video_profile_names
:
encoded_videos
[
enc_vid
[
'profile'
]]
=
{
key
:
enc_vid
[
key
]
for
key
in
[
"url"
,
"file_size"
]}
except
edxval_api
.
ValVideoNotFoundError
:
except
edxval_api
.
ValVideoNotFoundError
:
pass
pass
...
@@ -861,6 +873,14 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -861,6 +873,14 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
"file_size"
:
0
,
# File size is unknown for fallback URLs
"file_size"
:
0
,
# File size is unknown for fallback URLs
}
}
# Include youtube link if there is no encoding for mobile- ie only a fallback URL or no encodings at all
# We are including a fallback URL for older versions of the mobile app that don't handle Youtube urls
if
self
.
youtube_id_1_0
:
encoded_videos
[
"youtube"
]
=
{
"url"
:
self
.
create_youtube_url
(
self
.
youtube_id_1_0
),
"file_size"
:
0
,
# File size is not relevant for external link
}
transcripts_info
=
self
.
get_transcripts_info
()
transcripts_info
=
self
.
get_transcripts_info
()
transcripts
=
{
transcripts
=
{
lang
:
self
.
runtime
.
handler_url
(
self
,
'transcript'
,
'download'
,
query
=
"lang="
+
lang
,
thirdparty
=
True
)
lang
:
self
.
runtime
.
handler_url
(
self
,
'transcript'
,
'download'
,
query
=
"lang="
+
lang
,
thirdparty
=
True
)
...
...
common/test/acceptance/pages/studio/video/video.py
View file @
3893f3f0
...
@@ -53,7 +53,7 @@ DISPLAY_NAME = "Component Display Name"
...
@@ -53,7 +53,7 @@ DISPLAY_NAME = "Component Display Name"
DEFAULT_SETTINGS
=
[
DEFAULT_SETTINGS
=
[
# basic
# basic
[
DISPLAY_NAME
,
'Video'
,
False
],
[
DISPLAY_NAME
,
'Video'
,
False
],
[
'Default Video URL'
,
'http
://youtu.be/
3_yD_cEKoCk, , '
,
False
],
[
'Default Video URL'
,
'http
s://www.youtube.com/watch?v=
3_yD_cEKoCk, , '
,
False
],
# advanced
# advanced
[
DISPLAY_NAME
,
'Video'
,
False
],
[
DISPLAY_NAME
,
'Video'
,
False
],
...
...
lms/djangoapps/courseware/tests/test_video_mongo.py
View file @
3893f3f0
...
@@ -1013,14 +1013,17 @@ class TestVideoDescriptorStudentViewJson(TestCase):
...
@@ -1013,14 +1013,17 @@ class TestVideoDescriptorStudentViewJson(TestCase):
'file_size'
:
222
,
'file_size'
:
222
,
}
}
TEST_EDX_VIDEO_ID
=
'test_edx_video_id'
TEST_EDX_VIDEO_ID
=
'test_edx_video_id'
TEST_YOUTUBE_ID
=
'test_youtube_id'
TEST_YOUTUBE_EXPECTED_URL
=
'https://www.youtube.com/watch?v=test_youtube_id'
def
setUp
(
self
):
def
setUp
(
self
):
super
(
TestVideoDescriptorStudentViewJson
,
self
)
.
setUp
()
super
(
TestVideoDescriptorStudentViewJson
,
self
)
.
setUp
()
sample_xml
=
(
video_declaration
=
"<video display_name='Test Video' youtube_id_1_0=
\'
"
+
self
.
TEST_YOUTUBE_ID
+
"
\'
>"
"<video display_name='Test Video'> "
+
sample_xml
=
''
.
join
([
"<source src='"
+
self
.
TEST_SOURCE_URL
+
"'/> "
+
video_declaration
,
"<transcript language='"
+
self
.
TEST_LANGUAGE
+
"' src='german_translation.srt' /> "
+
"<source src='"
,
self
.
TEST_SOURCE_URL
,
"'/> "
,
"</video>"
"<transcript language='"
,
self
.
TEST_LANGUAGE
,
"' src='german_translation.srt' /> "
,
"</video>"
]
)
)
self
.
transcript_url
=
"transcript_url"
self
.
transcript_url
=
"transcript_url"
self
.
video
=
instantiate_descriptor
(
data
=
sample_xml
)
self
.
video
=
instantiate_descriptor
(
data
=
sample_xml
)
...
@@ -1055,7 +1058,24 @@ class TestVideoDescriptorStudentViewJson(TestCase):
...
@@ -1055,7 +1058,24 @@ class TestVideoDescriptorStudentViewJson(TestCase):
}
}
return
self
.
video
.
student_view_data
(
context
)
return
self
.
video
.
student_view_data
(
context
)
def
verify_result_with_fallback_url
(
self
,
result
):
def
verify_result_with_fallback_and_youtube
(
self
,
result
):
"""
Verifies the result is as expected when returning "fallback" video data (not from VAL).
"""
self
.
assertDictEqual
(
result
,
{
"only_on_web"
:
False
,
"duration"
:
None
,
"transcripts"
:
{
self
.
TEST_LANGUAGE
:
self
.
transcript_url
},
"encoded_videos"
:
{
"fallback"
:
{
"url"
:
self
.
TEST_SOURCE_URL
,
"file_size"
:
0
},
"youtube"
:
{
"url"
:
self
.
TEST_YOUTUBE_EXPECTED_URL
,
"file_size"
:
0
}
},
}
)
def
verify_result_with_youtube_url
(
self
,
result
):
"""
"""
Verifies the result is as expected when returning "fallback" video data (not from VAL).
Verifies the result is as expected when returning "fallback" video data (not from VAL).
"""
"""
...
@@ -1065,7 +1085,7 @@ class TestVideoDescriptorStudentViewJson(TestCase):
...
@@ -1065,7 +1085,7 @@ class TestVideoDescriptorStudentViewJson(TestCase):
"only_on_web"
:
False
,
"only_on_web"
:
False
,
"duration"
:
None
,
"duration"
:
None
,
"transcripts"
:
{
self
.
TEST_LANGUAGE
:
self
.
transcript_url
},
"transcripts"
:
{
self
.
TEST_LANGUAGE
:
self
.
transcript_url
},
"encoded_videos"
:
{
"
fallback"
:
{
"url"
:
self
.
TEST_SOURCE
_URL
,
"file_size"
:
0
}},
"encoded_videos"
:
{
"
youtube"
:
{
"url"
:
self
.
TEST_YOUTUBE_EXPECTED
_URL
,
"file_size"
:
0
}},
}
}
)
)
...
@@ -1093,21 +1113,55 @@ class TestVideoDescriptorStudentViewJson(TestCase):
...
@@ -1093,21 +1113,55 @@ class TestVideoDescriptorStudentViewJson(TestCase):
def
test_no_edx_video_id
(
self
):
def
test_no_edx_video_id
(
self
):
result
=
self
.
get_result
()
result
=
self
.
get_result
()
self
.
verify_result_with_fallback_url
(
result
)
self
.
verify_result_with_fallback_and_youtube
(
result
)
def
test_no_edx_video_id_and_no_fallback
(
self
):
video_declaration
=
"<video display_name='Test Video' youtube_id_1_0=
\'
{}
\'
>"
.
format
(
self
.
TEST_YOUTUBE_ID
)
# the video has no source listed, only a youtube link, so no fallback url will be provided
sample_xml
=
''
.
join
([
video_declaration
,
"<transcript language='"
,
self
.
TEST_LANGUAGE
,
"' src='german_translation.srt' /> "
,
"</video>"
])
self
.
transcript_url
=
"transcript_url"
self
.
video
=
instantiate_descriptor
(
data
=
sample_xml
)
self
.
video
.
runtime
.
handler_url
=
Mock
(
return_value
=
self
.
transcript_url
)
result
=
self
.
get_result
()
self
.
verify_result_with_youtube_url
(
result
)
@ddt.data
(
@ddt.data
(
True
,
False
)
*
itertools
.
product
([
True
,
False
],
[
True
,
False
],
[
True
,
False
])
def
test_with_edx_video_id_video_associated_in_val
(
self
,
allow_cache_miss
):
)
"""
@ddt.unpack
Tests retrieving a video that is stored in VAL and associated with a course in VAL.
def
test_with_edx_video_id
(
self
,
allow_cache_miss
,
video_exists_in_val
,
associate_course_in_val
):
"""
self
.
video
.
edx_video_id
=
self
.
TEST_EDX_VIDEO_ID
self
.
video
.
edx_video_id
=
self
.
TEST_EDX_VIDEO_ID
if
video_exists_in_val
:
self
.
setup_val_video
(
associate_course_in_val
=
True
)
self
.
setup_val_video
(
associate_course_in_val
)
# the video is associated in VAL so no cache miss should ever happen but test retrieval in both contexts
result
=
self
.
get_result
(
allow_cache_miss
)
result
=
self
.
get_result
(
allow_cache_miss
)
if
video_exists_in_val
and
(
associate_course_in_val
or
allow_cache_miss
):
self
.
verify_result_with_val_profile
(
result
)
@ddt.data
(
True
,
False
)
def
test_with_edx_video_id_video_unassociated_in_val
(
self
,
allow_cache_miss
):
"""
Tests retrieving a video that is stored in VAL but not associated with a course in VAL.
"""
self
.
video
.
edx_video_id
=
self
.
TEST_EDX_VIDEO_ID
self
.
setup_val_video
(
associate_course_in_val
=
False
)
result
=
self
.
get_result
(
allow_cache_miss
)
if
allow_cache_miss
:
self
.
verify_result_with_val_profile
(
result
)
self
.
verify_result_with_val_profile
(
result
)
else
:
else
:
self
.
verify_result_with_fallback_url
(
result
)
self
.
verify_result_with_fallback_and_youtube
(
result
)
@ddt.data
(
True
,
False
)
def
test_with_edx_video_id_video_not_in_val
(
self
,
allow_cache_miss
):
"""
Tests retrieving a video that is not stored in VAL.
"""
self
.
video
.
edx_video_id
=
self
.
TEST_EDX_VIDEO_ID
# The video is not is VAL so in contexts that do and don't allow cache misses we should always get a fallback
result
=
self
.
get_result
(
allow_cache_miss
)
self
.
verify_result_with_fallback_and_youtube
(
result
)
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment