diff --git a/src/app/page.js b/src/app/page.js index b66baf2..cf39a10 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -22,7 +22,10 @@ export default function Home() { const p2pManagerRef = useRef(null); const [stats, setStats] = useState({ http: 0, - p2p: 0 + p2p: 0, + uploadSpeed: 0, + downloadSpeed: 0, + peers: 0 }); // URLs de ejemplo - usando proxy del servidor @@ -135,10 +138,13 @@ export default function Home() { }, []); const handlePeerStats = useCallback((data) => { - // Actualizar estadísticas P2P - usar los deltas que envía el componente + // Actualizar estadísticas P2P completas setStats(prev => ({ ...prev, - p2p: prev.p2p + (data.downloadSpeed || 0) * 5 // velocidad * 5 segundos = bytes descargados en este intervalo + p2p: prev.p2p + (data.downloadSpeed || 0) * 5, + uploadSpeed: data.uploadSpeed || 0, + downloadSpeed: data.downloadSpeed || 0, + peers: data.peers || 0 })); }, []); @@ -267,9 +273,32 @@ export default function Home() { Streaming de video con tecnología P2P y chat en tiempo real

-
-
- WebRTC Activo +
+ {/* Estadísticas P2P */} + {peers > 0 && ( +
+
+ 👥 + {stats.peers} +
+
+ ⬆️ + + {(stats.uploadSpeed / 1024).toFixed(1)} KB/s + +
+
+ ⬇️ + + {(stats.downloadSpeed / 1024).toFixed(1)} KB/s + +
+
+ )} +
+
+ WebRTC Activo +
@@ -376,6 +405,46 @@ export default function Home() { )} + {/* Panel de Estadísticas P2P */} + {stats.peers > 0 && ( +
+

+ 📊 + Estadísticas P2P en Tiempo Real +

+
+
+

👥 Peers Conectados

+

{stats.peers}

+
+ +
+

⬆️ Subida

+

+ {(stats.uploadSpeed / 1024).toFixed(1)} +

+

KB/s

+
+ +
+

⬇️ Descarga

+

+ {(stats.downloadSpeed / 1024).toFixed(1)} +

+

KB/s

+
+ +
+

📦 Total P2P

+

+ {(stats.p2p / 1024 / 1024).toFixed(2)} +

+

MB

+
+
+
+ )} + {/* Video Player */}
{watchingUser ? ( diff --git a/src/components/P2PManager.js b/src/components/P2PManager.js index 09eb980..93e830b 100644 --- a/src/components/P2PManager.js +++ b/src/components/P2PManager.js @@ -257,11 +257,56 @@ const P2PManager = forwardRef(({ }); peer.on('connect', () => { + console.log(`✅ Peer conectado con ${targetUser}`); setPeers(prev => { const newPeers = [...prev, targetUser]; if (onPeersUpdateRef.current) onPeersUpdateRef.current(newPeers); return newPeers; }); + + // Iniciar monitoreo de estadísticas WebRTC cada 1 segundo + const statsMonitor = setInterval(async () => { + if (!peer._pc || peer.destroyed) { + clearInterval(statsMonitor); + return; + } + + try { + const stats = await peer._pc.getStats(); + let bytesReceived = 0; + let bytesSent = 0; + + stats.forEach(report => { + if (report.type === 'inbound-rtp' && report.mediaType === 'video') { + bytesReceived += report.bytesReceived || 0; + } + if (report.type === 'outbound-rtp' && report.mediaType === 'video') { + bytesSent += report.bytesSent || 0; + } + }); + + // Guardar stats anteriores para calcular delta + if (!peer._lastStats) { + peer._lastStats = { bytesReceived, bytesSent, timestamp: Date.now() }; + } else { + const deltaTime = (Date.now() - peer._lastStats.timestamp) / 1000; + const deltaReceived = bytesReceived - peer._lastStats.bytesReceived; + const deltaSent = bytesSent - peer._lastStats.bytesSent; + + if (deltaTime > 0) { + downloadBytes.current += deltaReceived; + uploadBytes.current += deltaSent; + } + + peer._lastStats = { bytesReceived, bytesSent, timestamp: Date.now() }; + } + } catch (err) { + // Ignorar errores de stats + } + }, 1000); + + // Guardar el interval en el peer para limpiarlo después + peer._statsMonitor = statsMonitor; }); peer.on('data', (data) => { @@ -277,6 +322,10 @@ const P2PManager = forwardRef(({ }); peer.on('close', () => { + console.log(`🔌 Peer cerrado con ${targetUser}`); + if (peer._statsMonitor) { + clearInterval(peer._statsMonitor); + } if (peersRef.current[targetUser] === peer) { delete peersRef.current[targetUser]; delete remoteStreamsRef.current[targetUser]; @@ -290,6 +339,9 @@ const P2PManager = forwardRef(({ peer.on('error', (err) => { console.error('❌ Error en peer', targetUser, ':', err.message || err); + if (peer._statsMonitor) { + clearInterval(peer._statsMonitor); + } if (peersRef.current[targetUser] === peer) { delete peersRef.current[targetUser]; delete remoteStreamsRef.current[targetUser];