diff --git a/frontend/src/components/FloatingVideo.jsx b/frontend/src/components/FloatingVideo.jsx
index 46c191eb..7f1e1c53 100644
--- a/frontend/src/components/FloatingVideo.jsx
+++ b/frontend/src/components/FloatingVideo.jsx
@@ -73,72 +73,109 @@ export default function FloatingVideo() {
console.log("Attempting to play stream:", streamUrl);
try {
- // If the browser supports MSE for live playback, initialize mpegts.js
- if (mpegts.getFeatureList().mseLivePlayback) {
- // Set loading flag
- setIsLoading(true);
-
- const player = mpegts.createPlayer({
- type: 'mpegts', // MPEG-TS format
- url: streamUrl,
- isLive: true,
- enableWorker: true,
- enableStashBuffer: false, // Try disabling stash buffer for live streams
- liveBufferLatencyChasing: true,
- liveSync: true,
- cors: true, // Enable CORS for cross-domain requests
- // Add error recovery options
- autoCleanupSourceBuffer: true,
- autoCleanupMaxBackwardDuration: 10,
- autoCleanupMinBackwardDuration: 5,
- reuseRedirectedURL: true,
- });
-
- player.attachMediaElement(videoRef.current);
-
- // Add events to track loading state
- player.on(mpegts.Events.LOADING_COMPLETE, () => {
- setIsLoading(false);
- });
-
- player.on(mpegts.Events.METADATA_ARRIVED, () => {
- setIsLoading(false);
- });
-
- // Add error event handler
- player.on(mpegts.Events.ERROR, (errorType, errorDetail) => {
- setIsLoading(false);
-
- // Filter out aborted errors
- if (errorType !== 'NetworkError' || !errorDetail?.includes('aborted')) {
- console.error('Player error:', errorType, errorDetail);
- setLoadError(`Error: ${errorType}${errorDetail ? ` - ${errorDetail}` : ''}`);
- }
- });
-
- player.load();
-
- // Don't auto-play until we've loaded properly
- player.on(mpegts.Events.MEDIA_INFO, () => {
- setIsLoading(false);
- try {
- player.play().catch(e => {
- console.log("Auto-play prevented:", e);
- setLoadError("Auto-play was prevented. Click play to start.");
- });
- } catch (e) {
- console.log("Error during play:", e);
- setLoadError(`Playback error: ${e.message}`);
- }
- });
-
- // Store player instance so we can clean up later
- playerRef.current = player;
+ // Check for MSE support first
+ if (!mpegts.getFeatureList().mseLivePlayback) {
+ setIsLoading(false);
+ setLoadError("Your browser doesn't support live video streaming. Please try Chrome or Edge.");
+ return;
}
+
+ // Check for basic codec support
+ const video = document.createElement('video');
+ const h264Support = video.canPlayType('video/mp4; codecs="avc1.42E01E"');
+ const aacSupport = video.canPlayType('audio/mp4; codecs="mp4a.40.2"');
+
+ console.log("Browser codec support - H264:", h264Support, "AAC:", aacSupport);
+
+ // If the browser supports MSE for live playback, initialize mpegts.js
+ setIsLoading(true);
+
+ const player = mpegts.createPlayer({
+ type: 'mpegts',
+ url: streamUrl,
+ isLive: true,
+ enableWorker: true,
+ enableStashBuffer: false,
+ liveBufferLatencyChasing: true,
+ liveSync: true,
+ cors: true,
+ autoCleanupSourceBuffer: true,
+ autoCleanupMaxBackwardDuration: 10,
+ autoCleanupMinBackwardDuration: 5,
+ reuseRedirectedURL: true,
+ });
+
+ player.attachMediaElement(videoRef.current);
+
+ // Add events to track loading state
+ player.on(mpegts.Events.LOADING_COMPLETE, () => {
+ setIsLoading(false);
+ });
+
+ player.on(mpegts.Events.METADATA_ARRIVED, () => {
+ setIsLoading(false);
+ });
+
+ // Enhanced error event handler with codec-specific messages
+ player.on(mpegts.Events.ERROR, (errorType, errorDetail) => {
+ setIsLoading(false);
+
+ // Filter out aborted errors
+ if (errorType !== 'NetworkError' || !errorDetail?.includes('aborted')) {
+ console.error('Player error:', errorType, errorDetail);
+
+ // Provide specific error messages based on error type
+ let errorMessage = `Error: ${errorType}`;
+
+ if (errorType === 'MediaError') {
+ // Try to determine if it's an audio or video codec issue
+ const errorString = errorDetail?.toLowerCase() || '';
+
+ if (errorString.includes('audio') || errorString.includes('ac3') || errorString.includes('ac-3')) {
+ errorMessage = "Audio codec not supported by your browser. Try Chrome or Edge for better audio codec support.";
+ } else if (errorString.includes('video') || errorString.includes('h264') || errorString.includes('h.264')) {
+ errorMessage = "Video codec not supported by your browser. Try Chrome or Edge for better video codec support.";
+ } else if (errorString.includes('mse')) {
+ errorMessage = "Your browser doesn't support the codecs used in this stream. Try Chrome or Edge for better compatibility.";
+ } else {
+ errorMessage = "Media codec not supported by your browser. This may be due to unsupported audio (AC3) or video codecs. Try Chrome or Edge.";
+ }
+ } else if (errorDetail) {
+ errorMessage += ` - ${errorDetail}`;
+ }
+
+ setLoadError(errorMessage);
+ }
+ });
+
+ player.load();
+
+ // Don't auto-play until we've loaded properly
+ player.on(mpegts.Events.MEDIA_INFO, () => {
+ setIsLoading(false);
+ try {
+ player.play().catch(e => {
+ console.log("Auto-play prevented:", e);
+ setLoadError("Auto-play was prevented. Click play to start.");
+ });
+ } catch (e) {
+ console.log("Error during play:", e);
+ setLoadError(`Playback error: ${e.message}`);
+ }
+ });
+
+ // Store player instance so we can clean up later
+ playerRef.current = player;
} catch (error) {
setIsLoading(false);
- setLoadError(`Initialization error: ${error.message}`);
console.error("Error initializing player:", error);
+
+ // Provide helpful error message based on the error
+ if (error.message?.includes('codec') || error.message?.includes('format')) {
+ setLoadError("Codec not supported by your browser. Please try a different browser (Chrome/Edge recommended).");
+ } else {
+ setLoadError(`Initialization error: ${error.message}`);
+ }
}
// Cleanup when component unmounts or streamUrl changes
@@ -191,7 +228,7 @@ export default function FloatingVideo() {
style={{ width: '100%', height: '180px', backgroundColor: '#000' }}
/>
- {/* Loading overlay */}
+ {/* Loading overlay - only show when loading */}
{isLoading && (
)}
-
- {/* Error message overlay */}
- {!isLoading && loadError && (
-
-
- {loadError}
-
-
- )}
+
+ {/* Error message below video - doesn't block controls */}
+ {!isLoading && loadError && (
+
+
+ {loadError}
+
+
+ )}
);