mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-09 08:58:53 -05:00
fix:(video.js) support embed functionality and ensure videos play independently on the same page
This commit is contained in:
parent
2c6484b6ca
commit
222c728909
14
frontend-tools/video-js/index-embed.html
Normal file
14
frontend-tools/video-js/index-embed.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>VideoJS</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <div id="video-js-root-main"></div> -->
|
||||
<div id="video-js-root-embed" class="video-js-root-embed"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -7,14 +7,8 @@
|
||||
<title>VideoJS</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Main Video Player</h1>
|
||||
<div id="video-js-root-main"></div>
|
||||
|
||||
<hr />
|
||||
|
||||
<h1>Embed Video Player</h1>
|
||||
<div id="video-js-root-embed"></div>
|
||||
|
||||
<div id="video-js-root-main" class="video-js-root-main"></div>
|
||||
<!-- <div id="video-js-root-embed"></div> -->
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -22,6 +22,20 @@ html {
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
/* Fullscreen video styles for embedded video player */
|
||||
.video-js-root-embed .video-js video {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
object-fit: cover !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.video-js-root-embed .video-js .vjs-poster {
|
||||
border-radius: 0 !important;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.video-js div.vjs-control-bar {
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
@ -41,10 +55,32 @@ html {
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Fullscreen styles for embedded video player */
|
||||
.video-js-root-embed .video-container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
.video-js.vjs-fluid {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
/* Fullscreen fluid styles for embedded video player */
|
||||
.video-js-root-embed .video-js.vjs-fluid {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.vjs-autoplay-toggle .vjs-autoplay-icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -735,6 +771,32 @@ button {
|
||||
height: 100% !important;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* Fullscreen video-js player styles for embedded video player */
|
||||
.video-js-root-embed .video-js {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Prevent page scrolling when embed is active */
|
||||
.video-js-root-embed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 9999;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
html.video-js-root-embed-active,
|
||||
body.video-js-root-embed-active {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.video-chapter {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
|
||||
@ -1047,6 +1047,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
},
|
||||
siteUrl: '',
|
||||
nextLink: 'https://demo.mediacms.io/view?m=YjGJafibO',
|
||||
urlAutoplay: true,
|
||||
},
|
||||
[]
|
||||
);
|
||||
@ -1190,6 +1191,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
previewSprite: mediaData?.previewSprite || {},
|
||||
related_media: mediaData.data?.related_media || [],
|
||||
nextLink: mediaData?.nextLink || null,
|
||||
urlAutoplay: mediaData?.urlAutoplay || true,
|
||||
sources: getVideoSources(),
|
||||
};
|
||||
}, [mediaData]);
|
||||
@ -1419,13 +1421,13 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
|
||||
// Player dimensions - removed for responsive design
|
||||
// Autoplay behavior: Use 'muted' to comply with browser policies
|
||||
autoplay: 'play', // Set to true/false to show poster image initially (true/false, play, muted, any)
|
||||
autoplay: 'muted', // Auto-start muted to comply with browser policies (true/false, play, muted, any)
|
||||
|
||||
// Start video over when it ends
|
||||
loop: false,
|
||||
|
||||
// Start video muted
|
||||
muted: false,
|
||||
// Start video muted (check URL parameter or default)
|
||||
muted: mediaData.urlMuted || false,
|
||||
|
||||
// Poster image URL displayed before video starts
|
||||
poster: currentVideo.poster,
|
||||
@ -1691,6 +1693,54 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
// Set up auto-save for preference changes
|
||||
userPreferences.current.setupAutoSave(playerRef.current);
|
||||
|
||||
// Expose the player instance globally for timestamp functionality
|
||||
if (typeof window !== 'undefined') {
|
||||
if (!window.videojsPlayers) {
|
||||
window.videojsPlayers = {};
|
||||
}
|
||||
window.videojsPlayers[videoId] = playerRef.current;
|
||||
}
|
||||
|
||||
// Call the onPlayerInitCallback if provided via MEDIA_DATA
|
||||
if (mediaData.onPlayerInitCallback && typeof mediaData.onPlayerInitCallback === 'function') {
|
||||
mediaData.onPlayerInitCallback({ player: playerRef.current }, playerRef.current.el());
|
||||
}
|
||||
|
||||
// Handle URL timestamp parameter
|
||||
if (mediaData.urlTimestamp !== null && mediaData.urlTimestamp >= 0) {
|
||||
const timestamp = mediaData.urlTimestamp;
|
||||
|
||||
// Wait for video metadata to be loaded before seeking
|
||||
if (playerRef.current.readyState() >= 1) {
|
||||
// Metadata is already loaded, seek immediately
|
||||
if (timestamp < playerRef.current.duration()) {
|
||||
playerRef.current.currentTime(timestamp);
|
||||
} else if (timestamp >= 0) {
|
||||
playerRef.current.play();
|
||||
}
|
||||
} else {
|
||||
// Wait for metadata to load
|
||||
playerRef.current.one('loadedmetadata', () => {
|
||||
if (timestamp >= 0 && timestamp < playerRef.current.duration()) {
|
||||
playerRef.current.currentTime(timestamp);
|
||||
} else if (timestamp >= 0) {
|
||||
playerRef.current.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Handle URL autoplay parameter or auto-start on page load
|
||||
if (mediaData?.urlAutoplay) {
|
||||
playerRef.current.play();
|
||||
} else {
|
||||
// Auto-start video on page load/reload (muted to comply with browser policies)
|
||||
playerRef.current.play().catch((error) => {
|
||||
console.log('ℹ️ Browser prevented autoplay (normal behavior):', error.message);
|
||||
// Fallback: ensure video is ready to play when user interacts
|
||||
});
|
||||
}
|
||||
|
||||
const setupMobilePlayPause = () => {
|
||||
const playerEl = playerRef.current.el();
|
||||
const videoEl = playerEl.querySelector('video');
|
||||
@ -2268,14 +2318,18 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
const newTime = Math.min(currentTime + seekAmount, duration);
|
||||
|
||||
playerRef.current.currentTime(newTime);
|
||||
customComponents.current.seekIndicator.show('forward', seekAmount);
|
||||
if (customComponents.current.seekIndicator) {
|
||||
customComponents.current.seekIndicator.show('forward', seekAmount);
|
||||
}
|
||||
} else if (event.key === 'ArrowLeft' || event.keyCode === 37) {
|
||||
event.preventDefault();
|
||||
const currentTime = playerRef.current.currentTime();
|
||||
const newTime = Math.max(currentTime - seekAmount, 0);
|
||||
|
||||
playerRef.current.currentTime(newTime);
|
||||
customComponents.current.seekIndicator.show('backward', seekAmount);
|
||||
if (customComponents.current.seekIndicator) {
|
||||
customComponents.current.seekIndicator.show('backward', seekAmount);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -2482,7 +2536,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
playerRef.current.on('play', () => {
|
||||
console.log('Video started playing');
|
||||
// Only show play indicator if not changing quality
|
||||
if (!playerRef.current.isChangingQuality) {
|
||||
if (!playerRef.current.isChangingQuality && customComponents.current.seekIndicator) {
|
||||
customComponents.current.seekIndicator.show('play');
|
||||
}
|
||||
});
|
||||
@ -2490,7 +2544,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
|
||||
playerRef.current.on('pause', () => {
|
||||
console.log('Video paused');
|
||||
// Only show pause indicator if not changing quality
|
||||
if (!playerRef.current.isChangingQuality) {
|
||||
if (!playerRef.current.isChangingQuality && customComponents.current.seekIndicator) {
|
||||
customComponents.current.seekIndicator.show('pause');
|
||||
}
|
||||
});
|
||||
|
||||
@ -9,29 +9,50 @@ import VideoJS from './VideoJS.jsx';
|
||||
const mountComponents = () => {
|
||||
// Mount main video player
|
||||
const rootContainerMain = document.getElementById('video-js-root-main');
|
||||
if (rootContainerMain) {
|
||||
if (rootContainerMain && !rootContainerMain.hasChildNodes()) {
|
||||
const rootMain = createRoot(rootContainerMain);
|
||||
rootMain.render(
|
||||
<StrictMode>
|
||||
<VideoJS videoId="video-main" />
|
||||
</StrictMode>
|
||||
);
|
||||
console.log('Mounted main VideoJS player');
|
||||
}
|
||||
|
||||
// Mount embed video player
|
||||
const rootContainerEmbed = document.getElementById('video-js-root-embed');
|
||||
if (rootContainerEmbed) {
|
||||
if (rootContainerEmbed && !rootContainerEmbed.hasChildNodes()) {
|
||||
const rootEmbed = createRoot(rootContainerEmbed);
|
||||
rootEmbed.render(
|
||||
<StrictMode>
|
||||
<VideoJS videoId="video-embed" />
|
||||
</StrictMode>
|
||||
);
|
||||
console.log('Mounted embed VideoJS player');
|
||||
}
|
||||
};
|
||||
|
||||
// Expose the mounting function globally for manual triggering
|
||||
window.triggerVideoJSMount = mountComponents;
|
||||
|
||||
// Listen for custom events to trigger mounting
|
||||
document.addEventListener('triggerVideoJSMount', () => {
|
||||
console.log('Received triggerVideoJSMount event, attempting to mount VideoJS components...');
|
||||
mountComponents();
|
||||
});
|
||||
|
||||
// Initial mount
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', mountComponents);
|
||||
} else {
|
||||
mountComponents();
|
||||
}
|
||||
|
||||
// Also periodically check for new containers (as a fallback)
|
||||
setInterval(() => {
|
||||
const embedContainer = document.getElementById('video-js-root-embed');
|
||||
if (embedContainer && !embedContainer.hasChildNodes()) {
|
||||
console.log('Found unmounted embed container during periodic check, mounting...');
|
||||
mountComponents();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user