MDN example: MediaStream Recording API - Recording a media element

User avatar
axew3
w3all User
w3all User
Posts: 2689
Joined: Fri Jan 22, 2016 5:15 pm
Location: Italy
Contact:

MDN example: MediaStream Recording API - Recording a media element

Post by axew3 »

The example of recorder at mdn network
MediaStream_Recording_API/Recording_a_media_element
that is using promises to grab/record video streams and that stop/close the video/audio instance on browser when you click on Stop recording button: but if you let elapse the counter time, without clicking on the Stop button the audio/video still will result open on browser (may you wish all stopped when wait function will finish, without user click requirement): to better explain, you'll see that the example will not close the audio/video and will remain opened, like still recording (and the hardware result still engaged/occupied by the browser instance) if you not click on stop button when recording time is elapsed.
This the answer using Creating and triggering events that i've apply:

Code: Select all

<!DOCTYPE html>
<html>
    <head>
          
        <style type="text/css">
            body {
  font: 14px "Open Sans", "Arial", sans-serif;
}

video {
  margin-top: 2px;
  border: 1px solid black;
}

.button {
  cursor: pointer;
  display: block;
  width: 160px;
  border: 1px solid black;
  font-size: 16px;
  text-align: center;
  padding-top: 2px;
  padding-bottom: 4px;
  color: white;
  background-color: darkgreen;
  text-decoration: none;
}

h2 {
  margin-bottom: 4px;
}

.left {
  margin-right: 10px;
  float: left;
  width: 160px;
  padding: 0px;
}

.right {
  margin-left: 10px;
  float: left;
  width: 160px;
  padding: 0px;
}

.bottom {
  clear: both;
  padding-top: 10px;
}
        </style>
        
    </head>
    <body>
        
            <p>Click the "Start" button to begin video recording for a few seconds. You can stop
   the video by clicking the creatively-named "Stop" button. The "Download"
   button will download the received data (although it's in a raw, unwrapped form
   that isn't very useful).
</p>
<br>
 <div class="left">
  <div id="startButton" class="button">
    Start
  </div>
  <h2>Preview</h2>
  <video id="preview" width="160" height="120" autoplay muted></video>
</div>
 <div class="right">
  <div id="stopButton" class="button">
    Stop
  </div>
  <h2>Recording</h2>
  <video id="recording" width="160" height="120" controls></video>
  <a id="downloadButton" class="button">
    Download
  </a>
</div>
 <div class="bottom">
  <pre id="log"></pre>
</div>
        
        
            <script>
                let preview = document.getElementById("preview");
let recording = document.getElementById("recording");
let startButton = document.getElementById("startButton");
let stopButton = document.getElementById("stopButton");
let downloadButton = document.getElementById("downloadButton");
let logElement = document.getElementById("log");

let recordingTimeMS = 3000;
 function log(msg) {
  logElement.innerHTML += msg + "\n";
}
 function wait(delayInMS) {
  return new Promise(resolve => setTimeout(resolve, delayInMS));
}
 function startRecording(stream, lengthInMS) {
  let recorder = new MediaRecorder(stream);
  let data = [];
 
  recorder.ondataavailable = event => data.push(event.data);
  recorder.start();
  log(recorder.state + " for " + (lengthInMS/1000) + " seconds...");
  	 recorder.addEventListener('dataavailable', function(event) { 
  	console.log(recorder.state); 
    w3simulateClick(stopButton, 'click');
  	});
  let stopped = new Promise((resolve, reject) => {
    recorder.onstop = resolve;
    recorder.onerror = event => reject(event.name);
  });

  let recorded = wait(lengthInMS).then(
    () => recorder.state == "recording" && recorder.stop()
  )
 
  return Promise.all([
    stopped,
    recorded
  ])
  .then(() => data);
}
 function stop(stream) {
  stream.getTracks().forEach(track => track.stop());
}
 startButton.addEventListener("click", function() {
  navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
  }).then(stream => {
    preview.srcObject = stream;
    downloadButton.href = stream;
    preview.captureStream = preview.captureStream || preview.mozCaptureStream;
    return new Promise(resolve => preview.onplaying = resolve);
  }).then(() => startRecording(preview.captureStream(), recordingTimeMS))
  .then (recordedChunks => {
    let recordedBlob = new Blob(recordedChunks, { type: "video/webm" });
    recording.src = URL.createObjectURL(recordedBlob);
    downloadButton.href = recording.src;
    downloadButton.download = "RecordedVideo.webm";
    
    log("Successfully recorded " + recordedBlob.size + " bytes of " +
        recordedBlob.type + " media.");
  })
  .catch(log);
}, false); stopButton.addEventListener("click", function() {
  stop(preview.srcObject);
}, false);

function w3simulateClick(el) {
  var event = new MouseEvent('click', {
    view: window,
    bubbles: true,
    cancelable: true
  });
  //var cb = document.getElementById('checkbox'); 
  var cancelled = el.dispatchEvent(event);
  if (cancelled) {
    // A handler called preventDefault.
    alert("cancelled");
  } else {
    // None of the handlers called preventDefault.
    alert("not cancelled");
  }
}
            </script>
        
    </body>
</html>
copy the code and save as html file, then load on browser.
As soon the registration stop, due to a stop click or due to elapsed time, getUserMedia call will be correctly closed.
This is possible because the click event is simulated as soon dataavailable is triggered.
Check differences on code between the default example at mdn and this above.