mirror of
https://github.com/videojs/video.js.git
synced 2025-01-06 06:50:51 +02:00
229 lines
7.9 KiB
JavaScript
229 lines
7.9 KiB
JavaScript
/* HTML5 Playback Technology - Wrapper for HTML5 Media API
|
|
================================================================================ */
|
|
_V_.html5 = _V_.PlaybackTech.extend({
|
|
|
|
init: function(player, options, ready){
|
|
this.player = player;
|
|
this.el = this.createElement();
|
|
this.ready(ready);
|
|
|
|
this.addEvent("click", this.proxy(this.onClick));
|
|
|
|
var source = options.source;
|
|
|
|
// If the element source is already set, we may have missed the loadstart event, and want to trigger it.
|
|
// We don't want to set the source again and interrupt playback.
|
|
if (source && this.el.currentSrc == source.src) {
|
|
player.triggerEvent("loadstart");
|
|
|
|
// Otherwise set the source if one was provided.
|
|
} else if (source) {
|
|
this.el.src = source.src;
|
|
}
|
|
|
|
// Chrome and Safari both have issues with autoplay.
|
|
// In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
|
|
// In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
|
|
// This fixes both issues. Need to wait for API, so it updates displays correctly
|
|
player.ready(function(){
|
|
if (this.options.autoplay && this.paused()) {
|
|
this.tag.poster = null; // Chrome Fix. Fixed in Chrome v16.
|
|
this.play();
|
|
}
|
|
});
|
|
|
|
this.setupTriggers();
|
|
|
|
this.triggerReady();
|
|
},
|
|
|
|
destroy: function(){
|
|
this.player.tag = false;
|
|
this.removeTriggers();
|
|
this.el.parentNode.removeChild(this.el);
|
|
},
|
|
|
|
createElement: function(){
|
|
var html5 = _V_.html5,
|
|
player = this.player,
|
|
|
|
// If possible, reuse original tag for HTML5 playback technology element
|
|
el = player.tag,
|
|
newEl;
|
|
|
|
// Check if this browser supports moving the element into the box.
|
|
// On the iPhone video will break if you move the element,
|
|
// So we have to create a brand new element.
|
|
if (!el || this.support.movingElementInDOM === false) {
|
|
|
|
// If the original tag is still there, remove it.
|
|
if (el) {
|
|
player.el.removeChild(el);
|
|
}
|
|
|
|
newEl = _V_.createElement("video", {
|
|
id: el.id || player.el.id + "_html5_api",
|
|
className: el.className || "vjs-tech"
|
|
});
|
|
|
|
el = newEl;
|
|
_V_.insertFirst(el, player.el);
|
|
}
|
|
|
|
// Update tag settings, in case they were overridden
|
|
_V_.each(["autoplay","preload","loop","muted"], function(attr){ // ,"poster"
|
|
if (player.options[attr] !== null) {
|
|
el[attr] = player.options[attr];
|
|
}
|
|
}, this);
|
|
|
|
return el;
|
|
},
|
|
|
|
// Make video events trigger player events
|
|
// May seem verbose here, but makes other APIs possible.
|
|
setupTriggers: function(){
|
|
_V_.each.call(this, _V_.html5.events, function(type){
|
|
_V_.addEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
|
|
});
|
|
},
|
|
removeTriggers: function(){
|
|
_V_.each.call(this, _V_.html5.events, function(type){
|
|
_V_.removeEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
|
|
});
|
|
},
|
|
eventHandler: function(e){
|
|
e.stopPropagation();
|
|
this.triggerEvent(e);
|
|
},
|
|
|
|
play: function(){ this.el.play(); },
|
|
pause: function(){ this.el.pause(); },
|
|
paused: function(){ return this.el.paused; },
|
|
|
|
currentTime: function(){ return this.el.currentTime; },
|
|
setCurrentTime: function(seconds){
|
|
try {
|
|
this.el.currentTime = seconds;
|
|
} catch(e) {
|
|
_V_.log(e, "Video isn't ready. (VideoJS)");
|
|
// this.warning(VideoJS.warnings.videoNotReady);
|
|
}
|
|
},
|
|
|
|
duration: function(){ return this.el.duration || 0; },
|
|
buffered: function(){ return this.el.buffered; },
|
|
|
|
volume: function(){ return this.el.volume; },
|
|
setVolume: function(percentAsDecimal){ this.el.volume = percentAsDecimal; },
|
|
muted: function(){ return this.el.muted; },
|
|
setMuted: function(muted){ this.el.muted = muted; },
|
|
|
|
width: function(){ return this.el.offsetWidth; },
|
|
height: function(){ return this.el.offsetHeight; },
|
|
|
|
supportsFullScreen: function(){
|
|
if (typeof this.el.webkitEnterFullScreen == 'function') {
|
|
|
|
// Seems to be broken in Chromium/Chrome && Safari in Leopard
|
|
if (!navigator.userAgent.match("Chrome") && !navigator.userAgent.match("Mac OS X 10.5")) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
enterFullScreen: function(){
|
|
try {
|
|
this.el.webkitEnterFullScreen();
|
|
} catch (e) {
|
|
if (e.code == 11) {
|
|
// this.warning(VideoJS.warnings.videoNotReady);
|
|
_V_.log("VideoJS: Video not ready.");
|
|
}
|
|
}
|
|
},
|
|
exitFullScreen: function(){
|
|
try {
|
|
this.el.webkitExitFullScreen();
|
|
} catch (e) {
|
|
if (e.code == 11) {
|
|
// this.warning(VideoJS.warnings.videoNotReady);
|
|
_V_.log("VideoJS: Video not ready.");
|
|
}
|
|
}
|
|
},
|
|
src: function(src){ this.el.src = src; },
|
|
load: function(){ this.el.load(); },
|
|
currentSrc: function(){ return this.el.currentSrc; },
|
|
|
|
preload: function(){ return this.el.preload; },
|
|
setPreload: function(val){ this.el.preload = val; },
|
|
autoplay: function(){ return this.el.autoplay; },
|
|
setAutoplay: function(val){ this.el.autoplay = val; },
|
|
loop: function(){ return this.el.loop; },
|
|
setLoop: function(val){ this.el.loop = val; },
|
|
|
|
error: function(){ return this.el.error; },
|
|
// networkState: function(){ return this.el.networkState; },
|
|
// readyState: function(){ return this.el.readyState; },
|
|
seeking: function(){ return this.el.seeking; },
|
|
// initialTime: function(){ return this.el.initialTime; },
|
|
// startOffsetTime: function(){ return this.el.startOffsetTime; },
|
|
// played: function(){ return this.el.played; },
|
|
// seekable: function(){ return this.el.seekable; },
|
|
ended: function(){ return this.el.ended; },
|
|
// videoTracks: function(){ return this.el.videoTracks; },
|
|
// audioTracks: function(){ return this.el.audioTracks; },
|
|
// videoWidth: function(){ return this.el.videoWidth; },
|
|
// videoHeight: function(){ return this.el.videoHeight; },
|
|
// textTracks: function(){ return this.el.textTracks; },
|
|
// defaultPlaybackRate: function(){ return this.el.defaultPlaybackRate; },
|
|
// playbackRate: function(){ return this.el.playbackRate; },
|
|
// mediaGroup: function(){ return this.el.mediaGroup; },
|
|
// controller: function(){ return this.el.controller; },
|
|
controls: function(){ return this.player.options.controls; },
|
|
defaultMuted: function(){ return this.el.defaultMuted; }
|
|
});
|
|
|
|
/* HTML5 Support Testing -------------------------------------------------------- */
|
|
|
|
_V_.html5.isSupported = function(){
|
|
return !!document.createElement("video").canPlayType;
|
|
};
|
|
|
|
_V_.html5.canPlaySource = function(srcObj){
|
|
return !!document.createElement("video").canPlayType(srcObj.type);
|
|
// TODO: Check Type
|
|
// If no Type, check ext
|
|
// Check Media Type
|
|
};
|
|
|
|
// List of all HTML5 events (various uses).
|
|
_V_.html5.events = "loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");
|
|
|
|
/* HTML5 Device Fixes ---------------------------------------------------------- */
|
|
|
|
_V_.html5.prototype.support = {
|
|
|
|
// Support for tech specific full screen. (webkitEnterFullScreen, not requestFullscreen)
|
|
// http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html
|
|
// Seems to be broken in Chromium/Chrome && Safari in Leopard
|
|
fullscreen: (typeof _V_.testVid.webkitEnterFullScreen !== undefined) ? (!_V_.ua.match("Chrome") && !_V_.ua.match("Mac OS X 10.5") ? true : false) : false,
|
|
|
|
// In iOS, if you move a video element in the DOM, it breaks video playback.
|
|
movingElementInDOM: !_V_.isIOS()
|
|
|
|
};
|
|
|
|
// Android
|
|
if (_V_.isAndroid()) {
|
|
|
|
// Override Android 2.2 and less canPlayType method which is broken
|
|
if (_V_.androidVersion() < 3) {
|
|
document.createElement("video").constructor.prototype.canPlayType = function(type){
|
|
return (type && type.toLowerCase().indexOf("video/mp4") != -1) ? "maybe" : "";
|
|
};
|
|
}
|
|
}
|