A current playlist segments are cached by a browser while playing HLS. This allows to rewind a stream back (a simple DVR function) in HLS player. Let's consider the DVR implementation based on VideoJS.
The following parameters should be set when creating a VideoJS player instance
const LIVE_THRESHOLD = 5; const LIVE_TOLERANCE = 5; ... const initVideoJsPlayer = function(video) { let videoJsPlayer = videojs(video, { ... liveui: true, liveTracker: { trackingThreshold: LIVE_THRESHOLD, liveTolerance: LIVE_TOLERANCE }, ... }); ... return videoJsPlayer; }
Where:
- liveui: true - enables rewind interface
- liveTracker.trackingThreshold - sets a minimal time in seconds to play before displaying rewind interface
- liveTracker.liveTolenrace - sets how far from the seekable end should be considered live playback, in seconds
A maximum time to rewind back depends on a segments count in playlist and on a segment size. The parameters are set at server side
hls_list_size=8 hls_time_min=2000
By default, the maximum time to rewind is 16 seconds
8 * 2000 = 16000
Playlist size should be increased to rewind a more time back
hls_list_size=30
Segment size should not be changed because some browsers (Safari) may stop playing HLS segments of other size.
Use Player.currentTime() method to rewind a currently playing stream. Get the maximum time range to rewind using Player.seekable() method
const backBtnClick = function(event) { if (player != null && player.liveTracker) { ... let seekable = player.seekable(); let backTime = -1; if (event.target.id.indexOf("10") !== -1) { backTime = player.currentTime() - 10; } else if (event.target.id.indexOf("30") !== -1) { backTime = player.currentTime() - 30; } if (backTime < 0) { backTime = seekable ? seekable.start(0) : player.currentTime(); } player.currentTime(backTime); } }
Use Player.liveTracker.seekToLiveEdge() to return back to live playback
const liveBtnClick = function() { if (player != null && player.liveTracker) { player.liveTracker.seekToLiveEdge(); ... } }
Rewind interface may not be enabled for the first HLS subscriber, in this case the Player.liveTracker.seekToLiveEdge() method should be called explicitly after some time since playback starts
const liveUIDisplay = function() { stopLiveUITimer() if (player && player.liveTracker) { liveUITimer = setInterval(function() { if (!player.liveTracker.isLive() && player.liveTracker.liveWindow() > LIVE_THRESHOLD) { // Live UI is not displayed yet, seek to live edge to display player.liveTracker.seekToLiveEdge(); } }, LIVE_UI_INTERVAL) } }