Chrome 录屏

web 提供MediaRecorder 类来实现前端录屏功能。编码过程由浏览器实现,依赖浏览器的能力,因为该标准由 w3c 推进,目前主要的试验田在 chrome 和 firefox,移动端兼容安卓内置的 chrome 内核浏览器。

使用的时候,先调用构造函数,传入MediaStream媒体流,实现摄像头屏幕录制

MediaRecorder常用的方法

//该事件可用于获取录制的媒体资源
recorder.ondataavailable = (e) => {
  if (showDataAvailable) {
    console.log("trigger ondataavailable");
  }
  allChunks.push(e.data);
};
//开始录制
recorder.start();
//停止录制
recorder.stop();
//暂停录制
recorder.pause();

检测浏览器编码能力的 api

MediaRecorder.isTypeSupported(format);

可以把下面这段代码贴进 console,来测试当前浏览器的支持状况。

var types = [
  "video/webm",
  "audio/webm",
  "video/webm;codecs=vp8",
  "video/webm;codecs=daala",
  "video/webm;codecs=h264",
  "audio/webm;codecs=opus",
  "video/mpeg",
];

for (var i in types) {
  console.log(
    "Is " +
      types[i] +
      " supported? " +
      (MediaRecorder.isTypeSupported(types[i]) ? "Maybe!" : "Nope :(")
  );
}

屏幕录制示例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <video></video>
    <button class="record-btn">录制</button>
    <button class="record-stop-btn">停止</button>
    <button class="record-pause-btn">暂停</button>
    <button class="record-resume-btn">恢复录制</button>
  </body>
  <script>
    let btn = document.querySelectorAll(".record-btn")[0];
    console.log("btn: ", btn);
    let btnStop = document.querySelectorAll(".record-stop-btn")[0];
    let btnPause = document.querySelectorAll(".record-pause-btn")[0];
    let btnResume = document.querySelectorAll(".record-resume-btn")[0];

    let mediaRecorder = null;
    btn.addEventListener("click", async (e) => {
      let stream = await navigator.mediaDevices.getDisplayMedia({
        video: true,
      });
      const mime = MediaRecorder.isTypeSupported("video/webm;codecs=vp9")
        ? "video/webm;codecs=vp9"
        : "video/webm";
      mediaRecorder = new MediaRecorder(stream, { mimeType: mime });
      let chunks = [];
      mediaRecorder.addEventListener("dataavailable", (e) => {
        console.log("dataavailable");
        chunks.push(e.data);
      });

      mediaRecorder.addEventListener("stop", (e) => {
        let blob = new Blob(chunks, {
          type: chunks[0].type,
        });
        let url = URL.createObjectURL(blob);
        let video = document.querySelector("video");
        video.src = url;
        let a = document.createElement("a");
        a.href = url;
        a.download = "video.webm";
        a.click();
      });

      mediaRecorder.start();
    });
    btnStop.addEventListener("click", function () {
      mediaRecorder.stop();
    });
    btnPause.addEventListener("click", function () {
      mediaRecorder.pause();
    });
    btnResume.addEventListener("click", function () {
      mediaRecorder.resume();
    });
  </script>
</html>

调起摄像头录制,多了一步从摄像头中获取视频,放入 canvas 中渲染的过程。

let allChunks = [];
let format = "video/webm;codecs=vp9";
const stream = canvas.captureStream(60); // 录制帧率60fps
const recorder = new MediaRecorder(stream, {
  mimeType: format,
});

recorder.ondataavailable = (e) => {
  allChunks.push(e.data);
};

