2013-08-07 18 views
6

Kodowanie podstawowego namiotu wideo i jednym z kluczowych wymagań jest to, że filmy wideo muszą być w stanie przejść do przodu, zachowując odtwarzacz na pełnym ekranie.Nie można dynamicznie zmieniać ścieżki nagłówka w Video.js

Korzystanie z Video.js (4.1.0) Udało mi się przekonać, że wszystko działa poprawnie, z tym wyjątkiem, że nie mogę zmienić napisów po przejściu na inny film.

Dodanie znacznika "śladu" po pierwszym utworzeniu odtwarzacza HTML lub dodaniu ścieżki do obiektu "opcji" podczas inicjowania odtwarzacza to jedyne sposoby, dzięki którym odtwarzacz może wyświetlić przycisk "DW" i Pokaż nagłówki. Nie mogę jednak ponownie zainicjować odtwarzacza na pełnym ekranie, więc zmiana ścieżki w ten sposób nie będzie działać.

Próbowałem addTextTrack i addTextTracks i oba pokazują, że utwory zostały dodane - używając czegoś takiego jak console.log (videoObject.textTracks()) - ale odtwarzacz nigdy ich nie pokazuje lub przycisk "CC".

Oto mój kod, każda pomoc jest mile widziana:

;(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); 
+0

Witam - czy nigdzie z tym nie skorzystałeś? Mam podobny problem. Chcę go podać jako adres URL VTT, gdy programowo zmieniam film src. – Phil

+0

Nie, po prostu opublikowałem to wczoraj i mam nadzieję, że ktoś znający się na wiadomości zadzwoni. Na różnych forach jest kilka podobnych pytań dotyczących starszych wersji Video.js, ale jak dotąd nie znalazłem żadnych odpowiedzi, które działają. – fodder

Odpowiedz

1

Robi dokładnie to samo (lub raczej nie robi dokładnie to samo) ... naprawdę trzeba dowiedzieć się, jak dynamicznie zmieniać/dodaj ścieżkę napisów.

Działa to dostać to gra przez leżącej HTML5, ale nie pokazuje przycisk 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 />'; 
6

Realizacja VideoJS prądu (4.4.2) ładuje każdy rodzaj ścieżek tekstowych (napisów, podpisy, rozdziały) o czasie inicjalizacji samego odtwarzacza, więc pobiera poprawnie tylko te, które są zdefiniowane między znacznikami><video.

EDYCJA: Chciałem załadować je podczas wywoływania funkcji addTextTrack, ale interfejs użytkownika odtwarzacza nigdy się nie zaktualizuje po czasie inicjalizacji i zawsze będzie wyświetlał ścieżki tekstu czasu inicjalizacji.

Jednym z możliwych sposobów obejścia tego problemu jest zniszczenie całego odtwarzacza odtwarzaczy wideo i odtworzenie go po zmianie źródła wideo po odświeżeniu zawartości między znacznikami <video>. W ten sposób nie aktualizujesz źródła za pomocą odtwarzacza videojs, ale dynamicznie dodajesz wymagane elementy DOM i inicjujesz na nich nowego gracza. Prawdopodobnie to rozwiązanie spowoduje błysk niektórych interfejsów i jest dość nieoptymalne dla problemu. Here is a link about destroying the videojs player

Druga opcja to dodanie obsługi dynamicznego tekstu do istniejącego kodu, co nie jest tak trudne, jak się wydaje, jeśli wiadomo, gdzie szukać (zrobiłem to tylko dla rozdziałów, ale mogłoby być podobne dla innych ścieżek tekstowych także). Poniższy kod działa z najnowszą oficjalną wersją 4.4.2. Zauważ, że używam jQuery do usuwania elementów tekstowych, więc jeśli ktokolwiek zastosuje te zmiany w obecnej postaci, jQuery musi zostać załadowany przed wideojakami.

Edytuj wideo.dev.plik js następująco:

1: Dodawanie funkcji clearTextTracks do odtwarzacza

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: Dodaj nowe zdarzenie wyzwalające 'textTracksChanged' na końcu istniejącego sposobu addTextTrack

vjs.Player.prototype.addTextTrack = function(kind, label, language, options) { 
    ... 
    this.trigger("textTracksChanged"); 
} 

3: Obsługa nowego zdarzenia w funkcji konstruktora 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: Wdrożenie metody odświeżania na TextTrackButton

// 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(); 
}; 

przykro, ale na razie nie mogę połączyć się prawdziwy przykład pracy, mam nadzieję, że fragmenty powyżej wystarczą jako punkt wyjścia dla każdego, kto zainteresowany w tym.

Możesz użyć tego kodu, gdy zaktualizujesz źródło do nowego filmu. Wystarczy wywołać metodę clearTextTracks i dodać nowe ścieżki tekstowe za pomocą metody addTextTrack, a menu powinno się teraz zaktualizować.

+0

Przepraszam, Zoltán, właśnie widziałem tę odpowiedź (z jakiegoś powodu nie otrzymałem e-maila). Zdecydowanie spróbuję tego, żeby sprawdzić, czy to działa. Ponieważ nie otrzymałem żadnych odpowiedzi w zeszłym roku, musiałem pójść trasa kompletnego unieszkodliwiania obiektu wideojs, który, jak powiedziałeś, z pewnością nie jest optymalny, ale przynajmniej działa. – fodder

+0

Dzięki za to. Jedna zmiana dla tych, którzy nie chcą używać jQuery, zmień to: $ (tracks [i] .el()). Remove(); W tym celu: ścieżki [i] .disable(); –

+0

Zauważyłem też, że to nie działa poprawnie dla mnie: if (this.items && this.items.length <= this.kind_ == "rozdziały"? 0: 1), więc po prostu zmieniłem go na if (this.items && this.items.length <= 1) –