feat: show ffmpeg PID and CPU% per stream in dashboard
Backend samples /proc/{pid}/stat every 2s to calculate CPU usage of
each ffmpeg process and exposes ffmpeg_pid + ffmpeg_cpu_pct in stats().
Dashboard shows a cyan ffmpeg badge with live CPU% per stream row,
plus a new StatCard with total ffmpeg CPU across all active streams.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Activity, Server, Users, Wifi, Clock, X, Film, Tv, Clapperboard, RefreshCw, AlertTriangle } from 'lucide-react'
|
||||
import { Activity, Server, Users, Wifi, Clock, X, Film, Tv, Clapperboard, RefreshCw, AlertTriangle, Cpu } from 'lucide-react'
|
||||
import api from '../lib/api'
|
||||
|
||||
interface StreamClient {
|
||||
@@ -37,6 +37,9 @@ interface StreamSession {
|
||||
reconnect_count?: number
|
||||
last_data_ago?: number
|
||||
stream_info?: StreamInfo
|
||||
// ffmpeg process info (live streams only)
|
||||
ffmpeg_pid?: number | null
|
||||
ffmpeg_cpu_pct?: number
|
||||
}
|
||||
|
||||
interface SlotInfo {
|
||||
@@ -195,9 +198,10 @@ export default function Dashboard() {
|
||||
}
|
||||
}
|
||||
|
||||
const totalClients = streams.reduce((a, s) => a + s.client_count, 0)
|
||||
const busySlots = slots.filter(s => s.status === 'busy').length
|
||||
const totalBpsDown = streams.reduce((a, s) => a + (s.bps_down || 0), 0)
|
||||
const totalClients = streams.reduce((a, s) => a + s.client_count, 0)
|
||||
const busySlots = slots.filter(s => s.status === 'busy').length
|
||||
const totalBpsDown = streams.reduce((a, s) => a + (s.bps_down || 0), 0)
|
||||
const totalCpu = streams.reduce((a, s) => a + (s.ffmpeg_cpu_pct ?? 0), 0)
|
||||
const anyReconnecting = streams.some(s => s.status === 'reconnecting')
|
||||
|
||||
return (
|
||||
@@ -225,11 +229,16 @@ export default function Dashboard() {
|
||||
)}
|
||||
|
||||
{/* Stats cards */}
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4">
|
||||
<StatCard icon={<Activity size={20} className="text-blue-400" />} label="Streams activos" value={streams.length} />
|
||||
<StatCard icon={<Users size={20} className="text-green-400" />} label="Usuarios conectados" value={totalClients} />
|
||||
<StatCard icon={<Server size={20} className="text-orange-400" />} label="Slots ocupados" value={`${busySlots}/${slots.length}`} />
|
||||
<StatCard icon={<Wifi size={20} className="text-purple-400" />} label="↓ Total proveedor" value={formatBps(totalBpsDown)} />
|
||||
<StatCard
|
||||
icon={<Cpu size={20} className={totalCpu > 80 ? 'text-red-400' : totalCpu > 40 ? 'text-yellow-400' : 'text-cyan-400'} />}
|
||||
label="ffmpeg CPU total"
|
||||
value={`${totalCpu.toFixed(1)}%`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Provider slots */}
|
||||
@@ -309,6 +318,23 @@ export default function Dashboard() {
|
||||
reconnectCount={s.reconnect_count}
|
||||
lastDataAgo={s.last_data_ago}
|
||||
/>
|
||||
{s.ffmpeg_pid && (
|
||||
<div className="mt-1.5 flex items-center gap-1.5">
|
||||
<span className="inline-flex items-center gap-1 bg-cyan-900/40 text-cyan-300 text-[10px] px-1.5 py-0.5 rounded border border-cyan-800 font-mono">
|
||||
<Cpu size={9} />
|
||||
ffmpeg
|
||||
</span>
|
||||
{s.ffmpeg_cpu_pct !== undefined && (
|
||||
<span className={`font-mono text-[10px] tabular-nums ${
|
||||
s.ffmpeg_cpu_pct > 80 ? 'text-red-400' :
|
||||
s.ffmpeg_cpu_pct > 40 ? 'text-yellow-400' :
|
||||
'text-gray-400'
|
||||
}`}>
|
||||
{s.ffmpeg_cpu_pct.toFixed(1)}%
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 py-2.5">
|
||||
<div className="flex flex-col gap-1">
|
||||
|
||||
Reference in New Issue
Block a user