调起摄像头示例

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>MediaRecorder使用示例</title>
  </head>
  <style>
    canvas {
      box-shadow: 0 0 10px gray;
      display: block;
    }
  </style>
  <h3 style="text-align: center; margin-top: 10px">
    MediaRecorder使用示例 - 摄像头版本
  </h3>
  <p style="text-align: center; margin-top: 10px; color: grey">
    点击画布在视频上作画<button id="clearBtn">清除笔迹</button>
  </p>
  <div style="text-align: center; margin-top: 10px">
    <canvas
      id="canvas"
      height="460"
      width="640"
      style="width: 640px; margin: auto"
    ></canvas>
    <video src="" id="srcvideo" style="display: none"></video>
  </div>
  <div style="text-align: center; margin-top: 10px">
    <button id="startBtn" disabled>开始录制</button>
    <button id="pauseBtn" disabled>暂停录制</button>
    <button id="resumeBtn" disabled>恢复录制</button>
    <button id="stopBtn" disabled>结束录制</button>
  </div>
  <div style="text-align: center; margin-top: 20px">
    <p>切换录制编码格式</p>
    <p>
      <input
        type="radio"
        name="format"
        value="video/webm;codecs=vp8"
        onclick="setFormatSelect('video/webm;codecs=vp8')"
      />video/webm;codecs=vp8
    </p>
    <p>
      <input
        type="radio"
        name="format"
        value="video/webm;codecs=vp9"
        onclick="setFormatSelect('video/webm;codecs=vp9')"
        checked="checked"
      />video/webm;codecs=vp9
    </p>
    <p>
      <input
        type="radio"
        name="format"
        value="video/webm;codecs=h264"
        onclick="setFormatSelect('video/webm;codecs=h264')"
      />video/webm;codecs=h264
    </p>
    <p>
      <input
        type="radio"
        name="format"
        value="video/webm;codecs=avc1"
        onclick="setFormatSelect('video/webm;codecs=avc1')"
      />video/webm;codecs=avc1
    </p>
    <p>
      <input
        type="radio"
        name="format"
        value="video/x-matroska;codecs=avc1"
        onclick="setFormatSelect('video/x-matroska;codecs=avc1')"
      />video/x-matroska;codecs=avc1
    </p>
  </div>
  <script>
    var allChunks = [];
    var mousex = 0;
    var mousey = 0;
    var drawArray = [];

    init();

    function init() {
      const ctx = canvas.getContext("2d");
      ctx.fillStyle = "white";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      navigator.mediaDevices
        .getUserMedia({
          video: true,
        })
        .then(function (mediaStream) {
          var srcvideo = document.getElementById("srcvideo");
          srcvideo.srcObject = mediaStream;
          srcvideo.play();
          playCanvas(srcvideo, ctx);
        });

      // document.body.onmousedown = e => {
      // }
      clearBtn.onclick = (e) => {
        drawArray = [];
      };
      canvas.onmousemove = (e) => {
        const { top, left } = canvas.getBoundingClientRect();
        mousex = e.clientX - left;
        mousey = e.clientY - top;
      };
      canvas.onmousedown = (e) => {
        const { top, left } = canvas.getBoundingClientRect();
        var downx = e.clientX - left;
        var downy = e.clientY - top;
        drawArray.push({
          x: downx,
          y: downy,
        });
      };
      setRecorder();
      setFormatSelect("video/webm;codecs=vp9");
    }

    function playCanvas(srcvideo, ctx) {
      ctx.drawImage(srcvideo, 0, 0, 640, 460);
      for (var i = 0; i < drawArray.length; i++) {
        ctx.beginPath();
        const xFraction = drawArray[i].x / 640;
        const yFraction = drawArray[i].y / 460;
        const r = 255 * (1 - xFraction);
        const g = 255 * yFraction;
        const b = 255 * xFraction * (1 - yFraction);
        ctx.fillStyle = `rgba(${r | 0}, ${g | 0}, ${b | 0}, 1)`;
        ctx.arc(drawArray[i].x, drawArray[i].y, 10, 0, 2 * Math.PI);
        ctx.fill();
      }
      requestAnimationFrame(() => {
        playCanvas(srcvideo, ctx);
      });
    }

    function setFormatSelect(format) {
      if (!MediaRecorder.isTypeSupported(format)) {
        alert(format);
        alert("当前浏览器不支持该编码类型");
        return;
      }
      allChunks = [];
      setRecorder(format);
    }
    // 使用API录制Canvas核心代码如下
    function setRecorder(format) {
      const stream = canvas.captureStream(60); // 60 FPS recording
      const recorder = new MediaRecorder(stream, {
        mimeType: format,
      });
      recorder.ondataavailable = (e) => {
        allChunks.push(e.data);
      };

      startBtn.disabled = false;
      startBtn.onclick = (e) => {
        recorder.start(10);
        startBtn.disabled = true;
        pauseBtn.disabled = false;
        resumeBtn.disabled = true;
        stopBtn.disabled = false;
      };
      stopBtn.onclick = (e) => {
        recorder.stop();
        blobDownload(format);
        startBtn.disabled = false;
        pauseBtn.disabled = true;
        resumeBtn.disabled = true;
        stopBtn.disabled = true;
      };

      pauseBtn.onclick = (e) => {
        recorder.pause();
        pauseBtn.disabled = true;
        resumeBtn.disabled = false;
      };
      resumeBtn.onclick = (e) => {
        recorder.resume();
        pauseBtn.disabled = false;
        resumeBtn.disabled = true;
      };
    }
    //下载录制的视频
    function blobDownload(format) {
      const link = document.createElement("a");
      link.style.display = "none";
      const fullBlob = new Blob(allChunks);
      const downloadUrl = window.URL.createObjectURL(fullBlob);
      link.href = downloadUrl;
      link.download = "media - " + format + ".mp4";
      document.body.appendChild(link);
      link.click();
      link.remove();
    }
  </script>
</html>

如果chrome 报错 navigator.mediaDevices is undefined

解决方法
  • chrome 下
    打开 chrome://flags/#unsafely-treat-insecure-origin-as-secure

  • 选 enabled
    填写需要调试的 URL,多个 URL 以,隔开
    完全重启 chrome 后起效(改了之后下面也会有个 relaunch 按钮)

  • 重启后发现,就可以非 https 调试了

  • edge 下 毕竟现在 edge 和 chrome 内核一样了,所以操作方法一样,只是打开链接不同:edge://flags/#unsafely-treat-insecure-origin-as-secure

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值