1
0
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:
Thomas 2019-06-18 12:41:16 -07:00 committed by Gary Katsevman
parent 2c7644f91e
commit c61f3d3e49
2 changed files with 129 additions and 20 deletions

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Video.js Text Descriptions, Chapters &amp; 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>

View File

@ -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);