vlibras-player-webjs
Version:
Biblioteca JavaScript moderna para integração do VLibras Player com React, Vue, Angular e vanilla JS
175 lines • 6.61 kB
JavaScript
import { useState, useEffect, useCallback, useRef } from 'react';
import { safeNavigator } from '../ssr/useIsomorphicLayoutEffect';
import { useVLibras } from './useVLibras';
/**
* Hook para monitoramento de performance do VLibras
*/
export function useVLibrasPerformance(options = {}) {
const { enableAnalytics = false, collectMetrics = true, sampleRate = 1.0 } = options;
const { player, isLoaded } = useVLibras();
const [metrics, setMetrics] = useState(null);
const [isCollecting, setIsCollecting] = useState(false);
const metricsRef = useRef({
translationTimes: [],
loadStartTime: 0,
memoryMeasurements: [],
errors: 0,
translations: 0,
totalCharacters: 0,
cacheHits: 0,
cacheMisses: 0
});
const startCollection = useCallback(() => {
if (!collectMetrics || Math.random() > sampleRate)
return;
setIsCollecting(true);
metricsRef.current.loadStartTime = performance.now();
// Reset counters
metricsRef.current = {
...metricsRef.current,
translationTimes: [],
memoryMeasurements: [],
errors: 0,
translations: 0,
totalCharacters: 0,
cacheHits: 0,
cacheMisses: 0
};
}, [collectMetrics, sampleRate]);
const stopCollection = useCallback(() => {
setIsCollecting(false);
// Calcular métricas finais
const data = metricsRef.current;
const now = performance.now();
const newMetrics = {
translationTime: data.translationTimes.length > 0
? data.translationTimes.reduce((a, b) => a + b, 0) / data.translationTimes.length
: 0,
loadTime: now - data.loadStartTime,
memoryUsage: data.memoryMeasurements.length > 0
? Math.max(...data.memoryMeasurements)
: 0,
fps: estimateFPS(),
cacheHitRate: (data.cacheHits + data.cacheMisses) > 0
? data.cacheHits / (data.cacheHits + data.cacheMisses)
: 0,
errorRate: data.translations > 0 ? data.errors / data.translations : 0,
totalTranslations: data.translations,
averageTranslationLength: data.translations > 0 ? data.totalCharacters / data.translations : 0
};
setMetrics(newMetrics);
}, []);
const resetMetrics = useCallback(() => {
setMetrics(null);
metricsRef.current = {
translationTimes: [],
loadStartTime: 0,
memoryMeasurements: [],
errors: 0,
translations: 0,
totalCharacters: 0,
cacheHits: 0,
cacheMisses: 0
};
}, []);
const getReport = useCallback(() => {
if (!metrics)
return 'Nenhuma métrica coletada';
return `
🔊 VLibras Performance Report
============================
🕐 Tempo médio de tradução: ${metrics.translationTime.toFixed(2)}ms
⚡ Tempo de carregamento: ${metrics.loadTime.toFixed(2)}ms
🧠 Uso de memória: ${(metrics.memoryUsage / (1024 * 1024)).toFixed(2)}MB
🎮 FPS médio: ${metrics.fps.toFixed(1)}
💾 Taxa de acerto cache: ${(metrics.cacheHitRate * 100).toFixed(1)}%
❌ Taxa de erro: ${(metrics.errorRate * 100).toFixed(2)}%
📊 Total de traduções: ${metrics.totalTranslations}
📝 Tamanho médio do texto: ${metrics.averageTranslationLength.toFixed(1)} caracteres
`.trim();
}, [metrics]);
const exportMetrics = useCallback(() => {
return {
timestamp: new Date().toISOString(),
metrics,
meta: {
userAgent: safeNavigator?.userAgent || 'unknown',
language: safeNavigator?.language || 'unknown',
enableAnalytics,
collectMetrics,
sampleRate
}
};
}, [metrics, enableAnalytics, collectMetrics, sampleRate]);
// Monitorar eventos do player
useEffect(() => {
if (!player || !isCollecting)
return;
const handleTranslationStart = (text) => {
metricsRef.current.translations++;
metricsRef.current.totalCharacters += text.length;
};
const handleTranslationComplete = () => {
// Medir tempo de tradução (simplificado)
const time = performance.now() - (metricsRef.current.loadStartTime || performance.now());
metricsRef.current.translationTimes.push(time);
};
const handleError = () => {
metricsRef.current.errors++;
};
// Monitorar memória periodicamente
const memoryInterval = setInterval(() => {
if (performance.memory) {
metricsRef.current.memoryMeasurements.push(performance.memory.usedJSHeapSize);
}
}, 5000);
// Se o player tiver event emitter, usar
if (player.eventEmitter) {
player.eventEmitter.on('translation:start', handleTranslationStart);
player.eventEmitter.on('translation:complete', handleTranslationComplete);
player.eventEmitter.on('error', handleError);
}
return () => {
clearInterval(memoryInterval);
if (player.eventEmitter) {
player.eventEmitter.off('translation:start', handleTranslationStart);
player.eventEmitter.off('translation:complete', handleTranslationComplete);
player.eventEmitter.off('error', handleError);
}
};
}, [player, isCollecting]);
// Auto-start collection quando player carrega
useEffect(() => {
if (isLoaded && enableAnalytics && !isCollecting) {
startCollection();
}
}, [isLoaded, enableAnalytics, isCollecting, startCollection]);
return {
metrics,
isCollecting,
startCollection,
stopCollection,
resetMetrics,
getReport,
exportMetrics
};
}
// Função auxiliar para estimar FPS
function estimateFPS() {
let frames = 0;
let lastTime = performance.now();
const countFrame = () => {
frames++;
const currentTime = performance.now();
if (currentTime - lastTime >= 1000) {
const fps = frames;
frames = 0;
lastTime = currentTime;
return fps;
}
return 60; // Default assumption
};
// Simplified FPS estimation
return countFrame();
}
//# sourceMappingURL=useVLibrasPerformance.js.map