Show video loading speed and quality indicators

Add detailed bitrate and download speed monitoring to the video player, along with visual indicators for buffering and quality levels.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 11420304-80a9-4ef2-adff-cbdaa418ffa8
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/11420304-80a9-4ef2-adff-cbdaa418ffa8/Qpg7dKb
This commit is contained in:
sebastjanartic 2025-08-07 09:22:30 +00:00
parent 3b648347cd
commit 8e8c07f34c
2 changed files with 87 additions and 12 deletions

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
import { Signal } from "lucide-react";
import { Signal, Activity, Wifi } from "lucide-react";
interface QualityIndicatorProps {
hlsInstance: any;
@ -8,8 +8,11 @@ interface QualityIndicatorProps {
export default function QualityIndicator({ hlsInstance, className = "" }: QualityIndicatorProps) {
const [currentQuality, setCurrentQuality] = useState<string>("");
const [currentBitrate, setCurrentBitrate] = useState<number>(0);
const [networkType, setNetworkType] = useState<string>("");
const [bufferHealth, setBufferHealth] = useState<"good" | "medium" | "poor">("good");
const [downloadSpeed, setDownloadSpeed] = useState<number>(0);
const [isBuffering, setIsBuffering] = useState<boolean>(false);
useEffect(() => {
if (!hlsInstance) return;
@ -18,6 +21,8 @@ export default function QualityIndicator({ hlsInstance, className = "" }: Qualit
const handleLevelSwitch = (event: any, data: any) => {
const level = hlsInstance.levels[data.level];
setCurrentQuality(`${level.height}p`);
setCurrentBitrate(Math.round(level.bitrate / 1000)); // Convert to kbps
console.log(`Preklopil na: ${level.height}p @ ${Math.round(level.bitrate/1000)}kbps`);
};
// Monitor buffer health
@ -35,8 +40,29 @@ export default function QualityIndicator({ hlsInstance, className = "" }: Qualit
}
};
// Monitor loading progress and speed
const handleFragLoaded = (event: any, data: any) => {
const stats = data.stats;
if (stats) {
const speed = (stats.total * 8) / (stats.loading.end - stats.loading.start); // bits per ms
const speedKbps = Math.round(speed); // Convert to kbps
setDownloadSpeed(speedKbps);
console.log(`Download hitrost: ${speedKbps} kbps`);
}
};
const handleWaiting = () => setIsBuffering(true);
const handlePlaying = () => setIsBuffering(false);
hlsInstance.on('hlsLevelSwitched', handleLevelSwitch);
hlsInstance.on('hlsBufferAppending', handleBufferAppending);
hlsInstance.on('hlsFragLoaded', handleFragLoaded);
const video = hlsInstance.media;
if (video) {
video.addEventListener('waiting', handleWaiting);
video.addEventListener('playing', handlePlaying);
}
// Detect network connection
const connection = (navigator as any).connection;
@ -58,6 +84,11 @@ export default function QualityIndicator({ hlsInstance, className = "" }: Qualit
if (hlsInstance) {
hlsInstance.off('hlsLevelSwitched', handleLevelSwitch);
hlsInstance.off('hlsBufferAppending', handleBufferAppending);
hlsInstance.off('hlsFragLoaded', handleFragLoaded);
}
if (video) {
video.removeEventListener('waiting', handleWaiting);
video.removeEventListener('playing', handlePlaying);
}
};
}, [hlsInstance]);
@ -74,11 +105,37 @@ export default function QualityIndicator({ hlsInstance, className = "" }: Qualit
if (!currentQuality) return null;
return (
<div className={`flex items-center gap-2 text-sm text-white bg-black/50 px-2 py-1 rounded ${className}`}>
<Signal className={`w-4 h-4 ${getSignalColor()}`} />
<span>{currentQuality}</span>
<div className={`flex flex-col gap-1 text-xs text-white bg-black/70 px-3 py-2 rounded ${className}`}>
{/* Quality and Signal */}
<div className="flex items-center gap-2">
<Signal className={`w-3 h-3 ${getSignalColor()}`} />
<span className="font-semibold">{currentQuality}</span>
{isBuffering && (
<Activity className="w-3 h-3 text-yellow-400 animate-pulse" />
)}
</div>
{/* Bitrate */}
{currentBitrate > 0 && (
<div className="flex items-center gap-1">
<span className="opacity-75">Bitrate:</span>
<span>{currentBitrate} kbps</span>
</div>
)}
{/* Download Speed */}
{downloadSpeed > 0 && (
<div className="flex items-center gap-1">
<Wifi className="w-3 h-3" />
<span>{downloadSpeed} kbps</span>
</div>
)}
{/* Network Type */}
{networkType && (
<span className="text-xs opacity-75">({networkType})</span>
<div className="opacity-75">
Omrežje: {networkType}
</div>
)}
</div>
);

View File

@ -132,25 +132,43 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
console.log('HLS manifest loaded - Available qualities:',
data.levels.map(l => `${l.height}p @ ${Math.round(l.bitrate/1000)}kbps`));
// Log bitrate analysis
console.log('BITRATE ANALIZA:');
data.levels.forEach((level, index) => {
console.log(`Nivo ${index}: ${level.width}x${level.height} @ ${Math.round(level.bitrate/1000)}kbps`);
});
// Set initial quality based on connection
const connection = (navigator as any).connection;
if (connection) {
const effectiveType = connection.effectiveType;
console.log('Network type detected:', effectiveType);
const downlink = connection.downlink; // Mbps
console.log(`Omrežje: ${effectiveType}, hitrost: ${downlink} Mbps`);
// Adjust starting level based on network
if (effectiveType === 'slow-2g' || effectiveType === '2g') {
hls.startLevel = 0; // Start with lowest quality
} else if (effectiveType === '3g') {
// More aggressive quality selection for slow connections
if (effectiveType === 'slow-2g' || effectiveType === '2g' || downlink < 1) {
hls.startLevel = 0; // Lowest quality
console.log('Nastavljam najnižjo kakovost zaradi počasne povezave');
} else if (effectiveType === '3g' || downlink < 3) {
hls.startLevel = Math.min(1, data.levels.length - 1);
console.log('Nastavljam nizko kakovost zaradi 3G povezave');
}
}
});
// Quality level monitoring
// Quality level monitoring with detailed stats
hls.on(Hls.Events.LEVEL_SWITCHED, (event, data) => {
const level = hls.levels[data.level];
console.log(`Kakovost preklopljena na: ${level.height}p @ ${Math.round(level.bitrate/1000)}kbps`);
console.log(`PREKLOPIL KAKOVOST: ${level.height}p @ ${Math.round(level.bitrate/1000)}kbps`);
console.log('Razlog preklopa: adaptivni algoritem na podlagi omrežne hitrosti');
});
// Fragment loading stats
hls.on(Hls.Events.FRAG_LOADED, (event, data) => {
const stats = data.stats;
const loadTime = stats.loading.end - stats.loading.start;
const speed = (stats.total * 8) / loadTime; // bits per ms = kbps
console.log(`Fragment naložen v ${loadTime}ms, hitrost: ${Math.round(speed)} kbps`);
});
// Buffer monitoring for dynamic adjustment