Вопрос или проблема
Проблема:
Я работаю над проектом, в котором использую MediaRecorder
и WebRTC
для захвата видеопотоков с камеры и анализа лиц, поз и контрольных точек рук с помощью решений по маркировке MediaPipe
(FaceLandmarker, PoseLandmarker и HandLandmarker). Проблема, с которой я сталкиваюсь, заключается в том, что когда вкладка или окно браузера становятся неактивными, частота кадров камеры значительно снижается, или поток приостанавливается. Это мешает мне точно захватывать движения или позы в реальном времени.
Наблюдаемое поведение:
Когда я переключаюсь на неактивную вкладку или сворачиваю браузер, браузер снижает частоту кадров видеопотока камеры до минимального уровня, что влияет на точность обнаружения поз и контрольных точек. В результате движения становятся неподвижными, и обнаружение работает неправильно, пока вкладка снова не станет активной.
Текущее решение:
Вот упрощенная версия моего решения, которая использует setTimeout и MediaRecorder
с логикой обнаружения контрольных точек:
useEffect(() => {
let faceLandmarker: FaceLandmarker;
let poseLandmarker: PoseLandmarker;
let handLandmarker: HandLandmarker;
let interval: ReturnType<typeof setTimeout>;
// Функция для обнаружения лица и контрольных точек
const detectFace = () => {
const canvas = canvasRef.current as HTMLCanvasElement;
const ctx = canvas.getContext('2d');
if (!ctx) return console.log('Не удалось найти контекст холста');
const drawingUtils = new DrawingUtils(ctx);
ctx.save();
ctx.clearRect(0, 0, 1280, 720);
if (videoRef.current && videoRef.current.readyState >= 2) {
const faceDetection = faceLandmarker.detectForVideo(videoRef.current, performance.now());
// Если обнаружены блендшейпы лица, обновите соответствующие состояния
if (
faceDetection.faceBlendshapes &&
faceDetection.faceBlendshapes.length > 0 &&
faceDetection.faceBlendshapes[0].categories
) {
blendshapes.current = faceDetection.faceBlendshapes[0].categories;
const matrix = new Matrix4().fromArray(faceDetection.facialTransformationMatrixes![0].data);
rotation.current = new Euler().setFromRotationMatrix(matrix);
riggedFace.current = Face.solve(faceDetection.faceLandmarks[0]);
}
const poseDetection = poseLandmarker.detectForVideo(videoRef.current, performance.now());
if (poseDetection) {
riggedPose.current = Pose.solve(poseDetection.worldLandmarks[0], poseDetection.landmarks[0]);
}
}
};
// Начните поток веб-камеры и инициализируйте контрольные точки
const startWebcam = async () => {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
});
videoRef.current.srcObject = stream;
videoRef.current.play();
const recorder = new MediaRecorder(stream, {});
// Инициализируйте маркеры для лица, позы и рук
[faceLandmarker, poseLandmarker, handLandmarker] = await InitLandmarkers();
// Обработайте процесс записи
recorder.ondataavailable = async (event: BlobEvent) => {
if (event.data.size > 0) {
detectFace(); // Запустите обнаружение лица, как только данные будут доступны
}
};
recorder.start(10); // Захват данных каждые 10 мс
};
// Начните поток веб-камеры при монтировании компонента
startWebcam();
return () => {
clearInterval(interval); // Очистите интервал при демонтаже
};
}, []);
Что я пробовал с WebWorkers: Я попробовал несколько решений, таких как использование WebWorkers
для выполнения обнаружения в фоновом режиме без зависимости от основного потока, но частота кадров видеопотока камеры все равно падает, когда вкладка неактивна, что делает обнаружение ненадежным.
Вопрос:
Существует ли способ обойти это поведение или заставить браузер поддерживать более высокую частоту кадров для видеопотока с камеры, даже когда вкладка неактивна? Я уже пробовал использовать setTimeout и WebWorkers, но ищу более надежный способ обеспечить плавное обнаружение поз, даже когда вкладка неактивна.
Любые советы по решению этой проблемы будут очень ценными!
Ответ или решение
К сожалению, современные браузеры имеют встроенные механизмы для экономии ресурсов, которые автоматически снижают частоту кадров видеопотока в неактивных вкладках или при сворачивании окна. Это может существенно затруднить захват и обработку видеоизображений, особенно когда речь идет о задачах анализа, требующих высокой точности, таких как распознавание лиц и поз.
Текущие Ограничения и Поведение Браузера
Как вы уже заметили, когда вкладка с веб-приложением становится неактивной, браузеры уменьшают частоту кадров видеопотока. Этот механизм предназначен для оптимизации производительности и расхода энергии, особенно на мобильных устройствах. К сожалению, это ограничивает способность вашего приложения анализировать движения или позы в реальном времени, когда вкладка неактивна.
Возможные Решения
Несмотря на фактические ограничения, есть несколько подходов, которые могут помочь смягчить проблему.
-
Настройка МедиаПотока:
Попробуйте установить низкое значение для свойстваframeRate
в параметрах получения медиа-потока:const stream = await navigator.mediaDevices.getUserMedia({ video: { frameRate: { ideal: 30, max: 60 } } });
Однако имейте в виду, что это может не изменить поведение браузера в неактивных вкладках.
-
Использование Веб-Рабочих (Web Workers):
Хотя вы уже пробовали использовать веб-работники, важно убедиться, что обработка на них выполняется достаточно эффективно. Обработчики для видео-потока все еще должны выполняться в главном потоке, однако можно перенести обработку данных и анализ в веб-работник при условии, что входные данные передаются с минимальной задержкой. -
Запрос на Фоновые Операции:
ИспользуйтеrequestIdleCallback
для выполнения фоновых задач. Это может помочь выполнить некоторые вычисления, когда браузер освобождает ресурсы:requestIdleCallback(() => { detectFace(); });
-
Оптимизация Алгоритма:
Оптимизируйте алгоритм распознавания так, чтобы он работал быстрее в реальном времени, особенно в условиях программного ограничения по производительности. -
Сигнализация Активности Вкладки:
Добавьте обработчики событий для отслеживания состояния активной вкладки (visibilitychange
) и адаптируйте свою логику захвата видеопотока в зависимости от этого состояния:document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { // Перезапустите или активируйте поток } else { // Приостановите обработку } });
Заключение
К сожалению, решением проблемы автоматического снижения частоты кадров в неактивных вкладках в современных браузерах на данный момент является ограниченность функций API. Однако предложенные подходы могут помочь улучшить обработку в условиях существующих ограничений. Ключевым моментом будет постоянное применение современных практик разработки и стремление к оптимизации производительности приложения. Настоятельно рекомендуем следить за обновлениями стандарта и возможностями API, а также рассматривать возможность использования альтернативных технологий для видеозахвата и обработки.