使用相机手电筒不允许更改面对模式 - Navigator.mediaDevices

Using camera flashlight not allowing to change facingmode - Navigator.mediaDevices

我正在尝试构建一个网络应用程序,它根据设备使用网络摄像头或移动相机拍照。我已经制作了一个更改 constraints.facingmode 的按钮,因此如果设备支持,用户可以使用两个摄像头(“环境”、“用户”)。问题是,当我也启用手电筒支持时,通过创建一个按钮并将其设置为手电筒切换器,如下所示:

const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
        if (SUPPORTS_MEDIA_DEVICES) {
            const track = stream.getVideoTracks()[0];
            const imageCapture = new ImageCapture(track);
            const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => {
                const btn = document.querySelector('.toggleCameraTorch');
                btn.style.visibility = 'visible';
                btn.addEventListener('click', function () {
                    try {
                        track.applyConstraints({
                            advanced: [{ torch: !wheelsfs.videoConstraint.torchState }]
                        });
                        wheelsfs.videoConstraint.torchState = !wheelsfs.videoConstraint.torchState;
                    }
                    catch(e) {
                        alert(e.message);
                    }
                });
            });
        }

在那之后,手电筒工作正常,但我无法再选择切换相机(面对模式)。当我尝试更换摄像头时,出现错误“无法启动视频源”。好像相机已经被什么东西占用了。

这就是我改变相机的方式 - 面对模式:

 wheelsfs.videoConstraint.facingMode.exact = wheelsfs.videoConstraint.facingMode.exact == "environment" ? "user" : "environment";  
    var cameraInput = wheelsfs.videoConstraint.facingMode.exact;

    wheelsfs.videoTrue.srcObject && wheelsfs.videoTrue.srcObject.getTracks().forEach(t => t.stop());

    wheelsfs.videoConstraint = {
        video: {
            width: { ideal: trueWidth },
            height: { ideal: trueHeight },
            facingMode: { ideal: "environment" }
        },
        facingMode: { exact: cameraInput }
    };

    navigator.mediaDevices.getUserMedia({ video: wheelsfs.videoConstraint }).then(function (stream) {
        wheelsfs.videoTrue.srcObject = stream;
        wheelsfs.videoTrue.play();
        const SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;
        if (SUPPORTS_MEDIA_DEVICES) {
            const track = stream.getVideoTracks()[0];
            const imageCapture = new ImageCapture(track);
            const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => {
                const btn = document.querySelector('.toggleCameraTorch');
                btn.style.visibility = 'visible';
                btn.addEventListener('click', function () {
                    try {
                        track.applyConstraints({
                            advanced: [{ torch: !wheelsfs.videoConstraint.torchState }]
                        });
                        wheelsfs.videoConstraint.torchState = !wheelsfs.videoConstraint.torchState;
                    }
                    catch (e) {
                        alert(e.message);
                    }
                });
            });
        }
    }).catch((e) => { console.log(e.message); }
                    

通过将 stream.getVideoTracks()[0] 存储到一个变量然后在更改相机(面向模式)之前对其调用 stop() 来解决它。

所以当我这样做时:

if (SUPPORTS_MEDIA_DEVICES) {
            wheelsfs.track = stream.getVideoTracks()[0];
            const imageCapture = new ImageCapture(wheelsfs.track);
            const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => {
                const btn = document.querySelector('.toggleCameraTorch');
                btn.style.visibility = 'visible';
                btn.addEventListener('click', function () {
                    try {
                        wheelsfs.track.applyConstraints({
                            advanced: [{ torch: !wheelsfs.videoConstraint.torchState }]
                        });
                        wheelsfs.videoConstraint.torchState = !wheelsfs.videoConstraint.torchState;
                    }
                    catch (e) {
                        alert(e.message);
                    }
                });
            });
        }

在第 2 行中,我将轨道保存在 public 变量中,然后当调用更改正在使用的相机的函数时,我确保我 运行 “wheelsfs.track.stop();”就在 navigator.mediaDevices.getUserMedia 电话之前。