1

我正在与 peerjs 创建视频聊天。

我正在使用以下功能切换相机(开/关):

function toggleCamera() {
    localStream.getVideoTracks()[0].enabled = !(localStream.getVideoTracks()[0].enabled);
}

调用此函数后,视频变黑,接收器只是黑屏(按预期工作)。现在我想检测黑屏/空白屏幕,以便向用户显示一些消息或图标,表明相机已禁用且没有流。

我该如何检测呢?

4

2 回答 2

1

常见的方法是发送信令消息(通过正常路径或数据通道)。轮询 getStats 以检测黑帧是一种有效的方法,但计算成本更高。

于 2020-07-30T11:18:53.980 回答
0

一段时间后,我设法得到了解决方案:

var previousBytes = 0;
var previousTS = 0;
var currentBytes = 0;
var currentTS = 0;

// peer - new Peer()
// stream - local camera stream (received from navigator.mediaDevices.getUserMedia(constraints))
let connection = peer.call(peerID, stream);

// peerConnection - reference to RTCPeerConnection (https://peerjs.com/docs.html#dataconnection-peerconnection)
connection.peerConnection.getStats(null).then(stats => {
    stats.forEach(report => {
        if (report.type === "inbound-rtp") {

            currentBytes = report.bytesReceived;
            currentTS = report.timestamp;

            if (previousBytes == 0) {
                previousBytes = currentBytes;
                previousTS = currentTS;
                return;
            }

            console.log({ previousBytes })
            console.log({ currentBytes })

            var deltaBytes = currentBytes - previousBytes;
            var deltaTS = currentTS - previousTS;

            console.log("Delta: " + (deltaBytes / deltaTS) + " kB/s")
            previousBytes = currentBytes;
            previousTS = currentTS;

        }
    });
});

这段代码实际上是在每秒被调用的函数中。当相机打开且未被覆盖时,deltaBytes 在 100 到 250 之间,当相机关闭(以编程方式)或覆盖(用餐巾纸或其他东西)时,相机流为黑色/空白,deltaBytes 为 1.5-3kbps。重新打开相机后,deltaBytes 会出现峰值,达到 500kbps 左右。

这是简短的控制台日志:

    124.52747252747253 kB/s
    202.213 kB/s
    194.64764764764766 kB/s
    15.313 kB/s (this is where camera is covered)
    11.823823823823824 kB/s
    11.862137862137862 kB/s
    2.164 kB/s
    2.005 kB/s
    2.078078078078078 kB/s
    1.99 kB/s
    2.059 kB/s
    1.992992992992993 kB/s
    159.89810189810188 kB/s (uncovered camera)
    502.669 kB/s
    314.7927927927928 kB/s
    255.0909090909091 kB/s
    220.042 kB/s
    213.46353646353646 kB/s

编辑:所以最后我按照@Philipp Hancke 说的做了。我创建了从页面加载到用户关闭它的主连接。通过这个连接,我正在发送用于启动视频通话、取消视频会话、打开/关闭摄像头的命令……然后在另一端,我正在解析这些命令并执行功能。

function sendMutedMicCommand() { masterConnection.send(`${commands.MutedMic}`); }
function sendUnmutedMicCommand() { masterConnection.send(`${commands.UnmutedMic}`); }
function sendPromptVideoCallCommand() { masterConnection.send(`${commands.PromptVideoCall}`); }
function sendAcceptVideoCallCommand() { masterConnection.send(`${commands.AcceptVideoCall}`); }
function sendDeclineVideoCallCommand() { masterConnection.send(`${commands.DeclineVideoCall}`); }

Function which handles data:
function handleData(data) {
    let actionType = data;
    switch (actionType) {
        case commands.MutedMic: ShowMuteIconOnReceivingVideo(true); break;
        case commands.UnmutedMic: ShowMuteIconOnReceivingVideo(false); break;
        case commands.PromptVideoCall: showVideoCallModal(); break;
        case commands.AcceptVideoCall: startVideoConference(); break;
        case commands.DeclineVideoCall: showDeclinedCallAlert(); break;
        default: break;
    }
}


const commands = {
    MutedMic: "mutedMic",
    UnmutedMic: "unmutedMic",
    PromptVideoCall: "promptVideoCall",
    AcceptVideoCall: "acceptVideoCall",
    DeclineVideoCall: "declineVideoCall",
}

然后当我收到 mutedMic 命令时,我会显示带有交叉麦克风的图标。当我收到 AcceptVideoCall 命令时,我会创建另一个对等点,即具有随机 ID 的 videoCallPeer,然后将其发送到另一端。另一方然后创建另一个具有随机 ID 的对等点,并使用接收到的 ID 启动视频会话。

于 2020-07-30T08:54:00.880 回答