mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-05 23:18:53 -05:00
Add audio poster support for audio files in video players
Introduces an audio-poster.jpg image and updates both chapters and video editor React video player components to display a poster image for audio files when no poster is provided. Also adds a posterUrl field to MEDIA_DATA and ensures fallback logic for poster images is consistent across iOS and standard video players.
This commit is contained in:
parent
bfcb774183
commit
54e2f1d7e4
BIN
frontend-tools/chapters-editor/client/public/audio-poster.jpg
Normal file
BIN
frontend-tools/chapters-editor/client/public/audio-poster.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 695 KiB |
@ -11,6 +11,7 @@ interface IOSVideoPlayerProps {
|
||||
const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps) => {
|
||||
const [videoUrl, setVideoUrl] = useState<string>('');
|
||||
const [iosVideoRef, setIosVideoRef] = useState<HTMLVideoElement | null>(null);
|
||||
const [posterImage, setPosterImage] = useState<string | undefined>(undefined);
|
||||
|
||||
// Refs for hold-to-continue functionality
|
||||
const incrementIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
@ -26,15 +27,24 @@ const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps
|
||||
|
||||
// Get the video source URL from the main player
|
||||
useEffect(() => {
|
||||
let url = '';
|
||||
if (videoRef.current && videoRef.current.querySelector('source')) {
|
||||
const source = videoRef.current.querySelector('source') as HTMLSourceElement;
|
||||
if (source && source.src) {
|
||||
setVideoUrl(source.src);
|
||||
url = source.src;
|
||||
}
|
||||
} else {
|
||||
// Fallback to sample video if needed
|
||||
setVideoUrl('/videos/sample-video.mp4');
|
||||
url = '/videos/sample-video.mp4';
|
||||
}
|
||||
setVideoUrl(url);
|
||||
|
||||
// Check if the media is an audio file and set poster image
|
||||
const isAudioFile = url.match(/\.(mp3|wav|ogg|m4a|aac|flac)$/i) !== null;
|
||||
|
||||
// Get posterUrl from MEDIA_DATA, or use audio-poster.jpg as fallback for audio files when posterUrl is empty
|
||||
const mediaPosterUrl = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.posterUrl) || '';
|
||||
setPosterImage(mediaPosterUrl || (isAudioFile ? '/audio-poster.jpg' : undefined));
|
||||
}, [videoRef]);
|
||||
|
||||
// Function to jump 15 seconds backward
|
||||
@ -127,6 +137,7 @@ const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps
|
||||
x-webkit-airplay="allow"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
poster={posterImage}
|
||||
>
|
||||
<source src={videoUrl} type="video/mp4" />
|
||||
<p>Your browser doesn't support HTML5 video.</p>
|
||||
|
||||
@ -38,6 +38,13 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
const sampleVideoUrl =
|
||||
(typeof window !== 'undefined' && (window as any).MEDIA_DATA?.videoUrl) || '/videos/sample-video.mp4';
|
||||
|
||||
// Check if the media is an audio file
|
||||
const isAudioFile = sampleVideoUrl.match(/\.(mp3|wav|ogg|m4a|aac|flac)$/i) !== null;
|
||||
|
||||
// Get posterUrl from MEDIA_DATA, or use audio-poster.jpg as fallback for audio files when posterUrl is empty
|
||||
const mediaPosterUrl = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.posterUrl) || '';
|
||||
const posterImage = mediaPosterUrl || (isAudioFile ? '/audio-poster.jpg' : undefined);
|
||||
|
||||
// Detect iOS device and Safari browser
|
||||
useEffect(() => {
|
||||
const checkIOS = () => {
|
||||
@ -354,6 +361,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
x-webkit-airplay="allow"
|
||||
controls={false}
|
||||
muted={isMuted}
|
||||
poster={posterImage}
|
||||
>
|
||||
<source src={sampleVideoUrl} type="video/mp4" />
|
||||
{/* Safari fallback for audio files */}
|
||||
|
||||
@ -6,6 +6,7 @@ if (typeof window !== 'undefined') {
|
||||
window.MEDIA_DATA = {
|
||||
videoUrl: '',
|
||||
mediaId: '',
|
||||
posterUrl: ''
|
||||
};
|
||||
window.lastSeekedPosition = 0;
|
||||
}
|
||||
@ -15,6 +16,7 @@ declare global {
|
||||
MEDIA_DATA: {
|
||||
videoUrl: string;
|
||||
mediaId: string;
|
||||
posterUrl?: string;
|
||||
};
|
||||
seekToFunction?: (time: number) => void;
|
||||
lastSeekedPosition: number;
|
||||
|
||||
BIN
frontend-tools/video-editor/client/public/audio-poster.jpg
Normal file
BIN
frontend-tools/video-editor/client/public/audio-poster.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 695 KiB |
@ -11,6 +11,7 @@ interface IOSVideoPlayerProps {
|
||||
const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps) => {
|
||||
const [videoUrl, setVideoUrl] = useState<string>('');
|
||||
const [iosVideoRef, setIosVideoRef] = useState<HTMLVideoElement | null>(null);
|
||||
const [posterImage, setPosterImage] = useState<string | undefined>(undefined);
|
||||
|
||||
// Refs for hold-to-continue functionality
|
||||
const incrementIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
@ -26,15 +27,24 @@ const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps
|
||||
|
||||
// Get the video source URL from the main player
|
||||
useEffect(() => {
|
||||
let url = '';
|
||||
if (videoRef.current && videoRef.current.querySelector('source')) {
|
||||
const source = videoRef.current.querySelector('source') as HTMLSourceElement;
|
||||
if (source && source.src) {
|
||||
setVideoUrl(source.src);
|
||||
url = source.src;
|
||||
}
|
||||
} else {
|
||||
// Fallback to sample video if needed
|
||||
setVideoUrl('/videos/sample-video.mp4');
|
||||
url = '/videos/sample-video.mp3';
|
||||
}
|
||||
setVideoUrl(url);
|
||||
|
||||
// Check if the media is an audio file and set poster image
|
||||
const isAudioFile = url.match(/\.(mp3|wav|ogg|m4a|aac|flac)$/i) !== null;
|
||||
|
||||
// Get posterUrl from MEDIA_DATA, or use audio-poster.jpg as fallback for audio files when posterUrl is empty
|
||||
const mediaPosterUrl = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.posterUrl) || '';
|
||||
setPosterImage(mediaPosterUrl || (isAudioFile ? '/audio-poster.jpg' : undefined));
|
||||
}, [videoRef]);
|
||||
|
||||
// Function to jump 15 seconds backward
|
||||
@ -127,6 +137,7 @@ const IOSVideoPlayer = ({ videoRef, currentTime, duration }: IOSVideoPlayerProps
|
||||
x-webkit-airplay="allow"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
poster={posterImage}
|
||||
>
|
||||
<source src={videoUrl} type="video/mp4" />
|
||||
<p>Your browser doesn't support HTML5 video.</p>
|
||||
|
||||
@ -36,7 +36,14 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
const [tooltipTime, setTooltipTime] = useState(0);
|
||||
|
||||
const sampleVideoUrl =
|
||||
(typeof window !== 'undefined' && (window as any).MEDIA_DATA?.videoUrl) || '/videos/sample-video.mp4';
|
||||
(typeof window !== 'undefined' && (window as any).MEDIA_DATA?.videoUrl) || '/videos/sample-video.mp3';
|
||||
|
||||
// Check if the media is an audio file
|
||||
const isAudioFile = sampleVideoUrl.match(/\.(mp3|wav|ogg|m4a|aac|flac)$/i) !== null;
|
||||
|
||||
// Get posterUrl from MEDIA_DATA, or use audio-poster.jpg as fallback for audio files when posterUrl is empty
|
||||
const mediaPosterUrl = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.posterUrl) || '';
|
||||
const posterImage = mediaPosterUrl || (isAudioFile ? '/audio-poster.jpg' : undefined);
|
||||
|
||||
// Detect iOS device
|
||||
useEffect(() => {
|
||||
@ -344,6 +351,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({
|
||||
x-webkit-airplay="allow"
|
||||
controls={false}
|
||||
muted={isMuted}
|
||||
poster={posterImage}
|
||||
>
|
||||
<source src={sampleVideoUrl} type="video/mp4" />
|
||||
<p>Your browser doesn't support HTML5 video.</p>
|
||||
|
||||
BIN
static/chapters_editor/audio-poster.jpg
Normal file
BIN
static/chapters_editor/audio-poster.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 695 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
static/video_editor/audio-poster.jpg
Normal file
BIN
static/video_editor/audio-poster.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 695 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user