无法动态更改Video.js中的标题“曲目”

时间:2013-08-07 21:24:45

标签: dynamic video.js captions

我正在编写一个基本的视频选框,其中一个关键要求是视频需要能够在保持播放器全屏的同时前进。

使用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&nbsp;Playing</h1><h2>" + videos[newIndex]["title"] + "</h2>";
                if (videos.length > 1) { navHtml += "<h1>Up&nbsp;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);

2 个答案:

答案 0 :(得分:6)

当前的VideoJS实现(4.4.2)在播放器本身的初始化时间加载各种文本轨道(字幕,标题,章节),因此它只能正确地抓取在<video之间定义的那些&GT;标签

编辑:我的意思是它在调用addTextTrack时加载它们,但播放器UI在初始化时间后永远不会更新,并且将始终显示初始化时间文本轨道。

一种可能的解决方法是,在刷新<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 />';