Commit 626f2896 by muhammad-ammar Committed by Mushtaq Ali

add video poster support

EDUCATOR-44
parent 763f0051
...@@ -13,7 +13,7 @@ import ddt ...@@ -13,7 +13,7 @@ import ddt
import pytz import pytz
from django.conf import settings from django.conf import settings
from django.test.utils import override_settings from django.test.utils import override_settings
from edxval.api import create_profile, create_video, get_video_info from edxval.api import create_profile, create_video, get_video_info, get_course_video_image_url
from mock import Mock, patch from mock import Mock, patch
from contentstore.models import VideoUploadConfig from contentstore.models import VideoUploadConfig
......
...@@ -28,7 +28,7 @@ define( ...@@ -28,7 +28,7 @@ define(
icon: '', icon: '',
text: HtmlUtils.interpolateHtml( text: HtmlUtils.interpolateHtml(
// Translators: This is a 3 part text which tells the image requirements. // Translators: This is a 3 part text which tells the image requirements.
gettext('Image requirements {lineBreak} 1280px by 720px {lineBreak} .jpg | .png | .gif'), gettext('Image requirements: {lineBreak} 1280px by 720px {lineBreak} .jpg, .png, or .gif'),
{ {
lineBreak: HtmlUtils.HTML('<br>') lineBreak: HtmlUtils.HTML('<br>')
} }
...@@ -208,7 +208,10 @@ define( ...@@ -208,7 +208,10 @@ define(
this.$('.thumbnail-action .action-icon'), this.$('.thumbnail-action .action-icon'),
HtmlUtils.HTML(this.actionsInfo[action].icon) HtmlUtils.HTML(this.actionsInfo[action].icon)
); );
this.$('.thumbnail-action .action-text').html(this.actionsInfo[action].text); HtmlUtils.setHtml(
this.$('.thumbnail-action .action-text'),
HtmlUtils.HTML(this.actionsInfo[action].text)
);
this.$('.thumbnail-action .action-text-sr').text(additionalSRText || ''); this.$('.thumbnail-action .action-text-sr').text(additionalSRText || '');
this.$('.thumbnail-wrapper').attr('class', 'thumbnail-wrapper {action}'.replace('{action}', action)); this.$('.thumbnail-wrapper').attr('class', 'thumbnail-wrapper {action}'.replace('{action}', action));
}, },
......
...@@ -147,6 +147,11 @@ ...@@ -147,6 +147,11 @@
} }
.assets-library { .assets-library {
.js-table-body .video-id-col {
word-break: break-all;
}
.assets-title { .assets-title {
display: inline-block; display: inline-block;
width: flex-grid(5, 9); width: flex-grid(5, 9);
......
...@@ -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": ""}' 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"}'
> >
<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"]}' 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"}'
> >
<div class="focus_grabber first"></div> <div class="focus_grabber first"></div>
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
var state, var state,
oldOTBD, oldOTBD,
playbackRates = [0.75, 1.0, 1.25, 1.5], playbackRates = [0.75, 1.0, 1.25, 1.5],
describeInfo; describeInfo,
POSTER_URL = '/media/video-images/poster.png';
beforeEach(function() { beforeEach(function() {
oldOTBD = window.onTouchBasedDevice; oldOTBD = window.onTouchBasedDevice;
...@@ -320,6 +321,15 @@ ...@@ -320,6 +321,15 @@
}).done(done); }).done(done);
}); });
}); });
describe('poster', function() {
it('has url in player config', function() {
expect(state.videoPlayer.player.config.poster).toEqual(POSTER_URL);
expect(state.videoPlayer.player.videoEl).toHaveAttrs({
poster: POSTER_URL
});
});
});
}); });
describe('non-hls encoding', function() { describe('non-hls encoding', function() {
...@@ -338,6 +348,28 @@ ...@@ -338,6 +348,28 @@
jasmine.getEnv().describe(describeInfo.description, describeInfo.specDefinitions); jasmine.getEnv().describe(describeInfo.description, describeInfo.specDefinitions);
}); });
it('does not show poster for html5 video if url is not present', function() {
state = jasmine.initializePlayer(
'video_html5.html',
{
poster: null
}
);
expect(state.videoPlayer.player.config.poster).toEqual(null);
expect(state.videoPlayer.player.videoEl).not.toHaveAttr('poster');
});
it('does not show poster for hls video if url is not present', function() {
state = jasmine.initializePlayer(
'video_hls.html',
{
poster: null
}
);
expect(state.videoPlayer.player.config.poster).toEqual(null);
expect(state.videoPlayer.player.videoEl).not.toHaveAttr('poster');
});
it('native controls are used on iPhone', function() { it('native controls are used on iPhone', function() {
window.onTouchBasedDevice.and.returnValue(['iPhone']); window.onTouchBasedDevice.and.returnValue(['iPhone']);
......
...@@ -44,8 +44,11 @@ function(_) { ...@@ -44,8 +44,11 @@ function(_) {
* // video format of the source. Supported * // video format of the source. Supported
* // video formats are: 'mp4', 'webm', and * // video formats are: 'mp4', 'webm', and
* // 'ogg'. * // 'ogg'.
* poster: Video poster URL
* *
* events: { // Object's properties identify the * browserIsSafari: Flag to tell if current browser is Safari
*
* events: { // Object's properties identify the
* // events that the API fires, and the * // events that the API fires, and the
* // functions (event listeners) that the * // functions (event listeners) that the
* // API will call when those events occur. * // API will call when those events occur.
...@@ -320,6 +323,11 @@ function(_) { ...@@ -320,6 +323,11 @@ function(_) {
this.videoEl.prop('controls', true); this.videoEl.prop('controls', true);
} }
// Set video poster
if (this.config.poster) {
this.videoEl.prop('poster', this.config.poster);
}
// Place the <video> element on the page. // Place the <video> element on the page.
this.videoEl.appendTo(el.find('.video-player > div:first-child')); this.videoEl.appendTo(el.find('.video-player > div:first-child'));
}; };
......
...@@ -162,6 +162,7 @@ function(HTML5Video, HTML5HLSVideo, Resizer, HLS, _) { ...@@ -162,6 +162,7 @@ function(HTML5Video, HTML5HLSVideo, Resizer, HLS, _) {
commonPlayerConfig = { commonPlayerConfig = {
playerVars: state.videoPlayer.playerVars, playerVars: state.videoPlayer.playerVars,
videoSources: state.config.sources, videoSources: state.config.sources,
poster: state.config.poster,
browserIsSafari: state.browserIsSafari, browserIsSafari: state.browserIsSafari,
events: { events: {
onReady: state.videoPlayer.onReady, onReady: state.videoPlayer.onReady,
......
...@@ -310,7 +310,10 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers, ...@@ -310,7 +310,10 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
'streams': self.youtube_streams, 'streams': self.youtube_streams,
'sub': self.sub, 'sub': self.sub,
'sources': sources, 'sources': sources,
'poster': edxval_api and edxval_api.get_course_video_image_url(
course_id=self.runtime.course_id.for_branch(None),
edx_video_id=self.edx_video_id.strip()
),
# 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),
......
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