Enable video playback on more browsers and fix video loading issues

Integrates HLS.js for wider browser support and fixes video playback by using iframe.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 50814a1e-92e4-4968-856f-7bc7eedf5e8f
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/50814a1e-92e4-4968-856f-7bc7eedf5e8f/tKnLVTM
This commit is contained in:
sebastjanartic
2025-08-04 18:38:31 +00:00
parent b77e18915f
commit e087324c76
4 changed files with 113 additions and 17 deletions
+100 -11
View File
@@ -3,6 +3,7 @@ import { X } from "lucide-react";
import { type Video } from "@shared/schema";
import { Button } from "@/components/ui/button";
import { apiRequest } from "@/lib/queryClient";
import Hls from "hls.js";
interface VideoModalProps {
video: Video | null;
@@ -45,6 +46,7 @@ function formatDate(date: Date | string): string {
export default function VideoModal({ video, isOpen, onClose }: VideoModalProps) {
const videoRef = useRef<HTMLVideoElement>(null);
const hlsRef = useRef<Hls | null>(null);
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
@@ -66,6 +68,82 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
};
}, [isOpen, onClose]);
// Initialize HLS when video is available
useEffect(() => {
if (isOpen && video && videoRef.current) {
const videoElement = videoRef.current;
// Clean up previous HLS instance
if (hlsRef.current) {
hlsRef.current.destroy();
hlsRef.current = null;
}
const videoUrl = video.videoUrl;
console.log('Loading video:', videoUrl);
// Check if the video URL is HLS (.m3u8)
if (videoUrl.includes('.m3u8')) {
if (Hls.isSupported()) {
// Use HLS.js for browsers that don't support HLS natively
const hls = new Hls({
debug: true,
enableWorker: false,
lowLatencyMode: true,
backBufferLength: 90
});
hls.loadSource(videoUrl);
hls.attachMedia(videoElement);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
console.log('HLS manifest loaded successfully');
});
hls.on(Hls.Events.ERROR, (event, data) => {
console.error('HLS error:', data);
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
console.log('Network error, trying to recover...');
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.log('Media error, trying to recover...');
hls.recoverMediaError();
break;
default:
console.log('Fatal error, destroying HLS instance...');
hls.destroy();
break;
}
}
});
hlsRef.current = hls;
} else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
// For Safari that supports HLS natively
videoElement.src = videoUrl;
console.log('Using native HLS support');
} else {
console.error('HLS is not supported in this browser');
}
} else {
// For regular MP4 videos
videoElement.src = videoUrl;
console.log('Using native video support for MP4');
}
}
// Cleanup when modal closes
return () => {
if (hlsRef.current) {
hlsRef.current.destroy();
hlsRef.current = null;
}
};
}, [isOpen, video]);
const handleVideoPlay = async () => {
if (video) {
try {
@@ -102,17 +180,28 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
</Button>
<div className="relative bg-black rounded-lg overflow-hidden">
<video
ref={videoRef}
className="w-full h-auto max-h-[80vh]"
controls
preload="metadata"
onPlay={handleVideoPlay}
data-testid="video-player"
src={video.videoUrl}
>
Your browser does not support the video tag.
</video>
{video.videoUrl.includes('iframe.mediadelivery.net') ? (
<iframe
src={video.videoUrl}
className="w-full h-auto max-h-[80vh] aspect-video"
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
allowFullScreen
onLoad={handleVideoPlay}
data-testid="video-iframe"
/>
) : (
<video
ref={videoRef}
className="w-full h-auto max-h-[80vh]"
controls
preload="metadata"
onPlay={handleVideoPlay}
data-testid="video-player"
crossOrigin="anonymous"
>
Your browser does not support the video tag.
</video>
)}
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-6">
<h3