Skip to content

Commit a55fbd5

Browse files
committed
perf(player): pre-fetch HLS manifest via IntersectionObserver
1 parent 38924fe commit a55fbd5

1 file changed

Lines changed: 51 additions & 35 deletions

File tree

static/playHLSVideo.js

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,51 @@
4343
}
4444
}
4545

46-
function initializeHls() {
47-
newVideo.removeEventListener('play', initializeHls);
48-
var hls = new Hls({ autoStartLoad: false });
46+
function addQualitySelector(videoElement, hlsInstance, availableLevels) {
47+
var qualitySelector = document.createElement('select');
48+
qualitySelector.classList.add('quality-selector');
49+
var defaultIndex = getIndexOfDefault(availableLevels.length);
50+
availableLevels.forEach(function (level, index) {
51+
var option = document.createElement('option');
52+
option.value = index.toString();
53+
var bitrate = (level.bitrate / 1_000).toFixed(0);
54+
option.text = level.height + 'p (' + bitrate + ' kbps)';
55+
if (index === defaultIndex) {
56+
option.selected = "selected";
57+
}
58+
qualitySelector.appendChild(option);
59+
});
60+
qualitySelector.selectedIndex = defaultIndex;
61+
qualitySelector.addEventListener('change', function () {
62+
var selectedIndex = qualitySelector.selectedIndex;
63+
hlsInstance.nextLevel = selectedIndex;
64+
hlsInstance.startLoad();
65+
});
66+
67+
videoElement.parentNode.appendChild(qualitySelector);
68+
}
69+
70+
// hide manifest latency from play
71+
var observer = new IntersectionObserver(function (entries) {
72+
if (!entries[0].isIntersecting) return;
73+
observer.disconnect();
74+
75+
var hls = new Hls({ autoStartLoad: false }); // manifest only; segments deferred until startLoad()
4976
hls.loadSource(playlist);
5077
hls.attachMedia(newVideo);
51-
hls.on(Hls.Events.MANIFEST_PARSED, function () {
78+
79+
var manifestParsed = false;
80+
hls.once(Hls.Events.MANIFEST_PARSED, function () {
5281
hls.loadLevel = getIndexOfDefault(hls.levels.length);
53-
var availableLevels = hls.levels.map(function(level) {
82+
var availableLevels = hls.levels.map(function (level) {
5483
return {
5584
height: level.height,
5685
width: level.width,
5786
bitrate: level.bitrate,
5887
};
5988
});
60-
6189
addQualitySelector(newVideo, hls, availableLevels);
62-
63-
hls.startLoad();
64-
newVideo.play();
90+
manifestParsed = true;
6591
});
6692

6793
hls.on(Hls.Events.ERROR, function (event, data) {
@@ -83,37 +109,27 @@
83109

84110
console.error("HLS error", data);
85111
});
86-
}
87112

88-
function addQualitySelector(videoElement, hlsInstance, availableLevels) {
89-
var qualitySelector = document.createElement('select');
90-
qualitySelector.classList.add('quality-selector');
91-
var defaultIndex = getIndexOfDefault(availableLevels.length);
92-
availableLevels.forEach(function (level, index) {
93-
var option = document.createElement('option');
94-
option.value = index.toString();
95-
var bitrate = (level.bitrate / 1_000).toFixed(0);
96-
option.text = level.height + 'p (' + bitrate + ' kbps)';
97-
if (index === defaultIndex) {
98-
option.selected = "selected";
113+
function whenReady(fn) {
114+
if (manifestParsed) {
115+
fn();
116+
} else {
117+
hls.once(Hls.Events.MANIFEST_PARSED, fn);
99118
}
100-
qualitySelector.appendChild(option);
101-
});
102-
qualitySelector.selectedIndex = defaultIndex;
103-
qualitySelector.addEventListener('change', function () {
104-
var selectedIndex = qualitySelector.selectedIndex;
105-
hlsInstance.nextLevel = selectedIndex;
106-
hlsInstance.startLoad();
107-
});
119+
}
108120

109-
videoElement.parentNode.appendChild(qualitySelector);
110-
}
121+
function startPlayback() {
122+
whenReady(function () { hls.startLoad(); newVideo.play(); });
123+
}
111124

112-
newVideo.addEventListener('play', initializeHls);
125+
if (autoplay) {
126+
startPlayback();
127+
} else {
128+
newVideo.addEventListener('play', startPlayback, { once: true });
129+
}
130+
}, { rootMargin: '200px' });
113131

114-
if (autoplay) {
115-
newVideo.play();
116-
}
132+
observer.observe(newVideo);
117133
});
118134
} else {
119135
var videos = document.querySelectorAll("video.hls_autoplay");

0 commit comments

Comments
 (0)