mirror of
https://github.com/videojs/video.js.git
synced 2024-11-24 08:42:25 +02:00
feat: allow displaying of multiple text tracks at once (#5817)
This allows the user to display multiple tracks when `allowMultipleShowingTracks` is passed to the `TextTrackDisplay`. Currently, multiple tracks must be shown programmatically and cannot be done via the subtitles menus. In addition, this adds two new classes to cue elements: `vjs-text-track-cue` and `vjs-text-track-cue-${track.language}`. This allows easier targetting with CSS. Example usage: ```js var player = videojs('example-video', { textTrackDisplay: { allowMultipleShowingTracks: true } }); ``` Fixes #5798.
This commit is contained in:
parent
2c7644f91e
commit
c61f3d3e49
60
sandbox/double-sub-video.html.example
Normal file
60
sandbox/double-sub-video.html.example
Normal file
@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Video.js Text Descriptions, Chapters & Captions Example</title>
|
||||
|
||||
<!-- Load the source files -->
|
||||
<link href="../dist/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../dist/video.js"></script>
|
||||
|
||||
<!-- Set the location of the flash SWF -->
|
||||
<script>
|
||||
videojs.options.flash.swf = '../node_modules/videojs-flash/node_modules/videojs-swf/dist/video-js.swf';
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- NOTE: we have to disable native Text Track support for the HTML5 tech,
|
||||
since even HTML5 video players with native Text Track support
|
||||
don't currently support 'description' text tracks in any
|
||||
useful way! Currently this means that iOS will not display
|
||||
ANY text tracks -->
|
||||
<video id="example_video_1" class="video-js" controls preload="none" width="640" height="360"
|
||||
poster="//d2zihajmogu5jn.cloudfront.net/elephantsdream/poster.png">
|
||||
|
||||
<source src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/ed_hd.mp4" type="video/mp4">
|
||||
<source src="//d2zihajmogu5jn.cloudfront.net/elephantsdream/ed_hd.ogg" type="video/ogg">
|
||||
|
||||
<track kind="captions" src="../docs/examples/elephantsdream/captions.en.vtt" srclang="en" label="English" default>
|
||||
<track kind="captions" src="../docs/examples/elephantsdream/captions.sv.vtt" srclang="sv" label="Swedish">
|
||||
<track kind="captions" src="../docs/examples/elephantsdream/captions.ru.vtt" srclang="ru" label="Russian">
|
||||
<track kind="captions" src="../docs/examples/elephantsdream/captions.ja.vtt" srclang="ja" label="Japanese">
|
||||
<track kind="captions" src="../docs/examples/elephantsdream/captions.ar.vtt" srclang="ar" label="Arabic">
|
||||
|
||||
<track kind="descriptions" src="../docs/examples/elephantsdream/descriptions.en.vtt" srclang="en" label="English">
|
||||
|
||||
<track kind="chapters" src="../docs/examples/elephantsdream/chapters.en.vtt" srclang="en" label="English">
|
||||
|
||||
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
|
||||
</video>
|
||||
<script>
|
||||
var vid = document.getElementById('example_video_1');
|
||||
var player = videojs(vid, {
|
||||
textTrackDisplay: {
|
||||
allowMultipleShowingTracks: true
|
||||
}
|
||||
});
|
||||
|
||||
player.on('loadedmetadata', function() {
|
||||
player.textTracks()[0].mode = 'showing';
|
||||
player.textTracks()[1].mode = 'showing';
|
||||
player.textTracks()[2].mode = 'showing';
|
||||
player.textTracks()[3].mode = 'showing';
|
||||
player.textTracks()[4].mode = 'showing';
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
import Component from '../component';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
import window from 'global/window';
|
||||
|
||||
const darkGray = '#222';
|
||||
@ -240,10 +241,26 @@ class TextTrackDisplay extends Component {
|
||||
*/
|
||||
updateDisplay() {
|
||||
const tracks = this.player_.textTracks();
|
||||
const allowMultipleShowingTracks = this.options_.allowMultipleShowingTracks;
|
||||
|
||||
this.clearDisplay();
|
||||
|
||||
// Track display prioritization model: if multiple tracks are 'showing',
|
||||
if (allowMultipleShowingTracks) {
|
||||
const showingTracks = [];
|
||||
|
||||
for (let i = 0; i < tracks.length; ++i) {
|
||||
const track = tracks[i];
|
||||
|
||||
if (track.mode !== 'showing') {
|
||||
continue;
|
||||
}
|
||||
showingTracks.push(track);
|
||||
}
|
||||
this.updateForTrack(showingTracks);
|
||||
return;
|
||||
}
|
||||
|
||||
// Track display prioritization model: if multiple tracks are 'showing',
|
||||
// display the first 'subtitles' or 'captions' track which is 'showing',
|
||||
// otherwise display the first 'descriptions' track which is 'showing'
|
||||
|
||||
@ -277,29 +294,14 @@ class TextTrackDisplay extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an {@link TextTrack} to to the {@link Tech}s {@link TextTrackList}.
|
||||
* Style {@Link TextTrack} activeCues according to {@Link TextTrackSettings}.
|
||||
*
|
||||
* @param {TextTrack} track
|
||||
* Text track object to be added to the list.
|
||||
* Text track object containing active cues to style.
|
||||
*/
|
||||
updateForTrack(track) {
|
||||
if (typeof window.WebVTT !== 'function' || !track.activeCues) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cues = [];
|
||||
|
||||
for (let i = 0; i < track.activeCues.length; i++) {
|
||||
cues.push(track.activeCues[i]);
|
||||
}
|
||||
|
||||
window.WebVTT.processCues(window, cues, this.el_);
|
||||
|
||||
if (!this.player_.textTrackSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateDisplayState(track) {
|
||||
const overrides = this.player_.textTrackSettings.getValues();
|
||||
const cues = track.activeCues;
|
||||
|
||||
let i = cues.length;
|
||||
|
||||
@ -378,6 +380,53 @@ class TextTrackDisplay extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an {@link TextTrack} to to the {@link Tech}s {@link TextTrackList}.
|
||||
*
|
||||
* @param {TextTrack|TextTrack[]} tracks
|
||||
* Text track object or text track array to be added to the list.
|
||||
*/
|
||||
updateForTrack(tracks) {
|
||||
if (!Array.isArray(tracks)) {
|
||||
tracks = [tracks];
|
||||
}
|
||||
if (typeof window.WebVTT !== 'function' ||
|
||||
tracks.every((track)=> {
|
||||
return !track.activeCues;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cues = [];
|
||||
|
||||
// push all active track cues
|
||||
for (let i = 0; i < tracks.length; ++i) {
|
||||
const track = tracks[i];
|
||||
|
||||
for (let j = 0; j < track.activeCues.length; ++j) {
|
||||
cues.push(track.activeCues[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// removes all cues before it processes new ones
|
||||
window.WebVTT.processCues(window, cues, this.el_);
|
||||
|
||||
// add unique class to each language text track & add settings styling if necessary
|
||||
for (let i = 0; i < tracks.length; ++i) {
|
||||
const track = tracks[i];
|
||||
|
||||
for (let j = 0; j < track.activeCues.length; ++j) {
|
||||
const cueEl = track.activeCues[j].displayState;
|
||||
|
||||
Dom.addClass(cueEl, 'vjs-text-track-cue');
|
||||
Dom.addClass(cueEl, 'vjs-text-track-cue-' + ((track.language) ? track.language : i));
|
||||
}
|
||||
if (this.player_.textTrackSettings) {
|
||||
this.updateDisplayState(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component.registerComponent('TextTrackDisplay', TextTrackDisplay);
|
||||
|
Loading…
Reference in New Issue
Block a user