Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when passing a DOM element to RecordRTC #279

Open
chrisnyc opened this issue Jun 9, 2017 · 3 comments
Open

Exception when passing a DOM element to RecordRTC #279

chrisnyc opened this issue Jun 9, 2017 · 3 comments

Comments

@chrisnyc
Copy link

chrisnyc commented Jun 9, 2017

Hi, Muaz, first off, thanks so much for all your work on RecordRTC, it's awesome!

I'm trying to use the method described here: https://www.webrtc-experiment.com/RecordRTC/Canvas-Recording/webpage-recording.html to record a section of a web page by passing in a DOM element. , but I'm getting the exception: "RecordRTC.js:2899 Please pass either HTMLCanvasElement or CanvasRenderingContext2D."

My ultimate goal is to record 2 canvases on top of each other, one is a 3d canvas and the other is a 2d canvas on top (hud). Getting RecordRTC recording a canvas by passing a DIV seems like a good first step. I think you've said recording 2 canvases on top of each other isn't supported yet, but I think this is a pretty common setup for games so I'm pursuing this anyway. I was able to capture them side-by-side using an array of Media Streams, but I really need to record it the way it appears on the page, with the HUD being mostly transparent on top of the 3d canvas.

My recorder (javascript) looks like this:

function createRecorder(){
    var elementToRec = document.getElementById("div3d");
        recorder = RecordRTC(elementToRec, {
        type: "canvas",
        showMousePointer: true
    });
}

My html looks like this:

<div id='divCanvases' class='style2d'>
    <div id='div3d' class='style3d'>
        <canvas id='canvas3d' class='style3d'></canvas>
    </div>
    <div id='div2d' class='style2d'>
        <canvas id='canvas2d' class='style2d'></canvas>
        <video id='s_video' class='styleVid' type='video/webm' ></video>
    </div>
</div>

And the CSS styles are:

.style3d {
    display: block;
    position: fixed;
    overflow: hidden;
    will-change: transform;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    border: 0;
    padding: 0;
    margin: 0;
    z-index: 0;
}
.style2d {
    display: block;
    position: fixed;
    overflow: hidden;
    will-change: transform;
    text-align: center;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    border: 0;
    padding: 0;
    margin: 0;
    z-index: 1;
}
.styleVid {
    margin: 0 auto;
    display: none;
    width: 50%;
    height: 50%;
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    object-fit: fill;
    z-index: 2;
}

By the way, I found this package that might enable RecordRTC to merge 2 video MediaStreams. https://github.com/RationalCoding/video-stream-merger

You can see my game here: http://www.pocketoys.com/ if you're interested in it at all. I haven't released the version with RecordRTC yet.

Thanks so much for any assistance.

Update I just released the version with RecordRTC to the web. You can see it in action if you select "Play Offline". The online game is pretty network intensive, and I'm wary of trying to capture the video at the same time, hopefully I can enable that later.

I tried again to get video-stream-merger working but it's throwing an error. I'll raise it to the owner. This is what I'm trying. I set fps to 1 just to go easy on it....

