http-streaming icon indicating copy to clipboard operation
http-streaming copied to clipboard

Dash captions cannot handle duplicate "lang" and ignores label

Open EyMaddis opened this issue 5 years ago • 13 comments

Description

When providing multiple subtitle tracks in dash, not every track is selectable. This happens if the lang=".." attribute has the same value more than once. Only the first one is selectable

In the manifest, the <AdaptationSet mimeType="text/vtt" lang="de"> is contained twice. Once with a label "Deutsch" and once with "forced", but only "de" will be shown, so a related issue is that Label is ignored!

This is contained twice (with different labels):

<AdaptationSet mimeType="text/vtt" lang="de">
    ....
      <Label>Forced</Label>
....
    </AdaptationSet>

Sources

Playlist that does not work: https://universum-dev-public.s3-eu-west-1.amazonaws.com/dash_fake_caption_de_de.mpd

In case the files ever lead to 404, here is the source:

<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" type="static" minBufferTime="PT30S" profiles="urn:mpeg:dash:profile:isoff-main:2011" mediaPresentationDuration="PT3M0.224S">
  <Period start="PT0S" duration="PT3M0.224S" id="1">
    <AdaptationSet mimeType="video/mp4" frameRate="24000/1001" segmentAlignment="true" subsegmentAlignment="true" startWithSAP="1" subsegmentStartsWithSAP="1" bitstreamSwitching="false">
      <SegmentTemplate timescale="96000" media="dashvideo_1080_dash_$Number%09d$.mp4" initialization="dashvideo_1080_dashinit.mp4" duration="3603600" startNumber="1"/>
      <Representation id="1" width="1920" height="1080" bandwidth="6000000" codecs="avc1.640028"/>
    </AdaptationSet>
    <AdaptationSet mimeType="audio/mp4" lang="eng" segmentAlignment="0">
      <SegmentTemplate timescale="48000" media="dashaudio_ger_dash_$Number%09d$.mp4" initialization="dashaudio_ger_dashinit.mp4" duration="1801800" startNumber="1"/>
      <Label>DE</Label>
      <Representation id="2" bandwidth="256000" audioSamplingRate="48000" codecs="mp4a.40.2"/>
    </AdaptationSet>
    <AdaptationSet mimeType="audio/mp4" lang="eng" segmentAlignment="0">
      <SegmentTemplate timescale="48000" media="dashaudio_engl_dash_$Number%09d$.mp4" initialization="dashaudio_engl_dashinit.mp4" duration="1801800" startNumber="1"/>
      <Label>ENG</Label>
      <Representation id="3" bandwidth="96000" audioSamplingRate="48000" codecs="mp4a.40.2"/>
    </AdaptationSet>
    <AdaptationSet mimeType="text/vtt" lang="de">
      <Role schemeIdUri="urn:mpeg:dash:role" value="subtitle"/>
      <Label>Deutsch</Label>
      <Representation id="4" bandwidth="256">
        <BaseURL>dashcaption_de_dash.mpd</BaseURL>
      </Representation>
    </AdaptationSet>
    <AdaptationSet mimeType="text/vtt" lang="de">
      <Role schemeIdUri="urn:mpeg:dash:role" value="subtitle"/>
      <Label>Forced</Label>
      <Representation id="5" bandwidth="256">
        <BaseURL>dashcaption_forced_dash.mpd</BaseURL>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>

Steps to reproduce

Test case:

  1. open https://videojs.github.io/http-streaming/
  2. enter https://universum-dev-public.s3-eu-west-1.amazonaws.com/dash_fake_caption_de_de.mpd
  3. select application/dash+xml
  4. hit load (the video is not going to play, but it does not need to!)
  5. observe captions to only include de:

image

Results

Expected

Expected the text tracks list to show Deutsch and Forced instead of de once.

Additional Information

If you use https://universum-dev-public.s3-eu-west-1.amazonaws.com/dash_fake_caption_de_en.mpd it will separate the two tracks. All I did was to change the second lang to en instead of de!

videojs-http-streaming version

