fbsamples / Canvas-Streaming-Example

This project contains example code showing how to go live on Facebook using a <canvas> element as a source.
Other
340 stars 73 forks source link

Video stream stops when tab is in background #3

Open mrcatman opened 5 years ago

mrcatman commented 5 years ago

I use the code to stream video to my own RTMP server (not Facebook's). When the tab where the stream comes from is in background (i.e. the other tab is active), the browser (Chrome) stops sending the video to the server (but audio, which comes from an AudioContext, keeps sending). Even if i use CaptureStream from a video element, not a one, the stream also stops. Are there any workarounds for this case? I've even disabled "Throttle expensive background timers" flag in Chrome.

bradisbell commented 5 years ago

I use the code to stream video to my own RTMP server (not Facebook's).

Please note the terms in the LICENSE file.

Even if i use CaptureStream from a video element, not a one, the stream also stops. Are there any workarounds for this case?

The only workaround I've found is to have your application popup in its own window. This is a Chromium bug, in my opinion. The browser should keep rendering elements that have a capture stream.

randallb commented 4 years ago

This is explicitly a chrome bug. It's also variable dependent on platform.

Closing.

randallb commented 4 years ago

Update... i just found a fix for this today.

https://stackoverflow.com/questions/44156528/canvas-doesnt-repaint-when-tab-inactive-backgrounded-for-recording-webgl

I might implement this in the example if someone begs / needs. :) It's pretty simple to do though.

burakguder commented 4 years ago

Please I really need this bug fixed :) I can't run canvas stream in the background

burakguder commented 4 years ago
<!doctype html>
<html>
 <head>
   <meta charset="utf-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script>

   <script>

        var fps = 50;

        function pushStream () {

           console.log("pushStream");
           const ws = new WebSocket("ws://edge1.xxxxx.com:3000");

           ws.addEventListener('open', (e) => {

//---------------------------------------  KAMERA ----------------------------- \\

var canvas_w = 1280;
var canvas_h = 720;

var canvas = document.getElementById('konfiumStudio');
var ctx = canvas.getContext('2d');
var canvasContext = canvas.getContext("2d");
var canvasStream = canvas.captureStream(30);

var webcamShare_w = 256;
var webcamShare_h = 144;

var webcamShare_x = canvas_w - webcamShare_w - 5;
var webcamShare_y = 5;

var screenShare_x = 5;
var screenShare_y = 5;

var screenShare_w = canvas_w - webcamShare_w - 8;
var screenShare_h = canvas_h - 10;

/* cihaz listesi */

webcamPlayer = null;
screenPlayer = null;

function SelectTemplate($select) {

    if ($select == 1) {
        temp1();
    }

}

function temp1() {

     screenShare_x = 0;
     screenShare_y = 0;

     screenShare_w = 1280;
     screenShare_h = 720;

}

               var video = document.querySelector("#videoElement");
                 webcamPlayer = document.createElement("video");

               if (navigator.mediaDevices.getUserMedia) {

                    webcamPlayer.muted = true;
                    webcamPlayer.poster = '';

                  navigator.mediaDevices.getUserMedia({  audio: true , video: {width: 320, height: 180, facingMode: "user"} })
                    .then(function (stream) {

                        mediaRecorder = new MediaRecorder(stream, {
                            mimeType: 'video/webm;codecs=h264',
                            audioBitsPerSecond : 128000,
                            videoBitsPerSecond : 256000
                          });
                          var stopAnim = audioTimerLoop(1000 / fps);

                           mediaRecorder.addEventListener('stop', ws.close.bind(ws));
                            mediaRecorder.addEventListener('dataavailable', (e) => {
                                 ws.send(e.data);

                         });

                              mediaRecorder.onstop = e => {
                                // we can stop our loop
                                // stopAnim();
                              }
                          mediaRecorder.start(150); // Start recording, and dump data every second

                        webcamPlayer.srcObject = stream;
                        webcamPlayer.play();
                        webcamPlayer.addEventListener('play', function() {
                            var $this = this; //cache
                            (function loop() {
                              if (!$this.paused && !$this.ended) {
                                ctx.drawImage(webcamPlayer, webcamShare_x, webcamShare_y, webcamShare_w , webcamShare_h);
                                setTimeout(loop, 1000 / 30); // drawing at 30fps
                                //addaudio();
                              }
                            })();
                          }, 0);
                    })
                    .catch(function (err0r) {
                      console.log("Bazi seyler ters gitti gibi ama arastiracagiz ... : "+err0r);
                    });

                }

             //---------------------------------------  KAMERA ----------------------------- \\        

             console.log('WebSocket Open', e);

             mediaStream = document.querySelector('canvas').captureStream(fps); // 30 FPS
             mediaRecorder = new MediaRecorder(mediaStream, {
               mimeType: 'video/webm;codecs=h264',
               audioBitsPerSecond : 128000,
               videoBitsPerSecond : 3000000
             });
             var stopAnim = audioTimerLoop(1000 / fps);

              mediaRecorder.addEventListener('stop', ws.close.bind(ws));

            mediaRecorder.addEventListener('dataavailable', (e) => {
                // ws.send(e.data);

            });

              mediaRecorder.onstop = e => {
                // we can stop our loop
                // stopAnim();
              }
             mediaRecorder.start(1000); // Start recording, and dump data every second

           });

           ws.addEventListener('close', (e) => {
             console.log('WebSocket Close', e);
             mediaRecorder.stop();
           });

        }

        function audioTimerLoop( frequency) {

          var freq = frequency / 1000;      // AudioContext time parameters are in seconds
          var aCtx = new AudioContext();
          // Chrome needs our oscillator node to be attached to the destination
          // So we create a silent Gain Node
          var silence = aCtx.createGain();
          silence.gain.value = 0;
          silence.connect(aCtx.destination);

          onOSCend();

          var stopped = false;       // A flag to know when we'll stop the loop
          function onOSCend() {
            var osc = aCtx.createOscillator();
            osc.onended = onOSCend; // so we can loop
            osc.connect(silence);
            osc.start(0); // start it now
            osc.stop(aCtx.currentTime + freq); // stop it next frame
           // callback(aCtx.currentTime); // one frame is done
            if (stopped) {  // user broke the loop
              osc.onended = function() {
                aCtx.close(); // clear the audioContext
                return;
              };
            }
          };
          // return a function to stop our loop
          return function() {
            stopped = true;
          };
        }

   </script>
 </head>
 <body>
  <canvas width="1280" height="720" style="background: #37383a;" id="konfiumStudio">  </canvas>
   <nav>
     <button onclick="pushStream()">Go Live</button>
   </nav>
 </body>
</html>

canvas is still not working efficiently in the background