Hls.js: Faulty playback of Alternate-Audio Playlists with Primary/Backup, if Primary returns 404 (since hls.js 0.8.3)

Created on 21 Nov 2017  路  12Comments  路  Source: video-dev/hls.js

Environment

Steps to reproduce
  1. Open (broken since 0.8.3, same in any newer version) http://streambox.fr/mse/hls.js-0.8.3/demo/?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined
  2. The stream does not startup - "error while loading level playlist"
  3. In version 0.8.2: http://streambox.fr/mse/hls.js-0.8.2/demo/?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined
  4. The stream automatically switches to the backup stream (as Primary returns 404!)
Expected behavior

hls.js supports fallback to backup-renditions in older versions, but it generally seems to fail on playlists with GROUP-IDs, supporting alternate audio.

More info on Primary/Backup-Playlists:
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-SW22

More info on Error-Handling for HTTP-Live-Streaming:
https://developer.apple.com/videos/play/wwdc2017/514/

Actual behavior

there is a final "error while loading level playlist" instead of falling back to the backup source.

Console output
[log] > loadSource:https://apiproxy.akamaized.net/hlsjs/av/master_prim_faila.m3u8
logger.js:37 [log] > trigger BUFFER_RESET
logger.js:37 [log] > set autoLevelCapping:-1
logger.js:37 [log] > attachMedia
logger.js:37 [log] > media source opened
logger.js:37 [log] > manifest loaded,1 level(s) found, first bitrate:1288815
logger.js:37 [log] > startLoad(-1)
logger.js:37 [log] > switching to level 0
logger.js:37 [log] > loading playlist for level 0
logger.js:37 [log] > main stream:STOPPED->IDLE
logger.js:37 [log] > audio tracks updated
logger.js:37 [log] > subtitle tracks updated
xhr-loader.js:80 GET https://apiproxy.akamaized.net/hlsjs/av/av-1400-p/prog_index.m3u8 404 (Not Found)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onLevelLoading @ playlist-loader.js:170
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:84
trigger @ hls.js:88
setLevelInternal @ level-controller.js:177
set @ level-controller.js:151
set @ level-controller.js:372
set @ hls.js:245
startLoad @ stream-controller.js:88
(anonymous) @ hls.js:178
startLoad @ hls.js:178
onManifestParsed @ stream-controller.js:898
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
onManifestLoaded @ level-controller.js:120
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadsuccess @ playlist-loader.js:530
readystatechange @ xhr-loader.js:117
XMLHttpRequest.send (async)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onManifestLoading @ playlist-loader.js:166
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadSource @ hls.js:173
loadStream @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:285
(anonymous) @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:258
logger.js:37 [error] > 404 while loading https://apiproxy.akamaized.net/hlsjs/av/av-1400-p/prog_index.m3u8
(anonymous) @ logger.js:37
readystatechange @ xhr-loader.js:121
XMLHttpRequest.send (async)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onLevelLoading @ playlist-loader.js:170
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:84
trigger @ hls.js:88
setLevelInternal @ level-controller.js:177
set @ level-controller.js:151
set @ level-controller.js:372
set @ hls.js:245
startLoad @ stream-controller.js:88
(anonymous) @ hls.js:178
startLoad @ hls.js:178
onManifestParsed @ stream-controller.js:898
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
onManifestLoaded @ level-controller.js:120
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadsuccess @ playlist-loader.js:530
readystatechange @ xhr-loader.js:117
XMLHttpRequest.send (async)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onManifestLoading @ playlist-loader.js:166
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadSource @ hls.js:173
loadStream @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:285
(anonymous) @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:258
logger.js:37 [warn] > level controller,levelLoadError for level 0: switching to redundant stream id 1
(anonymous) @ logger.js:37
onError @ level-controller.js:273
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loaderror @ playlist-loader.js:560
readystatechange @ xhr-loader.js:122
XMLHttpRequest.send (async)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onLevelLoading @ playlist-loader.js:170
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:84
trigger @ hls.js:88
setLevelInternal @ level-controller.js:177
set @ level-controller.js:151
set @ level-controller.js:372
set @ hls.js:245
startLoad @ stream-controller.js:88
(anonymous) @ hls.js:178
startLoad @ hls.js:178
onManifestParsed @ stream-controller.js:898
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
onManifestLoaded @ level-controller.js:120
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadsuccess @ playlist-loader.js:530
readystatechange @ xhr-loader.js:117
XMLHttpRequest.send (async)
loadInternal @ xhr-loader.js:80
load @ xhr-loader.js:39
load @ playlist-loader.js:217
onManifestLoading @ playlist-loader.js:166
onEventGeneric @ event-handler.js:65
onEvent @ event-handler.js:53
EventEmitter.emit @ events.js:96
trigger @ hls.js:88
loadSource @ hls.js:173
loadStream @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:285
(anonymous) @ ?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:258
?src=https%3A%2F%2Fapiproxy.akamaized.net%2Fhlsjs%2Fav%2Fmaster_prim_faila.m3u8&enableStreaming=true&autoRecoverError=true&enableWorker=true&dumpfMP4=false&levelCapping=-1&defaultAudioCodec=undefined:528 {type: "networkError", details: "levelLoadError", fatal: false, url: undefined, loader: XhrLoader,聽鈥
Bug Wontfix

All 12 comments

This is pretty curious - if i click on the demo link (#1 in steps to reproduce) the playback starts. But if you reload the demo-page it's getting broken.
In version 0.8.2 or below this seems to work fine.

Thanks @netTrekfd for opening this ticket!

one note:
hls.js Support for Primary/Backup Failover for HLS-Streams with Alternate Audio
e.g. https://apiproxy.akamaized.net/hlsjs/multichannelaudio/master_prim_fail_v1a.m3u8
has never worked (at least tested with hls.js 0.62-0.87).

I gave it a try and this commit broke something between 0.8.2 and 0.8.3 (stream controller is stuck in IDLE if first level request fails ...)
but then while rechecking against 0.8.7 I found out that a second thing has been broken : the logic dealing with switching to redundant level in case level request fails has been removed (most probably by https://github.com/video-dev/hls.js/pull/1346)
ping @NicolasSiver

I'm going to look into this. What exactly we had in 0.8.2 which would drive a switch to backup stream for a level manifest.

With latest changes it works:

image

I will push PR soon.

Thanks @NicolasSiver for providing the fix. I can confirm that the first of my sample streams now is playable.
But the error persists for my second sample (multiaudio playlist) where both the primary video & primary audio manifests are broken:
https://apiproxy.akamaized.net/hlsjs/multichannelaudio/master_prim_fail_v1a.m3u8

Can you please check and reopen?
Thanks!

@NicolasSiver @mangui Could you please recheck this issue with my teststream (see comment above). I think the switching logic is still broken. Or shall i create a new ticket for it?
Thanks!

@netTrekfd Hey! I tested and indeed the 404 error doesn't recover well. Would need to look further into this. Feel free to contact me directly.

@netTrekfd this might fix this issue in a simple way ^ :) check it out.

Re-opening this as it is not fixed on master yet, see PR https://github.com/video-dev/hls.js/pull/1630 which fixes this partly (but not merged yet).

Here is an updated description of the issue which is partly solved by above PR

Status:

  • Video/Audio Variant-Playlists of Primary will return HTTP 404 and can not be played back, but Video/Audio Variant-Playlists and Subtitle-Playlists of Backup are playable.

Expected behavior:

  • The Player should be able to playback a HLS-LiveStream with faulty Primary-Variant-Playlists, but working Backup-Variant Playlists.
    On start of Playback, Status of primary is faulty (HTTP 404), backup is OK.

Sample-Playlist:
https://apiproxy.akamaized.net/hlsjs/multichannelaudio/master_prim_fail_v1a.m3u8
https://apiproxy.akamaized.net/hlsjs/zdf/check_primfail4.m3u8

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.

Was this page helpful?
0 / 5 - 0 ratings