attempt to persist a single video.js instance

Continually recreating video.js instance on render is bad.
Instead, persist a single instance, and simply update the source and poster on the existing instance.
This commit is contained in:
DispatchCommit 2021-01-23 11:38:55 -08:00 committed by Sean Yesmunt
parent 912489cce0
commit 7c8383f2dc

View file

@ -325,59 +325,126 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} }
} }
// Create the video element. Note that a new videojs instantiation will happen on *every* render, so do not add props to this component! // Create the video DOM element and wrapper
function createVideoPlayerDOM(container) {
if (!container) {
console.error(`VideoPlayer Error: missing ref to container!`);
return;
}
// This seems like a poor way to generate the DOM for video.js
const wrapper = document.createElement('div');
wrapper.setAttribute('data-vjs-player', 'true');
const el = document.createElement(isAudio ? 'audio' : 'video');
el.className = 'video-js';
wrapper.appendChild(el);
container.appendChild(wrapper);
return el;
}
// Initialize video.js
function initializeVideoPlayer(el) {
if (!el) {
console.error(`Failed to initialize video player: Missing element to attach to`);
return;
}
player = videojs(el, videoJsOptions, () => {
// this seems like a weird thing to have to check for here
if (!player) {
console.error(`Failed to create videojs player!`);
return;
}
// Add various event listeners to player
player.one('play', onInitialPlay);
player.on('volumechange', onVolumeChange);
player.on('error', onError);
player.on('ended', onEnded);
// Replace volume bar with custom LBRY volume bar
LbryVolumeBarClass.replaceExisting(player);
// initialize mobile UI
player.mobileUi(); // Inits mobile version. No-op if Desktop.
// I think this is a callback function
onPlayerReady(player);
});
// Add quality selector to player
player.hlsQualitySelector({
displayCurrentQuality: true,
});
// Add reference to player to global scope
window.player = player;
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar
player.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
return player;
}
// This lifecycle hook is only called once (on mount)
useEffect(() => { useEffect(() => {
if (containerRef.current) { const vjsElement = createVideoPlayerDOM(containerRef.current);
const wrapper = document.createElement('div'); const vjsPlayer = initializeVideoPlayer(vjsElement);
wrapper.setAttribute('data-vjs-player', 'true');
const el = document.createElement(isAudio ? 'audio' : 'video');
el.className = 'video-js';
wrapper.appendChild(el);
// $FlowFixMe // Add event listener for keyboard shortcuts
containerRef.current.appendChild(wrapper); window.addEventListener('keydown', handleKeyDown);
fetch(source, { method: 'HEAD' }).then(response => { // Cleanup
if (response && response.redirected && response.url && response.url.endsWith('m3u8')) { return () => {
videoJsOptions.sources[0].type = 'application/x-mpegURL'; window.removeEventListener('keydown', handleKeyDown);
}
player = videojs(el, videoJsOptions, () => { if (player) {
if (player) { player.dispose();
player.one('play', onInitialPlay); window.player = undefined;
player.on('volumechange', onVolumeChange); }
player.on('error', onError); }
player.on('ended', onEnded); }, []);
LbryVolumeBarClass.replaceExisting(player);
player.mobileUi(); // Inits mobile version. No-op if Desktop.
onPlayerReady(player); // Update video player settings and reload it when props change
} useEffect(() => {
}); // For some reason the video player is responsible for detecting content type this way
fetch(source, { method: 'HEAD' }).then(response => {
if (!player) {
console.log(`Our player was disposed, we should disregard the fetch result.`);
return;
}
player.hlsQualitySelector({ let type = sourceType;
displayCurrentQuality: true,
});
window.player = player; // override type if we receive an .m3u8 (transcoded mp4)
if (
response &&
response.redirected &&
response.url &&
response.url.endsWith('m3u8')
) {
type = 'application/x-mpegURL';
}
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498) // Update player poster
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar // note: the poster prop seems to return null usually.
// $FlowFixMe if ( poster ) player.poster(poster);
player.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
window.addEventListener('keydown', handleKeyDown); // Update player source
player.src({
src: source,
type: type,
}); });
return () => { console.log(`Updated Player: ${source} (${type}) Poster: ${poster}`);
window.removeEventListener('keydown', handleKeyDown); });
if (player) { return () => {
player.dispose(); console.log('Guess we could clean up something here if needed');
window.player = undefined; };
}
};
}
}); });
return ( return (