Compare commits

...

7 Commits

Author SHA1 Message Date
Yiannis Christodoulou
ca0dc29488 build assets 2025-10-17 15:52:30 +03:00
Yiannis Christodoulou
a4f0c742a0 Improve VideoJS control bar layout and responsiveness
Added CSS rules to prevent control bar button overflow, prioritize essential controls, and hide less important buttons on smaller screens. Also removed legacy VideoJS static assets no longer in use.
2025-10-17 15:52:23 +03:00
Yiannis Christodoulou
6f3ed46413 Add audio sample and update video sample assets
Moved sample-media-file.json to src/assets, updated subtitle info with a new URL, and added a new sample-media-file.mp3.json for audio testing. These changes support improved handling and testing of both video and audio media in the VideoJSPlayer component.
2025-10-17 15:46:46 +03:00
Yiannis Christodoulou
178b5ed37c audio poster 2025-10-17 14:13:12 +03:00
Yiannis Christodoulou
2a12fec89e Keep poster visible for audio embeds and update track handling
Ensures the poster image remains visible during playback for audio files in embed players by updating both JavaScript logic and CSS. Also updates subtitle track handling to set the default track and adjusts Video.js player configuration for better control over native and emulated tracks.
2025-10-17 14:05:38 +03:00
Yiannis Christodoulou
55c701e055 fix: Adjust subtitle position when controls are visible 2025-10-17 11:31:39 +03:00
Yiannis Christodoulou
40d13e8bd0 Update Greek subtitles timing in sample VTT file
Adjusted the timing of subtitle cues in sample-subtitles-greek.vtt to better align with the video content.
2025-10-17 11:29:45 +03:00
11 changed files with 1349 additions and 95 deletions

View File

@ -3,14 +3,14 @@ WEBVTT
NOTE
Αυτό είναι ένα δείγμα υποτίτλων στα ελληνικά για το βίντεο των ωκεανών
00:00:00.000 --> 00:00:01.000
00:00:00.000 --> 00:00:05.000
Καλώς ήρθατε στον όμορφο κόσμο των ωκεανών
00:00:01.000 --> 00:00:02.000
00:00:05.000 --> 00:00:09.000
Αυτές οι τεράστιες υδάτινες εκτάσεις καλύπτουν το μεγαλύτερο μέρος του πλανήτη μας
00:00:02.000 --> 00:00:04.000
00:00:09.000 --> 00:00:15.000
Η θαλάσσια ζωή ανθίζει σε αυτά τα βαθιά γαλάζια νερά
00:00:05.000 --> 00:00:07.000
00:00:15.000 --> 00:00:20.000
Από το μικροσκοπικό πλαγκτόν μέχρι τις τεράστιες φάλαινες

View File

Before

Width:  |  Height:  |  Size: 695 KiB

After

Width:  |  Height:  |  Size: 695 KiB

View File

