捕获传入的WebRTC视频流的方法(客户端) [英] Ways to capture incoming WebRTC video streams (client side)

查看:308
本文介绍了捕获传入的WebRTC视频流的方法(客户端)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently looking to find a best way to store a incoming webrtc video streams. I am joining the videocall using webrtc (via chrome) and I would like to record every incoming video stream to from each participant to the browser. The solutions I am researching are:

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

Modifying a browser to store recording as a file e.g. by modifying Chromium itself

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

Any screen-recorders or using solutions like xvfb & ffmpeg is not an options due the resources constrains. Is there any other way that could let me capture packets or encoded video as a file? The solution must be working on Linux.

推荐答案

如果媒体流是您想要的,则方法是覆盖浏览器的PeerConnection。这是一个示例:

if the media stream is what you want a method is to override the browser's PeerConnection. Here is an example:

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

In an extension manifest add the following content script:

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

inject.js

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环聊中通过语音通话对其进行了测试,发现其中有两个通过pc.addStream添加的mediaStreams通过pc.ontrack添加了一个曲目。 addStream似乎是本地媒体流,并且 ontrack 是一个具有streams对象的RTCTrackEvent。

I tested this with a voice call in google hangouts and saw that two mediaStreams where added via pc.addStream and one track was added via pc.ontrack. addStream would seem to be local media streams and the event object in ontrack is a RTCTrackEvent which has a streams object. which I assume are what you are looking for.

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

To access these streams from your extenion's content script you will need to create audio elements and set the "srcObject" property to the media stream: e.g.

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);

}

然后,您可以在内容脚本中收听该事件/像这样访问媒体流:

Then in your content script you can listen for that event/access the mediastream like so:

window.addEventListener("remoteStreamAdded", function(e) {
    elm = document.getElementById("remoteStream");
    var stream = elm.captureStream();
})

有了内容脚本可用的捕获流,您几乎可以使用它执行任何操作。例如,MediaRecorder非常适合记录流,或者您可以使用peer.js或binary.js之类的内容流式传输到另一个源。

With the capture stream available to your content script you can do pretty much anything you want with it. For example, MediaRecorder works really well for recording the stream(s) or you could use something like peer.js or maybe binary.js to stream to another source.

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

I haven't tested this but it should also be possible to override the local streams. For example, in the inject.js you could establish some blank mediastream, override navigator.mediaDevices.getUserMedia and instead of returning the local mediastream return your own mediastream.

此方法假设您使用扩展/应用程序在文档开始处加载inject.js脚本,它应该也可以在firefox中运行,也许在其他环境中也可以。在完成目标工作之前,必须先加载该文件。

This method should work in firefox and maybe others as well assuming you use an extenion/app to load the inject.js script at the start of the document. It being loaded before any of the target's libs is key to making this work.

编辑以获取更多详细信息

进行了更详细的编辑

这篇关于捕获传入的WebRTC视频流的方法(客户端)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