-
Notifications
You must be signed in to change notification settings - Fork 130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Load text tracks from dash into video.js #135
Load text tracks from dash into video.js #135
Conversation
7f3cfc8
to
d774648
Compare
I might look into generating cues before calling Somethings to consider in this implementation:
|
c74b11b
to
cfe82ae
Compare
I'm new to working with video.js's implementation, but the Stepping through the
I updated how I handle this. If I apply the
Agreed, the source for |
I've reviewed all the samples in #103. This PR in it's current state does not match the functionality of the dash reference player. I'll keep working on it. |
cfe82ae
to
be9aa24
Compare
With this update, it's worked with everything I can throw at it @chemoish . |
I found what I perceive to be a flaw in the text track selection logic. This assumes a 1:1 relationship between dash text tracks and videojs's DOM track list. This is not guaranteed because the user can manipulate the videojs text tracks however they like (or not even use them), so this needs to be modified. |
src/js/setup-text-tracks.js
Outdated
// Example: | ||
// https://storage.googleapis.com/shaka-demo-assets/sintel-mp4-wvtt/dash.mpd | ||
|
||
// Return `track` so we can continue chaning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chaining
+ does this require chaining still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chemoish No, it doesn't :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
possibly update to .each
and remove comment/return.
src/js/videojs-dash.js
Outdated
|
||
// When `dashjs` finishes loading metadata, create audio tracks for | ||
// `video.js`. | ||
this.mediaPlayer_.on( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor, any reason why the event handler is bound inline rather than within the setup (different implementation than textTrack
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No good reason @chemoish , I will update it to make them consistent.
5067eb4
to
10fc47d
Compare
Updates pushed with the following changes:
|
10fc47d
to
f0a38b5
Compare
src/js/setup-text-tracks.js
Outdated
function attachDashTextTracksToVideojs(player, tracks) { | ||
const mediaPlayer = player.dash.mediaPlayer; | ||
|
||
const trackDictionaryKeyedByTextTrack = new WeakMap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's a good idea to use WeakMap yet, still. To support the widest field of browsers possible, we can't use WeakMap and WeakMap isn't really polyfillable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll replace it with a Map()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might not want to either Map either depending on which browsers we're targeting for this project. We wouldn't want to require es6-shim for Map()
support if we expect to be able to run this package in a browser that supports MSE+EME but not Map()
.
@forbesjo do need to worry about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, I didn't check to see how the babel transforms were handled. Map
can't be polyfilled so I agree it's unacceptable. I'll replace it.
src/js/setup-text-tracks.js
Outdated
tracks | ||
// Map input data to match HTMLTrackElement spec | ||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLTrackElement | ||
.map((track) => Object.assign( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any specific reason to assign on top of the dash.js track rather than just create a new object containing only the properties needed by the video.js track?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No good reason, I can axe the track
reference.
src/js/setup-text-tracks.js
Outdated
const textTracks = this.textTracks(); | ||
let activeTextTrackIndex = -1; | ||
|
||
function findMatchingTrack(dashTrack) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is only used in once spot, it may be easier to read if it is just inlined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was my original plan, but jshint didn't like me creating functions within a loop.
src/js/setup-text-tracks.js
Outdated
// Iterate through the tracks and find the one marked as showing. | ||
// If none are showing, `activeTextTrackIndex` will be set to | ||
// `-1`, disabling text tracks. | ||
for (let i = 0; i < textTracks.length; i += 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i++
just for consistent style
src/js/setup-text-tracks.js
Outdated
// Add track to videojs track list | ||
.map((track) => { | ||
const remoteTextTrack = player.addRemoteTextTrack(track, true); | ||
trackDictionaryKeyedByTextTrack.set(remoteTextTrack.track, track); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might make sense to match the original dash.js track (instead of the new reference) to make it easier down below (can skip trying to find the reference based on index matching, since we have the reference).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand. Later on I use index matching because I have to loop through player.textTracks()
to find the active track. After that, I use that track to figure out the dash track. dash.setTextTrack()
expects an index so I have to first find it, then figure out it's index. I must be missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point. When we're using remote time text files .getTracksFor('text')
will return an empty array so we have no choice but to use the tracks
passed in the event handler.
src/js/setup-text-tracks.js
Outdated
*/ | ||
const textTracks = player.textTracks(); | ||
|
||
for (let i = 0; i < textTracks.length; i += 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i++
just for consistent style
src/js/setup-text-tracks.js
Outdated
mediaPlayer.updateDashTextTrack(); | ||
|
||
// Update dash when videojs's selected text track changes. Use an arrow function so | ||
// `mediaPlayer.updateDashTextTrack` can be overriden exterally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we are ready yet to provide an external function that people can override. If we do though, we may want to add it onto player.dash, since mediaPlayer is technically a dash.js object that we don't have control over.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a mistake, I had used this logic elsewhere and forgot to remove it. I'll remove it here.
f0a38b5
to
82eba76
Compare
82eba76
to
91ae1b5
Compare
Use of |
91ae1b5
to
981cdb2
Compare
The audio track manipulation breaks dash playback in Safari 10.0.3. I am investigating. |
src/js/videojs-dash.js
Outdated
@@ -89,6 +91,12 @@ class Html5DashJS { | |||
this.mediaPlayer_.setProtectionData(this.keySystemOptions_); | |||
this.mediaPlayer_.attachSource(manifestSource); | |||
|
|||
// Setup text tracks | |||
setupTextTracks.call(null, this.player, tech); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be called before attachSource()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is that dashjs.MediaPlayer.events.TEXT_TRACKS_ADDED
/dashjs.MediaPlayer.events.PLAYBACK_METADATA_LOADED
may fire between attachSource()
and the event listener setup functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense. If the user can fetch a source and attach it, this might become a sync call and the events might get missed. I've moved the calls to be before attachSource()
.
I have a question and could use some advice. I'm having trouble bypassing native captions in Safari because of this line: https://github.com/videojs/video.js/blob/master/src/js/tech/html5.js#L798 I have been unsuccessful in finding a smooth way to disable native text tracks other than globally disabling it in the Html5 tech when There has to be a better way, can anyone give me some advice on where to look or what to do? |
As of video.js v5.14, video.js no longer supports native subtitles on anything besides Safari. For Chrome, this means there is *no* subtitle support with mpeg-dash. This will wait for dash.js to load all the text tracks and then add them to video.js if we're using a version that does not attempt to use native subtitles. When the video.js menu is used to change captions, we'll set the corresponding active text track in dash. We *cannot* dynamically add text track cues to video.js beacuse fragmented text tracks are loaded on the fly and there's no event fired when they are loaded. Therefore, we must has dash to natively display captions.
The v5.18.0 release of video.js includes a fix for videojs/video.js#4093 with videojs/video.js#4131. This is neccessary for text tracks to work in Chrome.
- Only set `textTrack.mode` for `captions` and `subtitles. - Don't call the initial `updateActiveDashTextTrack` until after the `textTrack.mode`s have been set.
e815d1e
to
f69fab8
Compare
Any updates on this @forbesjo ? |
FYI, I downloaded the patch of this PR, and noticed that changing the caption display settings doesn't actually change them. |
That's correct. The captions will be displayed natively by dash.js. |
@justinanastos testing this now |
@justinanastos Why would that preclude video.js from setting the caption style? Aren't the dash.js captions being spit out as |
Dash.js renders the captions natively rather than using Video.js's rendering capabilities. That means that the styling that Video.js can provide via the caption settings menu isn't (and potentially can't be) applied. |
Can't videojs just set CSS classes or something though? |
@justinanastos your PR works for me but as has been discussed the captions style cannot be changed since dash.js is doing the rendering and not video.js. Looking into this |
It doesn't look like there's a mechanism to disable the dash.js display so I agree with @gkatsev that the caption settings menu item should be disabled. |
@squarebracket I'm not sure if it's a great idea to reuse video.js's text track display for TTML rendering. Instead this script can add a new component div to the player specifically for TTML. That can be done in a separate PR. @gkatsev what's the recommended way of disabling menu items like the captions settings item? Thinking about this a little more we would still want to display caption settings if there are side-loaded captions (captions not coming from the source manifest). Though when a mix of in-manifest and external captions are present in the player a view might be confused when some captions can be customized while others cannot. |
I think we should leave the captions settings alone, merge this PR in and add other enhancements later |
@squarebracket I believe native cue rendering can do the same thing you're showing, right? There can be multiple cues on the screen at once and their position is defined by the vtt file. |
@justinanastos that is correct, however that information is dropped in the dash.js VTTCue rendering library, but is rendered for the TTML rendering library. |
As of video.js v5.14, video.js no longer supports native subtitles on anything besides Safari. For Chrome, this means there is no subtitle support. This will wait for dash.js to load all the text tracks and then add them to video.js if we're using a version that does not attempt to use native subtitles. Audio tracks will also be added.
Todo
.map
with.forEach
Load text tracks from dash into video.js #135 (review)WeakMap
Load text tracks from dash into video.js #135 (review)Map
Location forautomaticTextTrackSelection
optionWait for videojs/video.js#4131 to be merged. Add that version as an explicit dependency (maybe change it to apeerDependency
anddevDependency
since we don't actually need it here?This fix depends on videojs@^v5.18