编辑为广告清晰度
我希望创建一个HTML5视频播放,以特定的定时提示点触发事件。例如,我希望在视频播放过程中每隔一秒触发一次事件,检查文本框的内容(即包含second2文本框;包含second2文本框)。 “棘手”部分是我需要它在所有主要平台/浏览器上工作,包括IPhones和IPads。
IPhones特别好像是一个问题,无论播放器,设置,黑客我尝试过 - 当视频开始播放时,浏览器转到后台,视频以全屏容器(Quicktime?)播放。当视频停止播放并且浏览器返回控制时,我看到cuepoint事件被触发,但如果视频播放期间文本框无法访问则没有用!
我对FlowPlayer非常熟悉,并且已经完成了大量工作,以确保它适用于大多数相关平台的播放;它的API的cuepoint功能似乎正是我们需要的但是它有一个特定的警告/限制:
请注意,提示点受HTML5视频API的设备限制。在不支持内联视频的设备上 因为他们将播放委托给系统组件(例如QuickTime 在iPhone上)在现实世界中,提示点的效果几乎没有 设置
有没有人在iPhone / iPad上使用Flowplayer cuepoints或替代技术?显然,如果我可以维护一个代码库,那么最好有多个特定于平台的版本。
答案 0 :(得分:1)
这是一个简单的视频元素控制器,它跟踪视频元素触发的timeupdate事件,以触发指定时间码的回调函数。
它允许您为同一时间码附加多个回调。
timeupdate事件在不同的设备上以不同的速率触发,因此有一个限制,即提示点只能附加在整数值,所以在5秒而不是5.5,你可以删除它但是然后存在风险不会触发提示点
/**
* Function which allows you to register cuepoints to trigger callbacks
* at specific timecodes
* @param {HTMLElement} video_el The video element you want to track
*/
var VideoController = function(video_el){
/**
* The video element this controller is for
* @type {HTMLElement}
*/
this.element = video_el; //
/**
* Object containing all the cuepoints
* @type {Object}
*/
this.cuepoints = {};
/**
* The last processed_timecode so we dont fire events more than once
* @type {Number}
*/
this.processed_timecode = undefined;
/**
* Allows you to trigger a callback at a specific timecode
* @param {Number} timecode The timecode you want to trigger your callback
* @param {Function} callback Your callback function
*/
this.addCuepoint = function(timecode, callback){
//
timecode = Math.floor(timecode);
//
if(this.cuepoints[timecode] === undefined){
this.cuepoints[timecode] = [];
}
this.cuepoints[timecode].push(callback);
return this;
}
/**
* Internal method to track the videos current timecode and to trigger
* the cuepoints when neccesary
* @param {[type]} e A timeupdate event from the video
*/
this.timeupdate = function(e){
var timecode = Math.floor(e.target.currentTime);
// check to see if there is a callback registered for this timecode
if(this.cuepoints.hasOwnProperty(timecode) && this.cuepoints[timecode] !== undefined && this.processed_timecode !== timecode){
//if there is it loops through the array of callbacks and triggers them
for(var i = 0,l=this.cuepoints[timecode].length;i<l;i++){
this.cuepoints[timecode][i]();
}
}
//updates the processed_timecode so we do not fire these callbacks again
this.processed_timecode = timecode;
}.bind(this);
// add addEventListener to the video element to track the video timecode
this.element.addEventListener('timeupdate', this.timeupdate);
return this;
}
var video = document.getElementById('myVideoElement');
var video_controller = new VideoController(video);
video_controller.addCuepoint(2,function(){
console.log('do something at 2 seconds');
});
video_controller.addCuepoint(2,function(){
console.log('do something else at 2 seconds');
});
答案 1 :(得分:1)
我已经调整@Irfan上面的答案来使用requestAnimationFrame而不是依赖于timeupdate事件。 这将允许在半秒等时更精细地触发事件,只需根据需要调整.tofixed(1)。 这对于iPhone网络视频限制不太有帮助,但对于其他用例,它应该对需要精确触发或基于视频时间的事件的其他人有所帮助。
// Request Animation Frame Shim
// Source: https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var VideoController = function(video_el){
this.element = video_el;
this.cuepoints = {};
this.processed_timecode = undefined;
var self = this;
this.addCuepoint = function(timecode, callback){
var timecode = timecode.toFixed(1);
if(this.cuepoints[timecode] === undefined){
this.cuepoints[timecode] = [];
}
this.cuepoints[timecode].push(callback);
return this;
}
this.rafUpdate = function(timestamp){
var timecode = video_el.currentTime.toFixed(1);
if(!video_el.duration){
requestAnimFrame(self.rafUpdate);
}else if( timecode < video_el.duration ){
requestAnimFrame(self.rafUpdate);
}
if( self.cuepoints.hasOwnProperty(timecode) && self.cuepoints[timecode] !== undefined && self.processed_timecode !== timecode ){
for(var i = 0,l=self.cuepoints[timecode].length;i<l;i++){
self.cuepoints[timecode][i]();
}
}
self.processed_timecode = timecode;
}
requestAnimFrame( this.rafUpdate ); // keeps better time than video.timeupdate
return this;
}
var video = document.getElementById('myvideo');
globalVars['video'] = video;
var video_controller = new VideoController(globalVars['video']);
video_controller.addCuepoint(10.2,function(){
endframe.play();
});