JSFiddle - React, Tailwind, and code Playground

by mamounothman

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1"
    />
    <title>MediaStream Recording -> MediaSource</title>
    <link rel="stylesheet" href="main.css" />
  </head>

  <body>
    <div id="container">
      <video id="gum" playsinline="" autoplay="" muted=""></video>
      <video id="recorded" playsinline="" src="" controls=""></video>

      <div>
        <button id="record">Start</button>
      </div>
    </div>
    <script src="main.js" async=""></script>
  </body>
</html>

CSS

/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
.hidden {
  display: none;
}

.highlight {
  background-color: #eee;
  font-size: 1.2em;
  margin: 0 0 30px 0;
  padding: 0.2em 1.5em;
}

.warning {
  color: red;
  font-weight: 400;
}

@media screen and (min-width: 1000px) {
  /* hack! to detect non-touch devices */
  div#links a {
    line-height: 0.8em;
  }
}

audio {
  max-width: 100%;
}

body {
  font-family: "Roboto", sans-serif;
  font-weight: 300;
  margin: 0;
  padding: 1em;
  word-break: break-word;
}

button {
  background-color: #d84a38;
  border: none;
  border-radius: 2px;
  color: white;
  font-family: "Roboto", sans-serif;
  font-size: 0.8em;
  margin: 0 0 1em 0;
  padding: 0.5em 0.7em 0.6em 0.7em;
}

button:active {
  background-color: #cf402f;
}

button:hover {
  background-color: #cf402f;
}

button[disabled] {
  color: #ccc;
}

button[disabled]:hover {
  background-color: #d84a38;
}

canvas {
  background-color: #ccc;
  max-width: 100%;
  width: 100%;
}

code {
  font-family: "Roboto", sans-serif;
  font-weight: 400;
}

div#container {
  margin: 0 auto 0 auto;
  max-width: 60em;
  padding: 1em 1.5em 1.3em 1.5em;
}

div#links {
  padding: 0.5em 0 0 0;
}

h1 {
  border-bottom: 1px solid #ccc;
  font-family: "Roboto", sans-serif;
  font-weight: 500;
  margin: 0 0 0.8em 0;
  padding: 0 0 0.2em 0;
}

h2 {
  color: #444;
  font-weight: 500;
}

h3 {
  border-top: 1px solid #eee;
  color: #666;
  font-weight: 500;
  margin: 10px 0 10px 0;
  white-space: nowrap;
}

li {
  margin: 0 0 0.4em 0;
}

html {
  /* avoid annoying page width change
  when moving from the home page */
  overflow-y: scroll;
}

img {
  border: none;
  max-width: 100%;
}

input[type="radio"] {
  position: relative;
  top: -1px;
}

p {
  color: #444;
  font-weight: 300;
}

p#data {
  border-top: 1px dotted #666;
 ...

JavaScript

/*
*  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
*  Use of this source code is governed by a BSD-style license
*  that can be found in the LICENSE file in the root of the source
*  tree.
*/

"use strict";

const mediaSource = new MediaSource();
mediaSource.addEventListener("sourceopen", handleSourceOpen);
mediaSource.addEventListener("sourceclose", () =>
  console.log("mediaSource closed")
);
mediaSource.addEventListener("sourceended", () =>
  console.log("mediaSource ended")
);
let mediaRecorder;
let recordedBlobs;
let sourceBuffer;
let updatingBuffer = false;
let options;
const constraints = {
  audio: true,
  video: {
    width: 1280,
    height: 720
  }
};
let userMediaStream;

const recordedVideo = document.querySelector("video#recorded");
const recordButton = document.querySelector("button#record");
recordButton.addEventListener("click", () => {
  if (recordButton.textContent === "Start") {
    startRecording();
  } else {
    stopRecording();
    recordButton.textContent = "Start";
  }
});

function handleSourceOpen(event) {
  console.log("MediaSource opened");
  sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp9"');
  sourceBuffer.addEventListener("update", () => {
    console.log("sourceBuffer update");
  });
  sourceBuffer.addEventListener("error", e =>
    console.log(`sourceBuffer error: ${JSON.stringify(e, null, 2)}`)
  );
  console.log("Source buffer: ", sourceBuffer);
  sourceBuffer.addEventListener("abort", () =>
    console.log("sourceBuffer abort")
  );
  sourceBuffer.addEventListener("updatestart", () =>
    console.log("sourceBuffer update start")
  );
  sourceBuffer.addEventListener("updateend", () => {
    console.log("sourceBuffer update end");
    updatingBuffer = false;
  });
}

async function handleDataAvailable(event) {
  // console.log("handleDataAvailable", event);
  if (event.data && event.data.size > 0) {
    recordedBlobs.push(event.data);
  }

  if (recordedBlobs.length > 5) {
    if...