@ -110,9 +110,9 @@
"480_playlist": "/media/hls/d393b72d279d4d0da70a484eb6b8b44f/media-6/stream.m3u8"
},
"license": null,
"subtitles_info": [
"__subtitles_info": [
{
"src": "/media/original/subtitles/user/markos/7e5aaed284954ae497d09783bf81004f.ExitofElygiaGorgeChaniaCrete.vtt",
"src": "https://videojs.mediacms.io/media/original/subtitles/user/markos/7e5aaed284954ae497d09783bf81004f.ExitofElygiaGorgeChaniaCrete.vtt",
"srclang": "en",
"label": "English"
}

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,17 @@ button {
visibility: hidden !important;
}
/* Adjust subtitle position when controls are visible */
/* When controls are VISIBLE (user is active), add extra bottom margin */
.video-js:not(.vjs-user-inactive) .vjs-text-track-display {
margin-bottom: 2em; /* Adjust this value to move subtitles higher when controls are visible */
}
/* When controls are HIDDEN (user is inactive), use default positioning */
.video-js.vjs-user-inactive .vjs-text-track-display {
margin-bottom: 0.5em; /* Smaller margin when controls are hidden */
}
/* Center the fullscreen button inside its wrapper */
/* @media (hover: hover) and (pointer: fine) {
.vjs-fullscreen-control svg {
@ -39,3 +50,59 @@ button {
}
}
*/
/* Prevent control bar buttons from overflowing */
.video-js .vjs-control-bar {
overflow: visible !important;
display: flex !important;
flex-wrap: nowrap !important;
}
/* Ensure control bar stays within bounds - only allow non-essential buttons to shrink */
.video-js .vjs-control-bar .vjs-settings-button,
.video-js .vjs-control-bar .vjs-chapters-button,
.video-js .vjs-control-bar .vjs-subtitles-button,
.video-js .vjs-control-bar .vjs-captions-button,
.video-js .vjs-control-bar .vjs-subs-caps-button,
.video-js .vjs-control-bar .vjs-autoplay-toggle,
.video-js .vjs-control-bar .vjs-next-video-button {
flex-shrink: 1 !important;
min-width: 0 !important;
}
/* Priority controls that should never shrink - maintain their size and spacing */
.video-js .vjs-control-bar .vjs-play-control,
.video-js .vjs-control-bar .vjs-volume-panel,
.video-js .vjs-control-bar .vjs-fullscreen-control,
.video-js .vjs-control-bar .vjs-picture-in-picture-toggle,
.video-js .vjs-control-bar .custom-remaining-time {
flex-shrink: 0 !important;
}
/* Hide less important buttons on smaller screens */
@media (max-width: 768px) {
.video-js .vjs-control-bar .vjs-picture-in-picture-toggle {
display: none !important;
}
}
@media (max-width: 600px) {
.video-js .vjs-control-bar .vjs-autoplay-toggle {
display: none !important;
}
}
@media (max-width: 500px) {
.video-js .vjs-control-bar .vjs-next-video-button {
display: none !important;
}
}
@media (max-width: 400px) {
/* Hide subtitles/captions button on very small screens - already available in settings */
.video-js .vjs-control-bar .vjs-subtitles-button,
.video-js .vjs-control-bar .vjs-captions-button,
.video-js .vjs-control-bar .vjs-subs-caps-button {
display: none !important;
}
}

View File

@ -29,10 +29,10 @@ import KeyboardHandler from '../../utils/KeyboardHandler';
import PlaybackEventHandler from '../../utils/PlaybackEventHandler';
// Import sample media data
import sampleMediaData from '../../../public/sample-media-file.json';
import sampleMediaData from '../../assets/sample-media-file.json';
// Import fallback poster image
import audioPosterImg from '../../../public/audio-poster.jpg';
import audioPosterImg from '../../assets/audio-poster.jpg';
// Function to enable tooltips for all standard VideoJS buttons
const enableStandardButtonTooltips = (player) => {
@ -1849,7 +1849,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
src: '/sample-subtitles.vtt',
srclang: 'en',
label: 'English Subtitles',
default: false,
default: true,
},
{
kind: 'subtitles',
@ -1870,7 +1870,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
src: track.src,
srclang: track.srclang,
label: track.label,
default: false,
default: track.default || false,
}))
: [];
@ -2150,16 +2150,17 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
nativeControlsForTouch: PlayerConfig.nativeControlsForTouch,
// Use native audio tracks instead of emulated - disabled for consistency
nativeAudioTracks: true,
nativeAudioTracks: false,
// Use native text tracks instead of emulated - disabled for consistency
nativeTextTracks: true,
// Use Video.js text tracks for full positioning control on mobile
// Native tracks don't allow CSS positioning control
nativeTextTracks: isTouchDevice,
// Use native video tracks instead of emulated - disabled for consistency
nativeVideoTracks: true,
nativeVideoTracks: false,
// Preload text tracks
preloadTextTracks: true,
preloadTextTracks: false,
// Play inline
playsinline: true,
@ -2189,9 +2190,28 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
userPreferences.current.setupAutoSave(playerRef.current);
// Add class for audio files to enable audio-specific styling
console.log('mediaData.media_type', mediaData.data?.media_type);
if (mediaData.data?.media_type === 'audio') {
playerRef.current.addClass('vjs-audio-type');
// For embed players, ensure poster stays visible during playback
if (isEmbedPlayer) {
const ensurePosterVisible = () => {
const posterEl = playerRef.current.el().querySelector('.vjs-poster');
if (posterEl) {
posterEl.style.display = 'block';
posterEl.style.opacity = '1';
posterEl.style.visibility = 'visible';
}
};
// Keep poster visible on all play events
playerRef.current.on('play', ensurePosterVisible);
playerRef.current.on('playing', ensurePosterVisible);
playerRef.current.on('timeupdate', ensurePosterVisible);
// Initial call
setTimeout(ensurePosterVisible, 200);
}
}
// Enable tooltips for all standard VideoJS buttons
@ -3939,7 +3959,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
</p>
{/* Add subtitle tracks */}
{/* {subtitleTracks &&
{subtitleTracks &&
subtitleTracks.map((track, index) => (
<track
key={index}
@ -3950,7 +3970,7 @@ function VideoJSPlayer({ videoId = 'default-video' }) {
default={track.default}
/>
))}
{/*
<track kind="chapters" src="/sample-chapters.vtt" /> */}
{/* Add chapters track */}
{/* {chaptersData &&

View File

@ -18,6 +18,16 @@
background-color: #000 !important;
}
/* Keep poster visible even when playing for audio files */
#page-embed .video-js-root-embed .video-js.vjs-audio-type .vjs-poster,
#page-embed .video-js-root-embed .video-js.vjs-audio-poster-mode .vjs-poster,
#page-embed .video-js-root-embed .video-js.vjs-has-started.vjs-audio-type .vjs-poster,
#page-embed .video-js-root-embed .video-js.vjs-playing.vjs-audio-type .vjs-poster {
display: block !important;
opacity: 1 !important;
visibility: visible !important;
}
/* Fullscreen video element - maintain aspect ratio */
#page-embed .video-js-root-embed .video-js video {
position: absolute !important;

View File

@ -14,7 +14,6 @@ export default defineConfig({
},
},
root: path.resolve(__dirname, 'src'),
publicDir: path.resolve(__dirname, 'public'),
define: {
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'production'),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long