При проигрывании HLS сегменты текущего плейлиста могут кэшироваться браузером. Это дает возможность организовать обратную перемотку на определенное время (функционал простого DVR) в HLS плеере. Рассмотрим реализацию DVR на примере VideoJS.
При создании VideoJS плеера необходимо указать следующие параметры
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;
} |
Здесь:
Глубина обратной перемотки зависит от количества сегментов в плейлисте и размера сегмента плейлиста. Эти параметры настраиваются на стороне сервера
hls_list_size=8 hls_time_min=2000 |
По умолчанию, максимальное время, на которое можно перемотать назад, составляет 16 секунд
8 * 2000 = 16000 |
Чтобы увеличить глубину обратной перемотки, необходимо увеличить размер плейлиста
hls_list_size=30 |
Размер сегмента изменять не рекомендуется, поскольку в некоторых браузерах (Safari) при других значениях поток может перестать играть.
Для того, чтобы перемотать текущий поток, используется метод Player.currentTime(). Для получения максимально возможного диапазона перемотки используется метод Player.seekable()
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);
}
} |

Чтобы вернуться к проигрыванию живого потока, используется метод Player.liveTracker.seekToLiveEdge()
const liveBtnClick = function() {
if (player != null && player.liveTracker) {
player.liveTracker.seekToLiveEdge();
...
}
} |

Для первого подписчика на HLS поток интерфейс перемотки может не включаться автоматически, поэтому рекомендуется принудительно вызвать метод Player.liveTracker.seekToLiveEdge() через определенное время после начала проигрывания
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)
}
} |