range.end returned by getDVRWindowRange() is lower than actual end of live stream
vitalist82 opened this issue · comments
Hello,
we are using hasplayer.js for playing MSS+PlayReady streams.
In live streams, that have DVRWindowLength/TimeScale equal to 8hrs and total duration aprox. 1.5hr, we have a problem, when seeking back is performed, followed by few minutes of playback and then with an attempt to return to actual live position (time counted as sum of durations of all segments in manifest).
In such case, the player reports "loadNextFragment failed" for both audio and video and continues to fire timeupdate events while BufferController reports a constant Working time value and BufferLevel equal to 0 for 1 minute followed by this log:
[22:29:37.074][AbrController][video] Set playback quality: 0
[22:29:37.075][StreamController] Reset
[22:29:37.082][MediaPlayer] set config: {
"BufferController.liveDelay": 32,
"BufferController.minBufferTimeForPlaying": 3,
"BufferController.minBufferTime": 32,
"FragmentLoader.RetryAttempts": 6
}
[22:29:37.083][AbrController][video] Set playback quality: 4
[22:29:37.084][MediaPlayer] set config: {
"video": {
"ABR.keepBandwidthCondition": false
},
"audio": {
"ABR.keepBandwidthCondition": true
}
}
[22:29:37.085]<video> # play()
[22:29:37.167][Stream] <video> timeupdate event: 1516742860.662
[22:29:37.167][BufferController][video] Working time = 1516742860.662, Buffer level = 0.000
[22:29:37.168][BufferController][audio] Working time = 1516742860.662, Buffer level = 0.000
[22:29:37.168][Stream] <video> pause event
[22:29:37.168][Stream] stopBuffering
[22:29:37.168][BufferController][video] STOP
[22:29:37.169][BufferController][audio] STOP
[22:29:37.169][MssFragmentInfoController][video] START
[22:29:37.169][MssFragmentInfoController][video] Load next fragment for time: 1516742705.84
[22:29:37.169][MssFragmentInfoController][video] Request fragment info https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(112000)/FragmentInfo(video=15167427058400000)?stream_id=66532392309
[22:29:37.170][MssFragmentInfoController][video] Load request https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(112000)/FragmentInfo(video=15167427058400000)?stream_id=66532392309
[22:29:37.170][FragmentLoader][video] Load: https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(112000)/FragmentInfo(video=15167427058400000)?stream_id=66532392309
[22:29:37.173][MssFragmentInfoController][audio] START
[22:29:37.174][MssFragmentInfoController][audio] Load next fragment for time: 1516742717.36
[22:29:37.174][MssFragmentInfoController][audio] Request fragment info https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(64000)/FragmentInfo(audio_1=15167427173600000)?stream_id=66532392309
[22:29:37.175][MssFragmentInfoController][audio] Load request https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(64000)/FragmentInfo(audio_1=15167427173600000)?stream_id=66532392309
[22:29:37.176][FragmentLoader][audio] Load: https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(64000)/FragmentInfo(audio_1=15167427173600000)?stream_id=66532392309
[22:29:37.194][Stream] Pause.
[22:29:37.194]<video> # pause()
[22:29:37.195][Stream] Reset
[22:29:37.195][Stream] stopBuffering
[22:29:37.195][MssFragmentInfoController][video] STOP
[22:29:37.196][FragmentLoader][video] Abort XHR
[22:29:37.196][MssFragmentInfoController][audio] STOP
[22:29:37.197][FragmentLoader][audio] Abort XHR
[22:29:37.197][Stream] Pause.
[22:29:37.197]<video> # pause()
[22:29:37.215][Warn] Code: DOWNLOAD_ERR_CONTENT, Message: Failed to download fragmentInfo segment, Data: {
"url": "https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(112000)/FragmentInfo(video=15167427058400000)?stream_id=66532392309",
"status": 0
}
[22:29:37.230][Warn] Code: DOWNLOAD_ERR_CONTENT, Message: Failed to download fragmentInfo segment, Data: {
"url": "https://dc3livecadz-a.akamaihd.net/live/channel/1010/all.ism/QualityLevels(64000)/FragmentInfo(audio_1=15167427173600000)?stream_id=66532392309",
"status": 0
}
[22:29:37.265][MediaPlayer] Version: 1.13.1_f1b61eb - 2017-12-1_13:0:43
[22:29:37.265][MediaPlayer] user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; rv:11.0) like Gecko
[22:29:37.266][MediaPlayer] Load stream:
{
"url": "https://dc4livecadz-a.akamaihd.net/live/channel/1010/all.ism/Manifest?event_id=66532392309&h=1e57f64553d84b86590afa5c3742e072",
"startTime": 0,
"protData": {
"com.microsoft.playready": {
"laURL": "..."
[22:29:37.266][StreamController] load url: https://dc4livecadz-a.akamaihd.net/live/channel/1010/all.ism/Manifest?event_id=66532392309&h=1e57f64553d84b86590afa5c3742e072
[22:29:37.349][MssParser] Doing parse.
[22:29:37.876][MssParser] Parsing complete (xmlParser: 47ms, mss2dash: 480ms, total: 0.527s)
[22:29:37.884]<video> # reset source
[22:29:38.509][StreamController] Manifest updated
[22:29:38.510][StreamController] composeStreams
[22:29:38.511][StreamController] Create stream
[22:29:38.514][Stream] Create MediaSource
...
Then the playback starts from live end.
When I tried to use MediaPlayer.getDVRWindowRange() to get a valid seeking range for live stream to seek to the end of the stream instead of using the sum of durations of all segments from manifest, I was getting a value, that was not actual end of the stream, but few minutes behind.
This issue is not visible, when the seek call to the end of the stream is performed quickly after the first seek call. But the longer the player plays behind the live end position, the bigger the difference between range.end and actual end of the live stream.
Seeking to range.end works without problems compared to seeking to a time value above.
Could you please suggest a proper way to seek back to actual live position (current end of live stream) from a position somewhere in the middle of the live stream?
The issue was reported on XboxOne, which is using Edge browser and it can also be reproduced on IE11.
Thanks.
Best regards,
Tomas Beranek
Hi @vitalist82 ,
the call to the getDVRWindowRange has to be done each time that a timeUpdate occurs in order to keep this window uptodate. is it what you do? Then, your seek command could be done without problems.
Nico
Hi @nicosang ,
I added the call to getDVRWindowRange to timeupdate event handler.
The returned value is updated well, but stops being updated after seeking back in the stream.
Tomas
are the fragmentInfo requests well downloaded? When you do a seek command, fragmentInfo requests are started in order to, exactly, update dvr info....
I attached full trace containing only few fragmentInfo requests.
seek-to-live-2.txt
Both seek events triggered by user interaction are included in the log.
Hi @vitalist82 ,
The problem is indeed about fragmentInfo requests. I took a look at your log. We can see that only one fragmentInfo is requested (one video and one audio). It seems that this fragmentInfo has only one tfrf box, normally there is two tfrf boxes. This boxes are important because they give timestamps of the next fragmentInfo. Do you know why you just have one box of this type?
Nico
Hi @nicosang ,
I don't know the reason for having only one tfrf box, but I can ask our stream provider.
I've been looking into https://dc3livededz-a.akamaihd.net/live/channel/1017/all.ism/QualityLevels(112000)/FragmentInfo(video=15168305732000000)?stream_id=67198504400 with MP4 Reader and it doesn't seem to contain any tfrf box.
Thanks,
Tomas
the last uuid box in the traf box is the tfrf box. My last comment was not precise enough....you should have one tfrf box with two entries in it (so, not really two tfrf boxes). Anyway, I think that adding the second entry should solve your issue....
There is a note from our stream provider:
so, when fragments are requested right up against the live edge, it's possible that there are not yet two fragments which follow the one being requested
in that case, I suspect the origin will serve fewer than the requested number of 'lookahead references'
and once that happens, the CDNs will of course cache those responses for$LONG_TIME
Could this be an explanation for this behaviour?
maybe....is it possible that you give us access to your live stream? hasplayer.js could maybe improve its behavior....
I can send you a manifest URL and apropriate LA URL with an expiration period, that should be longer, than the duration of the live event, if that would help. There will be multiple live events available tomorrow at following times:
09:00
10:00
12:00
13:00
14:30
15:00
16:45
17:15
Once the apropriate live event will start, I can send you the URLs to work with.
no problem, send me the stream when it will be available tomorrow. I'm in Europe, I hope you too...it will be easier to synchronize us.
Hi Nico,
I forget to add, that those time are in GMT. Yes, I'm in Europe too.
There is a live event going on right now:
The license should be valid for long enough. I can send you URLs of upcoming events later, when needed.
Hi Nico,
if you would like another manifest and LA URL, I can send it to you.
Regards,
Tomas
Thanks Nico,
There is a live stream now, which will last for about one hour only, so I hope it will be enough. Later I will send another URLs to you. I've sent the URLs to your mailbox.
Tomas
Hey, @nicosang I'll send you a fresh Manifest/LA pair in a minute for a live stream per Tomas request.
Cheers,
Krzysztof
Hi @vitalist82 and @krozalski ,
could you, please, take a look at my last PR #215 ? I hope it will fix your issue.....
Thanks,
Nico
Hi @nicosang ,
I attached traces from the playback using hasplayer build from the fix branch.
It seems, that fragmentinfo requests are not being sent.
Tomas
bug fixed by PR #215
Many thanks @nicosang for the fix!
Best regards,
Tomas