Javascript 在网络应用程序中同时录制屏幕和预览摄像头在Chrome/macOS设置中效果不佳

Javascript 在网络应用程序中同时录制屏幕和预览摄像头在Chrome/macOS设置中效果不佳,javascript,html,getusermedia,web-mediarecorder,get-display-media,Javascript,Html,Getusermedia,Web Mediarecorder,Get Display Media,目标是在html视频元素中预览计算机的网络摄像头流,同时录制音频和显示另一个视频的Chrome选项卡,并使用MediaRecorder API、navigator.mediaDevices.getDisplayMedia和navigator.mediaDevice.getUserMedia预览 该实现在使用Chrome和Ubuntu/Windows设置时运行良好,但在macOS上运行时会变得滞后。下面提供了Javascript代码。有没有关于为什么在macOS上实现效果不好的想法 我尝试将编解码

目标是在html视频元素中预览计算机的网络摄像头流,同时录制音频和显示另一个视频的Chrome选项卡,并使用MediaRecorder API、navigator.mediaDevices.getDisplayMedia和navigator.mediaDevice.getUserMedia预览

该实现在使用Chrome和Ubuntu/Windows设置时运行良好,但在macOS上运行时会变得滞后。下面提供了Javascript代码。有没有关于为什么在macOS上实现效果不好的想法

我尝试将编解码器从vp9改为vp8,将帧率降低到24,分辨率已经降低。如果我再低一点,质量就会变差

我曾尝试在macOS上降低流和录制的质量,但没有任何性能提升

    export default function VideoRecord(props) {
    const [isLoading, setIsLoading] = useState(true);
​
    useEffect(() => {
        async function onLoad() {
            try {
                //some code
            } catch (e) {
                alert(e);
            }
        setIsLoading(false);
    }
​
    onLoad();
    }, [props.match.params.id]);
​
    var mediaRecorder;
    var recordedChunks = [];
    var videoStream;
    var cameraStream;
    var combinedStream;
    var BLOB;
    var cameraElem;
    var videoElem;
​
    $(function() {
        cameraElem = document.querySelector('#camera');
        videoElem = document.querySelector('#video');
    })
​
    var videoMediaOptions = {
        video: {
            width: 720,
            height: 480,
            aspectRatio: 1920/1080,
            cursor: "never",
            frameRate: 30
        },
        audio: false
    };
​
    var cameraMediaOptions = {
        video: {
            width: 300,
            height: 300
        },
        audio: true
    }
​
    async function startCapture() {
        try {
            videoStream = await navigator.mediaDevices.getDisplayMedia(videoMediaOptions);
            cameraStream = await navigator.mediaDevices.getUserMedia(cameraMediaOptions);
            cameraElem.srcObject = cameraStream;
            startRec();
​
        } catch(err) {
            console.error("Error: " + err);
        }
    }
​
    function handleDataAvailable(event) {
        if (event.data.size > 0) {
            recordedChunks.push(event.data);
            createBlob();
        }
    }
​
    function startRec () {
        var options = { mimeType: "video/webm; codecs=vp9" };
        combinedStream = new MediaStream([...cameraStream.getAudioTracks(), ...videoStream.getTracks()]);
        mediaRecorder = new MediaRecorder(combinedStream, options);
        mediaRecorder.ondataavailable = handleDataAvailable;
        mediaRecorder.start();
    }
​
    function createBlob() {
        BLOB = new Blob(recordedChunks, {
            type: "video/webm"
        });
​
        var url = URL.createObjectURL(BLOB);
​
        videoElem.srcObject = null;
        videoElem.src = url;
        videoElem.muted = false;
    }
​
    function stopCapture() {
        let cameraTracks = cameraStream.getTracks();
        cameraTracks.forEach(cameraTracks => cameraTracks.stop());
​
        let tracks = videoStream.getTracks();
        tracks.forEach(track => track.stop());
        mediaRecorder.stop();
    }
​
    function renderPage(){
        return (
            <div className="videoWrapper">
                <video preload="auto" id="video"></video>
                <video id="camera" autoPlay muted></video>
                <Button id="startBtn" onClick={startCapture}>Start</Button>
                <Button id="stopBtn" onClick={stopCapture}>Stop</Button>
            </div>
        )
    }
​
    return (
        <div id="videoRecordID" className="VideoRecord">
            {!isLoading && <div>Loading...</div>}
            {!isLoading && renderPage()}
        </div>
    );
}
导出默认功能录像(道具){
const[isLoading,setIsLoading]=useState(true);
​
useffect(()=>{
异步函数onLoad(){
试一试{
//一些代码
}捕获(e){
警报(e);
}
设置加载(假);
}
​
onLoad();
},[props.match.params.id]);
​
媒体记录器;
var recordedChunks=[];
视频流;
cameraStream变种;
var组合流;
var-BLOB;
卡默雷姆变种;
var videoElem;
​
$(函数(){
cameraElem=document.querySelector(“#camera”);
videoElem=document.querySelector(“#video”);
})
​
var videoMediaOptions={
视频:{
宽度:720,
身高:480,
方面:1920/1080,
光标:“从不”,
帧率:30
},
音频:错误
};
​
var摄像机选项={
视频:{
宽度:300,
身高:300
},
音频:正确
}
​
异步函数startCapture(){
试一试{
videoStream=Wait navigator.mediaDevices.getDisplayMedia(videoMediaOptions);
cameraStream=await navigator.mediaDevices.getUserMedia(CameramedOptions);
cameraElem.srcObject=cameraStream;
startRec();
​
}捕捉(错误){
控制台错误(“错误:+err”);
}
}
​
函数HandleData可用(事件){
如果(event.data.size>0){
recordedChunks.push(事件数据);
createBlob();
}
}
​
函数startRec(){
var options={mimeType:“视频/webm;编解码器=vp9”};
combinedStream=新媒体流([…cameraStream.getAudioTracks(),…videoStream.getTracks());
mediaRecorder=新的mediaRecorder(组合流,选项);
mediaRecorder.ondataavailable=handleDataAvailable;
mediaRecorder.start();
}
​
函数createBlob(){
BLOB=新BLOB(记录的块{
类型:“视频/webm”
});
​
var url=url.createObjectURL(BLOB);
​
videoElem.srcObject=null;
videoElem.src=url;
videoElem.muted=false;
}
​
函数stopCapture(){
让cameraTracks=cameraStream.getTracks();
forEach(cameraTracks=>cameraTracks.stop());
​
let tracks=videoStream.getTracks();
tracks.forEach(track=>track.stop());
mediaRecorder.stop();
}
​
函数renderPage(){
返回(
开始
停止
)
}
​
返回(
{!isLoading&&Loading…}
{!isLoading&&renderPage()}
);
}

MacOS的网络摄像头和屏幕捕获功能与Win或Linux相比有点复杂。尝试降低getDisplayMedia()的帧速率和/或分辨率。尝试使用getUserMedia()仅捕获音频,请记住,使用getDisplayMedia()执行纯屏幕抓取操作。它必须从屏幕捕获原始图像数据,并通过编码器运行(您的情况下为vp9)。并且,尝试使用vp8代替vp9。我已经尝试降低帧速率和分辨率,但如果分辨率降低,视频质量将对我的使用情况不利。您知道getDisplayMedia()是否还有其他选择吗?我需要在拍摄摄像机和音频的同时拍摄屏幕。