我正在编写一个基本的视频选框,其中一个关键要求是视频需要能够在保持播放器全屏的同时前进。
使用Video.js(4.1.0)我已经能够正常工作,只是在切换到另一个视频时我无法更改字幕。
首次创建播放器HTML时插入“track”标签,或者在播放器初始化时向“options”对象添加曲目是我可以让播放器显示“CC”按钮并显示的唯一方法字幕。但是,我无法在全屏时重新初始化播放器,因此以这种方式更改曲目将无效。
我尝试过addTextTrack和addTextTracks,并且都显示已经添加了轨道 - 使用类似console.log(videoObject.textTracks())的东西 - 但是播放器从不显示它们或“CC”按钮。
这是我的代码,非常感谢任何帮助:
;(function(window,undefined) {
// VIDEOS OBJECT
var videos = [
{"volume":"70","title":"TEST 1","url":"test1.mp4","type":"mp4"},
{"volume":"80","title":"TEST 2","url":"test2.mp4","type":"mp4"},
{"volume":"90","title":"TEST 3","url":"test3.mp4","type":"mp4"}
];
// CONSTANTS
var VIDEO_BOX_ID = "jbunow_marquee_video_box", NAV_TEXT_ID = "jbunow_marquee_nav_text", NAV_ARROWS_ID = "jbunow_marquee_nav_arrows", VIDEO_OBJ_ID = "jbunow_marquee_video", NAV_PREV_ID = "jbunow_nav_prev", NAV_NEXT_ID = "jbunow_nav_next";
// GLOBAL VARIABLS
var videoObject;
var currentTrack = 0;
var videoObjectCreated = false;
var controlBarHideTimeout;
jQuery(document).ready(function(){
// CREATE NAV ARROWS AND LISTENERS, THEN START MARQUEE
var navArrowsHtml = "<div id='" + NAV_PREV_ID + "' title='Play Previous Video'></div>";
navArrowsHtml += "<div id='" + NAV_NEXT_ID + "' title='Play Next Video'></div>";
jQuery('#' + NAV_ARROWS_ID).html(navArrowsHtml);
jQuery('#' + NAV_PREV_ID).on('click',function() { ChangeVideo(GetPrevVideo()); });
jQuery('#' + NAV_NEXT_ID).on('click',function() { ChangeVideo(GetNextVideo()); });
ChangeVideo(currentTrack);
});
var ChangeVideo = function(newIndex) {
var videoBox = jQuery('#' + VIDEO_BOX_ID);
if (!videoObjectCreated) {
// LOAD PLAYER HTML
videoBox.html(GetPlayerHtml());
// INITIALIZE VIDEO-JS
videojs(VIDEO_OBJ_ID, {}, function(){
videoObject = this;
// LISTENERS
videoObject.on("ended", function() { ChangeVideo(GetNextVideo()); });
videoObject.on("loadeddata", function () { videoObject.play(); });
videoObjectCreated = true;
PlayVideo(newIndex);
});
} else { PlayVideo(newIndex); }
}
var PlayVideo = function(newIndex) {
// TRY ADDING MULTIPLE TRACKS
videoObject.addTextTracks([{ kind: 'captions', label: 'English2', language: 'en', srclang: 'en', src: 'track2.vtt' }]);
// TRY ADDING HTML
//jQuery('#' + VIDEO_OBJ_ID + ' video').eq(0).append("<track kind='captions' src='track2.vtt' srclang='en' label='English' default />");
// TRY ADDING SINGLE TRACK THEN SHOWING USING RETURNED ID
//var newTrack = videoObject.addTextTrack('captions', 'English2', 'en', { kind: 'captions', label: 'English2', language: 'en', srclang: 'en', src: 'track2.vtt' });
//videoObject.showTextTrack(newTrack.id_, newTrack.kind_);
videoObject.volume(parseFloat(videos[newIndex]["volume"]) / 100); // SET START VOLUME
videoObject.src({ type: "video/" + videos[newIndex]["type"], src: videos[newIndex]["url"] }); // SET NEW SRC
videoObject.load();
videoObject.ready(function () {
videoObject.play();
clearTimeout(controlBarHideTimeout);
controlBarHideTimeout = setTimeout(function() { videoObject.controlBar.fadeOut(); }, 2000);
jQuery('#' + NAV_TEXT_ID).fadeOut(150, function() {
currentTrack = newIndex;
var navHtml = "";
navHtml += "<h1>Now Playing</h1><h2>" + videos[newIndex]["title"] + "</h2>";
if (videos.length > 1) { navHtml += "<h1>Up Next</h1><h2>" + videos[GetNextVideo()]["title"] + "</h2>"; }
jQuery('#' + NAV_TEXT_ID).html(navHtml).fadeIn(250);
});
});
}
var GetPlayerHtml = function() {
var playerHtml = "";
playerHtml += "<video id='" + VIDEO_OBJ_ID + "' class='video-js vjs-default-skin' controls='controls' preload='auto' width='560' height='315'>";
playerHtml += "<source src='' type='video/mp4' />";
//playerHtml += "<track kind='captions' src='track.vtt' srclang='en' label='English' default='default' />";
playerHtml += "</video>";
return playerHtml;
}
var GetNextVideo = function() {
if (currentTrack >= videos.length - 1) { return 0; }
else { return (currentTrack + 1); }
}
var GetPrevVideo = function() {
if (currentTrack <= 0) { return videos.length - 1; }
else { return (currentTrack - 1); }
}
})(window);
答案 0 :(得分:6)
当前的VideoJS实现(4.4.2)在播放器本身的初始化时间加载各种文本轨道(字幕,标题,章节),因此它只能正确地抓取在<video
之间定义的那些&GT;标签
一种可能的解决方法是,在刷新<video>
标记之间的内容后,销毁完整的videojs播放器并在视频源更改时重新创建它。因此,您不会通过videojs播放器更新源,而是通过动态添加所需的DOM元素并在其上初始化新播放器。可能这个解决方案会导致一些UI闪烁,并且对于这个问题来说非常不理想。 Here is a link about destroying the videojs player
第二个选项是将动态文本轨道处理添加到现有代码中,如果有人知道在哪里查找,它就不像听起来那么难(我只为章节做过,但对于其他文本轨道也是如此)。下面的代码适用于最新的官方版本4.4.2。请注意,我使用jQuery删除文本轨道元素,因此如果有人按原样应用这些更改,则需要在videojs之前加载jQuery。
编辑video.dev.js文件,如下所示:
1:向播放器添加clearTextTracks功能
vjs.Player.prototype.clearTextTracks = function() {
var tracks = this.textTracks_ = this.textTracks_ || [];
for (var i = 0; i != tracks.length; ++i)
$(tracks[i].el()).remove();
tracks.splice(0, tracks.length);
this.trigger("textTracksChanged");
};
2:将新的'textTracksChanged'事件触发器添加到现有addTextTrack方法的末尾
vjs.Player.prototype.addTextTrack = function(kind, label, language, options) {
...
this.trigger("textTracksChanged");
}
3:在TextTrackButton构造函数
中处理新事件vjs.TextTrackButton = vjs.MenuButton.extend({
/** @constructor */
init: function(player, options) {
vjs.MenuButton.call(this, player, options);
if (this.items.length <= 1) {
this.hide();
}
player.on('textTracksChanged', vjs.bind(this, this.refresh));
}
});
4:在TextTrackButton
上实现refresh方法// removes and recreates the texttrack menu
vjs.TextTrackButton.prototype.refresh = function () {
this.removeChild(this.menu);
this.menu = this.createMenu();
this.addChild(this.menu);
if (this.items && this.items.length <= this.kind_ == "chapters" ? 0 : 1) {
this.hide();
} else
this.show();
};
很抱歉,但是现在我无法链接到一个真实的工作示例,我希望上面的代码段足以作为任何对此感兴趣的人的起点。
将源更新为新视频时,可以使用此代码。只需调用clearTextTracks方法,并使用addTextTrack方法添加新文本轨道,现在菜单应自行更新。
答案 1 :(得分:1)
做同样的事情(或者说不做同样的事情)......真的需要弄清楚如何动态更改/添加字幕轨道。
这可以通过基础HTML5播放它,但它不会显示videojs CC按钮:
document.getElementById("HtmlFiveMediaPlayer_html5_api").innerHTML = '<track label="English Captions" srclang="en" kind="captions" src="http://localhost/media/captiontest/demo_Brian/demo_h264_1.vtt" type="text/vtt" default />';