what version of videojs-http-streaming does this occur with? videojs-http-streaming 1.10.4 ( latest from example page )

videojs version

what version of videojs does this occur with? video.js 7.5.5

Browsers

Tested in

  • Chrome 76.0.3809.100
  • Chrome Canary 78.0.3890.0
  • Firefox 67.0.4 (64-bit)

Platforms

what platforms are affected? please include operating system and version or device and version for each

  • MacOS Mojave 10.14.5 (18F132)
  • I guess all...

EyMaddis avatar Aug 27 '19 12:08 EyMaddis

👋 Thanks for opening your first issue here! 👋

If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

welcome[bot] avatar Aug 27 '19 12:08 welcome[bot]

Just a sidenote: The dash.js reference does this correctly: http://reference.dashif.org/dash.js/v3.0.0/samples/dash-if-reference-player/index.html

I thought that this might be a trivial usage of a Set in the parser and a missing getter for the label, but I have no idea where to actually find the parsing code to begin the investigation.

EyMaddis avatar Aug 27 '19 12:08 EyMaddis

Interesting, it's possible that we deduping based on kind and language. Looking at the HTML spec now, it seems that label is also used for deduping, though, I thought that labels didn't count previously. So, it's definitely possible we're not doing the right thing.

gkatsev avatar Aug 27 '19 18:08 gkatsev

I reproduced the same problem with audio languages. Same example as above. @gkatsev Is there a quick workaround if the files are immutable for me?

Or maybe you have a suggestion where to start when I want to investigate this myself.

EyMaddis avatar Aug 28 '19 16:08 EyMaddis

@gkatsev I think this boils down to this line. Maybe not specifically this line, but there are probably multiple occasions where this happens. As I said, the same applies to audio tracks.

EyMaddis avatar Aug 29 '19 10:08 EyMaddis

Yeah, could be related to that piece.

gkatsev avatar Aug 29 '19 19:08 gkatsev

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Oct 28 '19 20:10 stale[bot]

This is still very important

EyMaddis avatar Oct 28 '19 22:10 EyMaddis

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Dec 27 '19 23:12 stale[bot]

@gkatsev Is there actually a need to dedupe the data at all?

EyMaddis avatar Jan 28 '20 10:01 EyMaddis

Is there any change for looking into this? Especially the Label part 🤔

RomeroDiver avatar Nov 16 '20 14:11 RomeroDiver

I found the language and text track selection to be rather unusable for our files. Just to give a small insight (Please be aware that this originated in a previous version of Shaka and might not be necessary anymore):


function filterTextTracks({ language }: shaka.extern.Track) {
  return language !== 'und' && language.length > 0 // HLS bug, this is probably a part of `undefined`
}

const toSelect: shaka.extern.Track | undefined = player
    .getTextTracks()
    .filter(filterTextTracks)
    .find((t, index) => {
    return String(index) === track.internalId
    })
// TODO: We cant really control what track is selected on Dash. So far it looks like fulls subs are always the first entry
// which results in this function working as required, but might cause issues if this is not the case.
player.selectTextTrack(toSelect)
// silly safari bug fix, does not update if the state was incorrectly true already
// player.setTextTrackVisibility(false)
player.setTextTrackVisibility(true)

For AudioTracks it is even worse, especially on Safari where we need to use the following:

player.configure({
  abr: {
    enabled: false,
  },
})
// CAREFUL! This causes the previous track to be shown as 'active=true' for short period of time, which needs to be

// see: https://shaka-player-demo.appspot.com/docs/api/shaka.extern.html#.Track ->
// active: 'If true, this is the track being streamed (another track may be visible/audible in the buffer).'
// We, therefore, pass the currently selected track to distinguish between the active tracks from getVariantTracks().
player.selectVariantTrack(
  player.getVariantTracks().find(t => t.label === track.internalId),
  true
)
player.configure({
  abr: {
    enabled: true,
  },
})

EyMaddis avatar Nov 16 '20 17:11 EyMaddis

bump

ghost avatar Sep 23 '22 11:09 ghost