Unverified Commit 549c0f6b by Muhammad Ammar Committed by GitHub

Merge pull request #16422 from edx/ammar/add-video-duration-to-events

add video duration to events
parents a6254d50 feee5750
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div <div
id="video_id" id="video_id"
class="video closed" class="video closed"
data-metadata='{"autohideHtml5": "true", "autoplay": "false", "captionDataDir": "", "endTime": "", "generalSpeed": "1.0", "saveStateUrl": "/save_user_state", "savedVideoPosition": "0", "showCaptions": "true", "sources": ["/base/fixtures/hls/hls.m3u8", "/base/fixtures/test.mp4","/base/fixtures/test.webm"], "speed": "1.5", "startTime": "", "streams": "", "sub": "Z5KLxerq05Y", "transcriptAvailableTranslationsUrl": "/transcript/available_translations", "transcriptLanguage": "en", "transcriptLanguages": {"en": "English", "de": "Deutsch", "zh": "普通话"}, "transcriptTranslationUrl": "/transcript/translation/__lang__", "ytApiUrl": "/base/fixtures/youtube_iframe_api.js", "ytImageUrl": "", "ytTestTimeout": "1500", "ytMetadataUrl": "www.googleapis.com/youtube/v3/videos/", "source": "", "poster": "/media/video-images/poster.png"}' data-metadata='{"duration": 111, "autohideHtml5": "true", "autoplay": "false", "captionDataDir": "", "endTime": "", "generalSpeed": "1.0", "saveStateUrl": "/save_user_state", "savedVideoPosition": "0", "showCaptions": "true", "sources": ["/base/fixtures/hls/hls.m3u8", "/base/fixtures/test.mp4","/base/fixtures/test.webm"], "speed": "1.5", "startTime": "", "streams": "", "sub": "Z5KLxerq05Y", "transcriptAvailableTranslationsUrl": "/transcript/available_translations", "transcriptLanguage": "en", "transcriptLanguages": {"en": "English", "de": "Deutsch", "zh": "普通话"}, "transcriptTranslationUrl": "/transcript/translation/__lang__", "ytApiUrl": "/base/fixtures/youtube_iframe_api.js", "ytImageUrl": "", "ytTestTimeout": "1500", "ytMetadataUrl": "www.googleapis.com/youtube/v3/videos/", "source": "", "poster": "/media/video-images/poster.png"}'
> >
<div class="focus_grabber first"></div> <div class="focus_grabber first"></div>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div <div
id="video_id" id="video_id"
class="video closed" class="video closed"
data-metadata='{"autohideHtml5": "true", "autoplay": "false", "captionDataDir": "", "endTime": "", "generalSpeed": "1.0", "saveStateUrl": "/save_user_state", "savedVideoPosition": "0", "showCaptions": "true", "sources": ["/base/fixtures/test.mp4","/base/fixtures/test.webm","/base/fixtures/test.ogv"], "speed": "1.5", "startTime": "", "streams": "", "sub": "Z5KLxerq05Y", "transcriptAvailableTranslationsUrl": "/transcript/available_translations", "transcriptLanguage": "en", "transcriptLanguages": {"en": "English", "de": "Deutsch", "zh": "普通话"}, "transcriptTranslationUrl": "/transcript/translation/__lang__", "ytApiUrl": "/base/fixtures/youtube_iframe_api.js", "ytImageUrl": "", "ytTestTimeout": "1500", "ytMetadataUrl": "www.googleapis.com/youtube/v3/videos/", "source": "", "html5_sources": ["http://youtu.be/3_yD_cEKoCk.mp4"], "poster": "/media/video-images/poster.png"}' data-metadata='{"duration": 111, "autohideHtml5": "true", "autoplay": "false", "captionDataDir": "", "endTime": "", "generalSpeed": "1.0", "saveStateUrl": "/save_user_state", "savedVideoPosition": "0", "showCaptions": "true", "sources": ["/base/fixtures/test.mp4","/base/fixtures/test.webm","/base/fixtures/test.ogv"], "speed": "1.5", "startTime": "", "streams": "", "sub": "Z5KLxerq05Y", "transcriptAvailableTranslationsUrl": "/transcript/available_translations", "transcriptLanguage": "en", "transcriptLanguages": {"en": "English", "de": "Deutsch", "zh": "普通话"}, "transcriptTranslationUrl": "/transcript/translation/__lang__", "ytApiUrl": "/base/fixtures/youtube_iframe_api.js", "ytImageUrl": "", "ytTestTimeout": "1500", "ytMetadataUrl": "www.googleapis.com/youtube/v3/videos/", "source": "", "html5_sources": ["http://youtu.be/3_yD_cEKoCk.mp4"], "poster": "/media/video-images/poster.png"}'
> >
<div class="focus_grabber first"></div> <div class="focus_grabber first"></div>
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
state.el.trigger('ready'); state.el.trigger('ready');
expect(Logger.log).toHaveBeenCalledWith('load_video', { expect(Logger.log).toHaveBeenCalledWith('load_video', {
id: 'id', id: 'id',
code: this.code code: this.code,
duration: this.duration
}); });
}); });
...@@ -33,7 +34,8 @@ ...@@ -33,7 +34,8 @@
expect(Logger.log).toHaveBeenCalledWith('play_video', { expect(Logger.log).toHaveBeenCalledWith('play_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeFalsy(); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeFalsy();
}); });
...@@ -49,7 +51,8 @@ ...@@ -49,7 +51,8 @@
expect(Logger.log).toHaveBeenCalledWith('pause_video', { expect(Logger.log).toHaveBeenCalledWith('pause_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy(); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy();
}); });
...@@ -61,7 +64,8 @@ ...@@ -61,7 +64,8 @@
code: this.code, code: this.code,
current_time: 10, current_time: 10,
old_speed: '1.0', old_speed: '1.0',
new_speed: '2.0' new_speed: '2.0',
duration: this.duration
}); });
}); });
...@@ -72,7 +76,8 @@ ...@@ -72,7 +76,8 @@
code: this.code, code: this.code,
old_time: 0, old_time: 0,
new_time: 1, new_time: 1,
type: 'any' type: 'any',
duration: this.duration
}); });
expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy(); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy();
}); });
...@@ -88,7 +93,8 @@ ...@@ -88,7 +93,8 @@
expect(Logger.log).toHaveBeenCalledWith('stop_video', { expect(Logger.log).toHaveBeenCalledWith('stop_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy(); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy();
...@@ -97,7 +103,8 @@ ...@@ -97,7 +103,8 @@
expect(Logger.log).toHaveBeenCalledWith('stop_video', { expect(Logger.log).toHaveBeenCalledWith('stop_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy(); expect(state.videoEventsPlugin.emitPlayVideoEvent).toBeTruthy();
}); });
...@@ -107,7 +114,8 @@ ...@@ -107,7 +114,8 @@
expect(Logger.log).toHaveBeenCalledWith('skip_video', { expect(Logger.log).toHaveBeenCalledWith('skip_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
}); });
...@@ -116,7 +124,8 @@ ...@@ -116,7 +124,8 @@
expect(Logger.log).toHaveBeenCalledWith('do_not_show_again_video', { expect(Logger.log).toHaveBeenCalledWith('do_not_show_again_video', {
id: 'id', id: 'id',
code: this.code, code: this.code,
currentTime: 10 currentTime: 10,
duration: this.duration
}); });
}); });
...@@ -124,7 +133,8 @@ ...@@ -124,7 +133,8 @@
state.el.trigger('language_menu:show'); state.el.trigger('language_menu:show');
expect(Logger.log).toHaveBeenCalledWith('edx.video.language_menu.shown', { expect(Logger.log).toHaveBeenCalledWith('edx.video.language_menu.shown', {
id: 'id', id: 'id',
code: this.code code: this.code,
duration: this.duration
}); });
}); });
...@@ -133,7 +143,8 @@ ...@@ -133,7 +143,8 @@
expect(Logger.log).toHaveBeenCalledWith('edx.video.language_menu.hidden', { expect(Logger.log).toHaveBeenCalledWith('edx.video.language_menu.hidden', {
id: 'id', id: 'id',
code: this.code, code: this.code,
language: 'en' language: 'en',
duration: this.duration
}); });
}); });
...@@ -142,7 +153,8 @@ ...@@ -142,7 +153,8 @@
expect(Logger.log).toHaveBeenCalledWith('show_transcript', { expect(Logger.log).toHaveBeenCalledWith('show_transcript', {
id: 'id', id: 'id',
code: this.code, code: this.code,
current_time: 10 current_time: 10,
duration: this.duration
}); });
}); });
...@@ -151,7 +163,8 @@ ...@@ -151,7 +163,8 @@
expect(Logger.log).toHaveBeenCalledWith('hide_transcript', { expect(Logger.log).toHaveBeenCalledWith('hide_transcript', {
id: 'id', id: 'id',
code: this.code, code: this.code,
current_time: 10 current_time: 10,
duration: this.duration
}); });
}); });
...@@ -160,7 +173,8 @@ ...@@ -160,7 +173,8 @@
expect(Logger.log).toHaveBeenCalledWith('edx.video.closed_captions.shown', { expect(Logger.log).toHaveBeenCalledWith('edx.video.closed_captions.shown', {
id: 'id', id: 'id',
code: this.code, code: this.code,
current_time: 10 current_time: 10,
duration: this.duration
}); });
}); });
...@@ -169,7 +183,8 @@ ...@@ -169,7 +183,8 @@
expect(Logger.log).toHaveBeenCalledWith('edx.video.closed_captions.hidden', { expect(Logger.log).toHaveBeenCalledWith('edx.video.closed_captions.hidden', {
id: 'id', id: 'id',
code: this.code, code: this.code,
current_time: 10 current_time: 10,
duration: this.duration
}); });
}); });
...@@ -208,6 +223,7 @@ ...@@ -208,6 +223,7 @@
describe('html5 encoding only', function() { describe('html5 encoding only', function() {
beforeEach(function(done) { beforeEach(function(done) {
this.code = 'html5'; this.code = 'html5';
this.duration = 111;
state = jasmine.initializePlayer('video_html5.html'); state = jasmine.initializePlayer('video_html5.html');
done(); done();
}); });
...@@ -217,6 +233,7 @@ ...@@ -217,6 +233,7 @@
describe('hls encoding', function() { describe('hls encoding', function() {
beforeEach(function(done) { beforeEach(function(done) {
this.code = 'hls'; this.code = 'hls';
this.duration = 111;
state = jasmine.initializeHLSPlayer(); state = jasmine.initializeHLSPlayer();
done(); done();
}); });
......
...@@ -1011,6 +1011,21 @@ function(VideoPlayer, HLS) { ...@@ -1011,6 +1011,21 @@ function(VideoPlayer, HLS) {
}); });
}); });
describe('Video duration', function() {
beforeEach(function() {
state = jasmine.initializePlayer();
spyOn(state.videoPlayer, 'duration').and.returnValue(61);
});
it('overrides the duration if not set', function(done) {
jasmine.waitUntil(function() {
return state.duration !== undefined;
}).then(function() {
expect(state.duration).toEqual(61);
}).always(done);
});
});
describe('Overlay Play Button', function() { describe('Overlay Play Button', function() {
var playButtonOverlaySelector = '.video-wrapper .btn-play.fa.fa-youtube-play.fa-2x'; var playButtonOverlaySelector = '.video-wrapper .btn-play.fa.fa-youtube-play.fa-2x';
beforeEach(function() { beforeEach(function() {
......
...@@ -569,6 +569,7 @@ function(VideoPlayer, i18n, moment, _) { ...@@ -569,6 +569,7 @@ function(VideoPlayer, i18n, moment, _) {
this.config.speed || this.config.generalSpeed this.config.speed || this.config.generalSpeed
); );
this.htmlPlayerLoaded = false; this.htmlPlayerLoaded = false;
this.duration = this.metadata.duration;
_setConfigurations(this); _setConfigurations(this);
......
...@@ -653,6 +653,9 @@ function(HTML5Video, HTML5HLSVideo, Resizer, HLS, _) { ...@@ -653,6 +653,9 @@ function(HTML5Video, HTML5HLSVideo, Resizer, HLS, _) {
var duration = this.videoPlayer.duration(), var duration = this.videoPlayer.duration(),
time = this.videoPlayer.figureOutStartingTime(duration); time = this.videoPlayer.figureOutStartingTime(duration);
// this.duration will be set initially only if duration is coming from edx-val
this.duration = this.duration || duration;
if (time > 0 && this.videoPlayer.goToStartTime) { if (time > 0 && this.videoPlayer.goToStartTime) {
this.videoPlayer.seekTo(time); this.videoPlayer.seekTo(time);
} }
......
...@@ -143,7 +143,8 @@ ...@@ -143,7 +143,8 @@
var logInfo = _.extend({ var logInfo = _.extend({
id: this.state.id, id: this.state.id,
// eslint-disable-next-line no-nested-ternary // eslint-disable-next-line no-nested-ternary
code: this.state.isYoutubeType() ? this.state.youtubeId() : this.state.canPlayHLS ? 'hls' : 'html5' code: this.state.isYoutubeType() ? this.state.youtubeId() : this.state.canPlayHLS ? 'hls' : 'html5',
duration: this.state.duration
}, data, this.options.data); }, data, this.options.data);
Logger.log(eventName, logInfo); Logger.log(eventName, logInfo);
} }
......
...@@ -211,6 +211,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, ...@@ -211,6 +211,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
download_video_link = None download_video_link = None
branding_info = None branding_info = None
youtube_streams = "" youtube_streams = ""
video_duration = None
# Determine if there is an alternative source for this video # Determine if there is an alternative source for this video
# based on user locale. This exists to support cases where # based on user locale. This exists to support cases where
...@@ -253,7 +254,11 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, ...@@ -253,7 +254,11 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
if val_video_urls["youtube"]: if val_video_urls["youtube"]:
youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) youtube_streams = "1.00:{}".format(val_video_urls["youtube"])
except edxval_api.ValInternalError: # get video duration
video_data = edxval_api.get_video_info(self.edx_video_id.strip())
video_duration = video_data.get('duration')
except (edxval_api.ValInternalError, edxval_api.ValVideoNotFoundError):
# VAL raises this exception if it can't find data for the edx video ID. This can happen if the # VAL raises this exception if it can't find data for the edx video ID. This can happen if the
# course data is ported to a machine that does not have the VAL data. So for now, pass on this # course data is ported to a machine that does not have the VAL data. So for now, pass on this
# exception and fallback to whatever we find in the VideoDescriptor. # exception and fallback to whatever we find in the VideoDescriptor.
...@@ -326,6 +331,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, ...@@ -326,6 +331,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
'sub': self.sub, 'sub': self.sub,
'sources': sources, 'sources': sources,
'poster': poster, 'poster': poster,
'duration': video_duration,
# This won't work when we move to data that # This won't work when we move to data that
# isn't on the filesystem # isn't on the filesystem
'captionDataDir': getattr(self, 'data_dir', None), 'captionDataDir': getattr(self, 'data_dir', None),
......
...@@ -69,6 +69,7 @@ class TestVideoYouTube(TestVideo): ...@@ -69,6 +69,7 @@ class TestVideoYouTube(TestVideo):
'streams': '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg', 'streams': '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg',
'sub': 'a_sub_file.srt.sjson', 'sub': 'a_sub_file.srt.sjson',
'sources': sources, 'sources': sources,
'duration': None,
'poster': None, 'poster': None,
'captionDataDir': None, 'captionDataDir': None,
'showCaptions': 'true', 'showCaptions': 'true',
...@@ -149,6 +150,7 @@ class TestVideoNonYouTube(TestVideo): ...@@ -149,6 +150,7 @@ class TestVideoNonYouTube(TestVideo):
'streams': '1.00:3_yD_cEKoCk', 'streams': '1.00:3_yD_cEKoCk',
'sub': 'a_sub_file.srt.sjson', 'sub': 'a_sub_file.srt.sjson',
'sources': sources, 'sources': sources,
'duration': None,
'poster': None, 'poster': None,
'captionDataDir': None, 'captionDataDir': None,
'showCaptions': 'true', 'showCaptions': 'true',
...@@ -206,6 +208,7 @@ class TestGetHtmlMethod(BaseTestXmodule): ...@@ -206,6 +208,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
'streams': '1.00:3_yD_cEKoCk', 'streams': '1.00:3_yD_cEKoCk',
'sub': 'a_sub_file.srt.sjson', 'sub': 'a_sub_file.srt.sjson',
'sources': '[]', 'sources': '[]',
'duration': 111.0,
'poster': None, 'poster': None,
'captionDataDir': None, 'captionDataDir': None,
'showCaptions': 'true', 'showCaptions': 'true',
...@@ -306,6 +309,7 @@ class TestGetHtmlMethod(BaseTestXmodule): ...@@ -306,6 +309,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
for data in cases: for data in cases:
metadata = self.default_metadata_dict metadata = self.default_metadata_dict
metadata['sources'] = sources metadata['sources'] = sources
metadata['duration'] = None
DATA = SOURCE_XML.format( DATA = SOURCE_XML.format(
download_track=data['download_track'], download_track=data['download_track'],
track=data['track'], track=data['track'],
...@@ -424,6 +428,7 @@ class TestGetHtmlMethod(BaseTestXmodule): ...@@ -424,6 +428,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
], ],
'poster': 'null', 'poster': 'null',
} }
initial_context['metadata']['duration'] = None
for data in cases: for data in cases:
DATA = SOURCE_XML.format( DATA = SOURCE_XML.format(
...@@ -674,7 +679,7 @@ class TestGetHtmlMethod(BaseTestXmodule): ...@@ -674,7 +679,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
result = create_video( result = create_video(
dict( dict(
client_video_id='A Client Video id', client_video_id='A Client Video id',
duration=111, duration=111.0,
edx_video_id=edx_video_id, edx_video_id=edx_video_id,
status='test', status='test',
encoded_videos=encoded_videos, encoded_videos=encoded_videos,
...@@ -835,6 +840,7 @@ class TestGetHtmlMethod(BaseTestXmodule): ...@@ -835,6 +840,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
], ],
'poster': 'null', 'poster': 'null',
} }
initial_context['metadata']['duration'] = None
for data in cases: for data in cases:
DATA = SOURCE_XML.format( DATA = SOURCE_XML.format(
...@@ -1542,7 +1548,7 @@ class VideoDescriptorTest(TestCase, VideoDescriptorTestBase): ...@@ -1542,7 +1548,7 @@ class VideoDescriptorTest(TestCase, VideoDescriptorTestBase):
create_video({ create_video({
'edx_video_id': self.descriptor.edx_video_id, 'edx_video_id': self.descriptor.edx_video_id,
'client_video_id': 'test_client_video_id', 'client_video_id': 'test_client_video_id',
'duration': 111, 'duration': 111.0,
'status': 'dummy', 'status': 'dummy',
'encoded_videos': [{ 'encoded_videos': [{
'profile': 'mobile', 'profile': 'mobile',
...@@ -1643,7 +1649,7 @@ class VideoDescriptorTest(TestCase, VideoDescriptorTestBase): ...@@ -1643,7 +1649,7 @@ class VideoDescriptorTest(TestCase, VideoDescriptorTestBase):
self.assertEqual(video.edx_video_id, 'test_edx_video_id') self.assertEqual(video.edx_video_id, 'test_edx_video_id')
video_data = get_video_info(video.edx_video_id) video_data = get_video_info(video.edx_video_id)
self.assertEqual(video_data['client_video_id'], 'test_client_video_id') self.assertEqual(video_data['client_video_id'], 'test_client_video_id')
self.assertEqual(video_data['duration'], 111) self.assertEqual(video_data['duration'], 111.0)
self.assertEqual(video_data['status'], 'imported') self.assertEqual(video_data['status'], 'imported')
self.assertEqual(video_data['courses'], [{id_generator.target_course_id: None}]) self.assertEqual(video_data['courses'], [{id_generator.target_course_id: None}])
self.assertEqual(video_data['encoded_videos'][0]['profile'], 'mobile') self.assertEqual(video_data['encoded_videos'][0]['profile'], 'mobile')
...@@ -1788,6 +1794,7 @@ class TestVideoWithBumper(TestVideo): ...@@ -1788,6 +1794,7 @@ class TestVideoWithBumper(TestVideo):
'sub': 'a_sub_file.srt.sjson', 'sub': 'a_sub_file.srt.sjson',
'sources': sources, 'sources': sources,
'poster': None, 'poster': None,
'duration': None,
'captionDataDir': None, 'captionDataDir': None,
'showCaptions': 'true', 'showCaptions': 'true',
'generalSpeed': 1.0, 'generalSpeed': 1.0,
......
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