androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.68k stars 399 forks source link

ExoPlayer adds an additional empty subtitle track not present in the HLS playlist #432

Open hakonschia opened 1 year ago

hakonschia commented 1 year ago

Media3 Version

ExoPlayer 2.18.7

Devices that reproduce the issue

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

  1. Add the provided samples to media.exolist.json
  2. Play Subtitle samples > Sample 1 (broken)
  3. Open text track selector/subtitle dialog

Expected result

Only the subtitles given in the HLS playlist are shown in the track selector/subtitle selector dialog

Actual result

An additional subtitle choice with no label ("Unknown") is shown

This is a screenshot from a breakpoint in onTracksChanged() when playing Sample 1 (broken). There are two groups with type=C.TRACK_TYPE_TEXT, but the HLS playlist only contains one subtitle. The first group (id=main:muxed:2) is the erroneous one

studio64_oevZnpSo35

Media

Some samples to be added to media.exolist.json:

{
  "name": "Subtitle samples",
  "samples": [
    {
      "name": "Sample 1 (broken)",
      "uri": "https://nrk-od2.telenorcdn.net/open/ps/mynt/mynt25000121/8092c2d8-4.smil/muxed.m3u8?adap=small"
    },
    {
      "name": "Sample 2 (works)",
      "uri": "https://nrk-od2.telenorcdn.net/open/ps/nnfa/nnfa19060123/a2fff27f-7.smil/muxed.m3u8?adap=small"
    }
  ]
}

Bug Report

icbaker commented 1 year ago

Neither of the provided streams specify the optional CLOSED-CAPTIONS attribute in their EXT-X-STREAM-INF tags (see RFC 8216 section 4.4.6.2). This means it's up to the player to try and guess whether the MPEG-TS files contain muxed CEA-608 captions.

I believe the difference in behaviour between the two streams is because ExoPlayer handles the 'works' stream using 'chunkless preparation', but is unable to do this for the 'broken' stream (ExoPlayer tries to use chunkless prep by default for all HLS streams, only falling back to chunkful if necessary). I confirmed this by disabling chunkless preparation, and then both streams show the 'Unknown' subtitle track.

Some options to resolve this immediately:

  1. Update the streams to categorically state they don't contain CEA-608 subtitles muxed in their MPEG-TS segments. You can do this by adding CLOSED-CAPTIONS=NONE to all the EXT-X-STREAM-INF tags.
  2. Customise your HlsMediaSource.Factory by setting a DefaultHlsExtractorFactory constructed with exposeCea608WhenMissingDeclarations = false. See more info about customising media source factories: https://developer.android.com/guide/topics/media/exoplayer/media-sources#customizing-media-source-creation

I'm assigning this to @tianyif because the difference between chunkless & chunkful seems unexpected here. I believe that we default to exposeCea608WhenMissingDeclarations = true for compatibitility with streams that mux CEA-608 captions into their MPEG-TS segments without adding CLOSED-CAPTIONS attributes to their playlist. However if this behaviour doesn't work with chunkless preparation, then players needing to extract subtitles from these streams already have to customise their ExoPlayer to disable chunkless preparation - at which point they could also customise it to set exposeCea608WhenMissingDeclarations = true meaning we could safely flip the default of exposeCea608WhenMissingDeclarations to false (or it's a bug that exposeCea608WhenMissingDeclarations = true doesn't work with chunkless preparation - which should also be investigated).

hakonschia commented 1 year ago

Thanks for the quick and thorough reply! I've quickly tested and it works as expected when specifying CLOSED-CAPTIONS=NONE

hakonschia commented 1 year ago

Just a follow up question regarding chunkless preparation. Am I understanding it correctly that the broken sample has to use chunkful preparation because CODECS contains ac-3 without defining a corresponding #EXT-X-MEDIA:TYPE=AUDIO and referring to the audio group in the #EXT-X-STREAM-INF tag?