function createRecorderMerge(){
    var stream1 = get3dCanvas().captureStream();
    var stream2 = getHudCanvas().captureStream();

    var merger = new VideoStreamMerger({width:window.innerWidth, height:window.innerHeight,fps:1});

    merger.addStream(stream1,{x:0,y:0,width:window.innerWidth, height:window.innerHeight, mute:true});
    merger.addStream(stream2,{x:0,y:0,width:window.innerWidth, height:window.innerHeight, mute:true});

    merger.start();

    recorder3d = RecordRTC(merger.result, {
        recorderType: MediaStreamRecorder,
        type: "canvas",
        showMousePointer: true
    });
}```
Below is the output from the console:

spheres.js:4476 Recording video. Click STOP to stop.
15:50:22.854 RecordRTC.js:53 started recording canvas stream.
15:50:22.855 RecordRTC.js:963 Using recorderType: MediaStreamRecorder
15:50:22.856 RecordRTC.js:1894 Passing following config over MediaRecorder API. Object {type: "canvas", showMousePointer: true, mimeType: "video/webm", recorderType: function, initCallback: function…}checkForInactiveTracks: trueinitCallback: nullmimeType: "video/webm"recorderType: function MediaStreamRecorder(mediaStream, config)arguments: (...)caller: (...)length: 2name: "MediaStreamRecorder"prototype: Objectconstructor: function MediaStreamRecorder(mediaStream, config)arguments: (...)caller: (...)length: 2name: "MediaStreamRecorder"prototype: Objectconstructor: function MediaStreamRecorder(mediaStream, config)__proto__: Object__proto__: function ()[[FunctionLocation]]: RecordRTC.js:1847[[Scopes]]: Scopes[2]__proto__: Object__proto__: function ()apply: function apply()arguments: (...)bind: function bind()call: function call()caller: (...)constructor: function Function()length: 0name: ""toString: function toString()Symbol(Symbol.hasInstance): function [Symbol.hasInstance]()get arguments: function ThrowTypeError()set arguments: function ThrowTypeError()get caller: function ThrowTypeError()set caller: function ThrowTypeError()__proto__: Object[[FunctionLocation]]: <unknown>[[FunctionLocation]]: RecordRTC.js:1847[[Scopes]]: Scopes[2]showMousePointer: truetype: "canvas"__proto__: Object
15:50:22.859 RecordRTC.js:662 Recorder state changed: recording
15:50:22.859 RecordRTC.js:93 Initialized recorderType: MediaStreamRecorder for output-type: canvas
15:50:26.072 spheres.js:4476 Stopped recording. Click PLAY to view.
15:50:26.073 RecordRTC.js:119 Stopped recording canvas stream.
stopRecording @ RecordRTC.js:119
toggleVideoRecording @ spheres.js:5190
handleHudPauseBackSelection @ spheres.js:1908
15:50:26.073 RecordRTC.js:662 Recorder state changed: stopped
15:50:26.074 RecordRTC.js:662 Recorder state changed: inactive
15:50:26.075 RecordRTC.js:161 **video/webm -> 0 Bytes**
15:50:26.102 2871acc0-7b97-4554-ab2d-a56bc87eb54a:1 **GET blob:http://desktop.may.com/2871acc0-7b97-4554-ab2d-a56bc87eb54a 416 (Requested Range Not Satisfiable)**
@chrisnyc
Copy link
Author

Hi, perhaps the best approach here would be to take down the examples that no longer seem to work. They give the impression that RecordRTC has functionality which it does not (the ability to record an arbitrary DOM element).

@muaz-khan
Copy link
Owner

muaz-khan commented Jul 20, 2017

We already have this module: dev/MultiStreamRecorder.js (purpose of this script is simply merge multiple videos and multiple audios scripts into single MediaStream)

Here is the relevant documentation: https://github.com/muaz-khan/RecordRTC#record-multiple-videos

However MultiStreamRecorder requires following flag on windows:

chrome://flags/#enable-experimental-web-platform-features

Here are demo using MultiStreamRecorder:

  1. simple-demos/video-plus-screen-recording.html
  2. simple-demos/show-logo-on-recorded-video.html
  3. simple-demos/multi-cameras-recording.html

The first demo i.e. "Screen+Video recording" looks like this:

multistreamrecorder

You can use html2canvas.js to pass your DIV containing any number of nested canvas and you'll get single resulting Canvas object.

Here is a similar demo: Canvas-Recording/webpage-recording.html

Here is how it works:

var elementToShare = document.getElementById('elementToShare');

var canvas2d = document.createElement('canvas'); // OUR OWN invisible CANVAS
var context = canvas2d.getContext('2d');
canvas2d.width = elementToShare.clientWidth;
canvas2d.height = elementToShare.clientHeight;
canvas2d.style = 'display: none;';
(document.body || document.documentElement).appendChild(canvas2d);

// looper+selfinvoker method
(function looper() {
    if (recorder && recorder.getBlob() && recorder.getBlob().size) {
        // this line checks whether recorder is stopped
        return;
    }

    // looper keeps calling this method until recording stops
    html2canvas(elementToShare, {
        grabMouse: true,
        onrendered: function(canvas) {
            context.clearRect(0, 0, canvas2d.width, canvas2d.height);

            // draw html2canvas resulting canvas on our own canvas
            context.drawImage(canvas, 0, 0, canvas2d.width, canvas2d.height);

            // here is how looper works
            setTimeout(looper, 1);
        }
    });
})();

// note: captureStream requires a flag: chrome://flags/#enable-experimental-web-platform-features
var canvasStream = canvas2d.captureStream(); // capture from our own canvas

// following three properties are required to make sure
// our canvas is rendered correctly by the MultiStreamRecorder
// these properties ae merely for positioning for our streams
canvasStream.fullcanvas = true;
canvasStream.width = canvas2d.width;
canvasStream.height = canvas2d.height;

// to append camera on bottom-right corner
// i.e. how camer should be positioned
camera.width = 320;
camera.height = 240;
camera.top = canvasStream.height - camera.height;
camera.left: canvasStream.width - camera.width;

// now you can use MultiStreamRecorder here
// we are gonig to pass array of streams
var recorder = RecordRTC([microphone, camera, canvasStream], {
    type: 'video'
});

recorder.startRecording();

@truetopwebghost
Copy link

I tried to test https://github.com/muaz-khan/RecordRTC/blob/master/simple-demos/video-plus-screen-recording.html, but it doesn't work.
Is there any example to verify element capturing?
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants