diff --git a/facefusion/apis/static/index.html b/facefusion/apis/static/index.html
index 41f6e73d..56628493 100644
--- a/facefusion/apis/static/index.html
+++ b/facefusion/apis/static/index.html
@@ -159,6 +159,14 @@
@@ -327,7 +335,7 @@ const app = (function() {
if (fromNode) triggerDownstream(fromNode);
}
- const AUTO_EXEC_NODES = new Set(['face_detector', 'face_debugger', 'face_swapper', 'face_enhancer']);
+ const AUTO_EXEC_NODES = new Set(['face_detector', 'face_debugger', 'face_swapper', 'face_enhancer', 'face_landmarker']);
function isAutoExecNode(node) { return AUTO_EXEC_NODES.has(node.key); }
let autoExecTimers = {};
@@ -1005,8 +1013,48 @@ const app = (function() {
}
}
+ function vu(obj) { return obj.value + ' ' + obj.unit; }
+
+ function usageColor(v) { if (v < 50) return '#10b981'; if (v < 80) return '#f59e0b'; return '#ef4444'; }
+
+ function setBar(barId, labelId, value, unit) {
+ var bar = $(barId);
+ bar.style.width = Math.min(value, 100) + '%';
+ bar.style.backgroundColor = usageColor(value);
+ $(labelId).textContent = value + unit;
+ }
+
+ function updateMetrics(m) {
+ $('metricsBar').style.display = '';
+ setBar('metricCpuBar', 'metricCpuUtil', m.processor.utilization.value, '%');
+ setBar('metricMemBar', 'metricMemUtil', m.memory.utilization.value, '%');
+ if (m.graphic_devices?.length) {
+ var gpu = m.graphic_devices[0];
+ $('metricGpuContainer').style.display = '';
+ setBar('metricGpuBar', 'metricGpuUtil', gpu.utilization.gpu.value, '%');
+ $('metricVramContainer').style.display = '';
+ var vramPct = Math.round(gpu.video_memory.used.value / gpu.video_memory.total.value * 100);
+ $('metricVramBar').style.width = vramPct + '%';
+ $('metricVramBar').style.backgroundColor = usageColor(vramPct);
+ $('metricGpuVram').textContent = gpu.video_memory.used.value + '/' + gpu.video_memory.total.value + ' GB';
+ }
+ if (m.disks?.length) {
+ setBar('metricDiskBar', 'metricDiskUtil', m.disks[0].utilization.value, '%');
+ }
+ }
+
+ function connectMetricsWs() {
+ if (!accessToken) return;
+ apiCall('/metrics').then(m => { if (m) updateMetrics(m); }).catch(() => {});
+ const wsBase = API_BASE.replace(/^http/, 'ws');
+ const ws = new WebSocket(wsBase + '/metrics', [ 'access_token.' + accessToken ]);
+ ws.onmessage = e => { try { updateMetrics(JSON.parse(e.data)); } catch(err) {} };
+ ws.onclose = () => setTimeout(connectMetricsWs, 5000);
+ ws.onerror = () => ws.close();
+ }
+
lucide.createIcons();
- init();
+ init().then(connectMetricsWs);
return { addNode, addNodeByKey, addNodeAtCtx, addConnection, deleteNode, removeConnection,
resetView, fitView, toggleMenu, closeMenu, closeCtx, executeNode, saveToStorage,