Orange-OpenSource/hasplayer.js

Seeking in live issue in browser based on Qt WebEngine

Closed this issue · 3 comments

There's following problem with seeking in live streams on a device with a browser based on Qt WebEngine 5.6 (based on Chromium
45.0.2554.101) - only one seek call from many is actually changing the playback position. Usually the first seek call after the playback starts works and the others don't. And it is easier to seek when the player is buffering. I tried to trace down the issue but so far without success.

I added traces of a playback session with two subsequent seeks, where only the first one was successful. Is it possible to tell from the traces what could be the cause?

hasplayer-log.txt

Edit 9.10.2018:
From further debugging, it is visible, that the player is not starting playback from the requested position because in onBufferUpdated method it never gets to play.call(this). It returns because audioRange is null for the requested seekTime. In network logs I can see that both audio and video segments are downloaded, but then the player continues from the position before seek call.

I tried to find the reason of this behavior, but with my limited debugging options (no breakpoints, just traces) I was not able to find anything interesting.

When I commented out the whole if (audioController) { ... } block, seek calls were performed correctly and even audio was working well. But I'm sure there's a better solution that doesn't break anything else..

Edit 11.10.2018:
When ABR is disabled by calling player.setAutoSwitchQuality(false); seeking seems working.

Edit 15.10.2018:
The issue can be resolved by setting currentTime directly on the element instead of calling player's seek method. It's still not clear though, why seek method is not working.

bbert commented

Hi, sorry for late answer.
First question: have you tried using dash.js instead of hasplayer.js. We now recommend migrating to dash.js since we have (re)integrated support of smooth streaming in dash.js.

Now, when looking closely to the logs you provided, I found the reason of the issue, between lines 1744 and 1759:

**[14:00:01.039][Stream] <video> timeupdate event: 1538134700.279** 
[14:00:01.042][BufferController][video] Working time = 1538133434.559004, Buffer level = 0.000 
[14:00:01.043][BufferController][audio] Working time = 1538133434.559004, Buffer level = 0.441 
[14:00:01.083][FragmentLoader][audio] Loaded: https://dca-livemss-perform.secure.footprint.net/1kecbu210uxtb1lq1i548xepoi/tv.ism/QualityLevels(128000)/Fragments(audio_2_en=15381334350000000) (200, 210ms, 9ms) 
[14:00:01.099][BufferController][audio] Media loaded  https://dca-livemss-perform.secure.footprint.net/1kecbu210uxtb1lq1i548xepoi/tv.ism/QualityLevels(128000)/Fragments(audio_2_en=15381334350000000) 
[14:00:01.131][BufferController][audio] Buffer segment from url  https://dca-livemss-perform.secure.footprint.net/1kecbu210uxtb1lq1i548xepoi/tv.ism/QualityLevels(128000)/Fragments(audio_2_en=15381334350000000) 
[14:00:01.146][BufferController][audio] Buffering segment 
**[14:00:01.189][Stream] <video> timeupdate event: 1538134700.4** 
[14:00:01.192][BufferController][video] Working time = 1538133434.559004, Buffer level = 0.000 
[14:00:01.193][BufferController][audio] Working time = 1538133434.559004, Buffer level = 2.361 
[14:00:01.194][BufferController][audio] PLAYING - 1538134700.4 
[14:00:01.208][FragmentLoader][video] Loaded: https://dca-livemss-perform.secure.footprint.net/1kecbu210uxtb1lq1i548xepoi/tv.ism/QualityLevels(480000)/FragmentInfo(video=15381359809200000) (200, 0ms, 576ms) 
[14:00:01.237][MssFragmentInfoController][video] FragmentInfo loaded  https://dca-livemss-perform.secure.footprint.net/1kecbu210uxtb1lq1i548xepoi/tv.ism/QualityLevels(480000)/FragmentInfo(video=15381359809200000) 
[14:00:01.244][MssFragmentController][video] Add new segment - t = 1538135982.84 
[14:00:01.253][BufferController][audio] Segment buffered 
[14:00:01.255][BufferController][audio] Remove from 1538133433.08 to 1538134670.519 (1538134700.519) 

When seeking for live streams, the hasplayer:
1- stall the video element, i.e. set playbackRate to 0
2- download segments at seeking time
3- then seek video element at seeking time once we have buffered audio and video data corresponding to seeking time

In your case with your browser, even if playbackRate is set to 0, the video element currentTime is still progressing: from 1538134700.279 to 1538134700.4.
Then, in this case for the audio buffer controller, we consider the video element is playing and this edge effects explaining the issue. The working time is no more the seeking time but the video element currentTime (which is still the time at which we were playing before seeking).

So I would say this is browser implementation issue.
But please try with dash.js, you may not encounter this issue.

Hi Bertrand,

thank you for your answer and pointing out the issue with playbackRate. I will try to use dash.js, but I think this should be fixed on the browser side together with few other issues. For now we are using the workaround with setting currentTime directly on the element.

bbert commented

Yes setting currentTime directly is the good solution.
The reason why we have implemented live seeking this way is due to potential unconformity between segment timestamp (from manifest or tfrf) and media timestamp.
We noticed sometimes some light differences. Then for example:

  • you seek at time t
  • corresponding segment start time is at t-0.02 for example
  • but media time of this segment, from MSE buffer, really starts at t+0.02
    Then seeking fails, since you do not have media data at seeking time.

But this use case is really uncommon.
So setting currentTime directly should work.