Невозможно захватить позы камеры на неактивных вкладках/окнах в веб-приложениях

Вопрос или проблема

Проблема:

Я работаю над проектом, в котором использую 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, но ищу более надежный способ обеспечить плавное обнаружение поз, даже когда вкладка неактивна.

Любые советы по решению этой проблемы будут очень ценными!

Ответ или решение

К сожалению, современные браузеры имеют встроенные механизмы для экономии ресурсов, которые автоматически снижают частоту кадров видеопотока в неактивных вкладках или при сворачивании окна. Это может существенно затруднить захват и обработку видеоизображений, особенно когда речь идет о задачах анализа, требующих высокой точности, таких как распознавание лиц и поз.

Текущие Ограничения и Поведение Браузера

Как вы уже заметили, когда вкладка с веб-приложением становится неактивной, браузеры уменьшают частоту кадров видеопотока. Этот механизм предназначен для оптимизации производительности и расхода энергии, особенно на мобильных устройствах. К сожалению, это ограничивает способность вашего приложения анализировать движения или позы в реальном времени, когда вкладка неактивна.

Возможные Решения

Несмотря на фактические ограничения, есть несколько подходов, которые могут помочь смягчить проблему.

  1. Настройка МедиаПотока:
    Попробуйте установить низкое значение для свойства frameRate в параметрах получения медиа-потока:

    const stream = await navigator.mediaDevices.getUserMedia({
       video: {
           frameRate: { ideal: 30, max: 60 }
       }
    });

    Однако имейте в виду, что это может не изменить поведение браузера в неактивных вкладках.

  2. Использование Веб-Рабочих (Web Workers):
    Хотя вы уже пробовали использовать веб-работники, важно убедиться, что обработка на них выполняется достаточно эффективно. Обработчики для видео-потока все еще должны выполняться в главном потоке, однако можно перенести обработку данных и анализ в веб-работник при условии, что входные данные передаются с минимальной задержкой.

  3. Запрос на Фоновые Операции:
    Используйте requestIdleCallback для выполнения фоновых задач. Это может помочь выполнить некоторые вычисления, когда браузер освобождает ресурсы:

    requestIdleCallback(() => {
       detectFace();
    });
  4. Оптимизация Алгоритма:
    Оптимизируйте алгоритм распознавания так, чтобы он работал быстрее в реальном времени, особенно в условиях программного ограничения по производительности.

  5. Сигнализация Активности Вкладки:
    Добавьте обработчики событий для отслеживания состояния активной вкладки (visibilitychange) и адаптируйте свою логику захвата видеопотока в зависимости от этого состояния:

    document.addEventListener('visibilitychange', () => {
       if (document.visibilityState === 'visible') {
           // Перезапустите или активируйте поток
       } else {
           // Приостановите обработку
       }
    });

Заключение

К сожалению, решением проблемы автоматического снижения частоты кадров в неактивных вкладках в современных браузерах на данный момент является ограниченность функций API. Однако предложенные подходы могут помочь улучшить обработку в условиях существующих ограничений. Ключевым моментом будет постоянное применение современных практик разработки и стремление к оптимизации производительности приложения. Настоятельно рекомендуем следить за обновлениями стандарта и возможностями API, а также рассматривать возможность использования альтернативных технологий для видеозахвата и обработки.

Оцените материал
Добавить комментарий

Капча загружается...