Google chrome 捕获传入WebRTC视频流的方法(客户端)

Google chrome 捕获传入WebRTC视频流的方法(客户端),google-chrome,webrtc,chromium,openwebrtc,Google Chrome,Webrtc,Chromium,Openwebrtc,我目前正在寻找一种存储传入webrtc视频流的最佳方法。我正在使用webrtc(通过chrome)加入videocall,我想记录每个参与者到浏览器的每个传入视频流。 我正在研究的解决方案有: 拦截进入浏览器的网络数据包,例如使用Whireshark,然后解码。在本条之后: 修改浏览器以将录制存储为文件,例如通过修改Chromium本身 由于资源限制,任何屏幕录像机或使用xvfb&ffmpeg等解决方案都不是一种选择。有没有其他方法可以让我捕获数据包或编码视频作为文件?解决方案必须在Linu

我目前正在寻找一种存储传入webrtc视频流的最佳方法。我正在使用webrtc(通过chrome)加入videocall,我想记录每个参与者到浏览器的每个传入视频流。 我正在研究的解决方案有:

  • 拦截进入浏览器的网络数据包,例如使用Whireshark,然后解码。在本条之后:

  • 修改浏览器以将录制存储为文件,例如通过修改Chromium本身


由于资源限制,任何屏幕录像机或使用xvfb&ffmpeg等解决方案都不是一种选择。有没有其他方法可以让我捕获数据包或编码视频作为文件?解决方案必须在Linux上运行

捕获数据包只会为您提供网络数据包,然后您需要将这些数据包转换为帧并放入容器中。一个服务器,例如可以录制视频


运行headless chrome和使用javascript MediaRecorder API是另一种选择,但资源负担更重。

如果媒体流是您想要的,一种方法是覆盖浏览器的对等连接。以下是一个例子:

在扩展清单中添加以下内容脚本:

content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["payload/inject.js"],
      "all_frames": true,
      "match_about_blank": true,
      "run_at": "document_start"
    }
]
inject.js

var inject = '('+function() { 
    //overide the browser's default RTCPeerConnection. 
    var origPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
    //make sure it is supported
    if (origPeerConnection) {

        //our own RTCPeerConnection
        var newPeerConnection = function(config, constraints) {
            console.log('PeerConnection created with config', config);
            //proxy the orginal peer connection
            var pc = new origPeerConnection(config, constraints);
            //store the old addStream
            var oldAddStream = pc.addStream;

            //addStream is called when a local stream is added. 
            //arguments[0] is a local media stream
            pc.addStream = function() {
                console.log("our add stream called!")
                //our mediaStream object
                console.dir(arguments[0])
                return oldAddStream.apply(this, arguments);
            }

            //ontrack is called when a remote track is added.
            //the media stream(s) are located in event.streams
            pc.ontrack = function(event) {
                console.log("ontrack got a track")
                console.dir(event);
            }

            window.ourPC = pc;

            return pc; 
        };

    ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection'].forEach(function(obj) {
        // Override objects if they exist in the window object
        if (window.hasOwnProperty(obj)) {
            window[obj] = newPeerConnection;
            // Copy the static methods
            Object.keys(origPeerConnection).forEach(function(x){
                window[obj][x] = origPeerConnection[x];
            })
            window[obj].prototype = origPeerConnection.prototype;
        }
    });
  }

}+')();';
var script = document.createElement('script');
script.textContent = inject;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
我在google hangouts用语音通话测试了这一点,发现两个mediaStreams通过pc.addStream添加,一个曲目通过pc.ontrack添加。addStream似乎是本地媒体流,中的事件对象是具有streams对象的RTCTrackEvent。我想这就是你要找的

要从扩展的内容脚本访问这些流,您需要创建音频元素并将“srcObject”属性设置为媒体流:例如

pc.ontrack = function(event) {

    //check if our element exists
    var elm = document.getElementById("remoteStream");
    if(elm == null) {
        //create an audio element
        elm = document.createElement("audio");
        elm.id = "remoteStream";

    }

    //set the srcObject to our stream. not sure if you need to clone it
    elm.srcObject = event.streams[0].clone();
    //write the elment to the body
    document.body.appendChild(elm);

    //fire a custom event so our content script knows the stream is available.
    // you could pass the id in the "detail" object. for example:
    //CustomEvent("remoteStreamAdded", {"detail":{"id":"audio_element_id"}})
    //then access if via e.detail.id in your event listener.
    var e = CustomEvent("remoteStreamAdded");
    window.dispatchEvent(e);

}
然后在内容脚本中,您可以监听该事件/访问mediastream,如下所示:

window.addEventListener("remoteStreamAdded", function(e) {
    elm = document.getElementById("remoteStream");
    var stream = elm.captureStream();
})
有了内容脚本可用的捕获流,您几乎可以用它做任何事情。例如,MediaRecorder非常适合记录流,或者您可以使用peer.js或binary.js之类的东西将流传输到另一个源

我还没有对此进行测试,但也应该可以覆盖本地流。例如,在inject.js中,您可以建立一些空白的mediastream,覆盖navigator.mediaDevices.getUserMedia,而不是返回本地mediastream,返回您自己的mediastream

假设您在文档开始时使用extension/app加载inject.js脚本,那么这种方法应该可以在firefox和其他浏览器中使用。在任何目标的lib之前加载它是实现这一功能的关键

编辑以获取更多详细信息


编辑以获取更多详细信息

据我所知,Janus的工作需要控制webrtc服务器。我想以参与者的身份录制一个外部视频通话,而不需要对服务器进行任何控制。是否有一种方法可以通过某种方式将我的本地流量从我的浏览器实例代理给Janus?如果您有一个浏览器实例,请使用MediaRecorder API,有关示例,请参阅。您需要使用Chromes tabcapture来捕获选项卡,并为本地和远程参与者添加音频。这个答案仍然相关吗?我已经在GoogleMeet中尝试了你的inject.js方法,但是newPeerConnection函数没有被调用