demo: 视频流的录制与截视频帧

283 阅读1分钟
<!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>
  <div class="left">
    <div id="startButton" class="button">开始录制</div>
    <h2>预览</h2>
    <div class="video"><video id="preview" width="100%" height="auto" autoplay muted></video></div>
  </div>

  <button id="takePhotoButton">截图</button>
  <img src="" alt="" style="border:10px solid black ;">


  <div class="right">
    <div class="rightBtn">
      <div id="stopButton" class="button">停止录制</div>
      <a id="downloadButton" class="button">录屏下载</a>
    </div>
    <h2>Recording</h2>

    <div class="video"><video id="recording" width="160" height="120" controls></video></div>
  </div>
</body>
<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 takePhotoButton = document.getElementById("takePhotoButton");
  let dataChunks = [];
  let recorder;

  // 开始录制
  function startRecording(stream, lengthInMS) {
    // 构造函数:创建一个新的 MediaRecorder 对象,用于记录录制操作中的数据
    recorder = new MediaRecorder(stream);
    // dataavailable 事件触发时调用。dataavailable 当 MediaRcorder 将媒体数据传递给程序时触发。
    recorder.ondataavailable = (event) => {
      let data = event.data;
      // console.log('当 MediaRcorder 将媒体数据传递给程序时触发。', data)
      dataChunks.push(data);
    };
    // 开始录制:将媒体录制到一个多多个 Blob 对象中,timeslice: 间隔时间,每间隔该时间将数据统一返回。 recorder.state = recording
    recorder.start(1000);
    // recorder.state	录制的状态:inactive(未开始或停止),recording (正在录制),paused(暂停)
    console.log(recorder.state + " start to recording .....");
  }

  stopButton.addEventListener("click", () => {
    // close the recording
    preview.srcObject.getTracks().forEach((track) => track.stop());
    // 停止录制:引发 dataavailable 事件(将收集数据到 Blob 中), 触发停止事件。recorder.state = inactive 
    recorder.stop();

    // Play recorded video
    let recordedBlob = new Blob(dataChunks, { type: "video/webm" });
    // Blob URL/Object URL 是一种伪协议,允许 Blob 和 File 对象用作图像,下载二进制数据链接等的 URL 源。
    // 在浏览器中,我们使用 URL.createObjectURL 方法来创建 Blob URL,该方法接收一个 Blob 对象,
    // 并为其创建一个唯一的 URL,其形式为 blob:<origin>/<uuid>,对应的示例如下:
    // blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641
    recording.src = URL.createObjectURL(recordedBlob);

    // Save download video, click the download button, you can download it
    // a标签的作为下载 
    downloadButton.href = recording.src;
    downloadButton.download = "RecordedVideo.webm";
  });
  
  startButton.addEventListener("click", () => {
    // get the stream
    navigator.mediaDevices
      .getUserMedia({
        audio: true,
        video: true,
      })
      .then((stream) => {
        // console.log('stream: ', stream)
        // set the stream to left video
        preview.srcObject = stream;
        // set the stream to <a> for download
        downloadButton.href = stream;
        // captureStream: which is streaming a real-time capture of the content being rendered in the media element. 
        // A MediaStream object  which can be used as a source for audio or video data by other media
        preview.captureStream = preview.captureStream || preview.mozCaptureStream;
        // console.log('preview.captureStream',preview.captureStream )
        console.log('preview.srcObject.getTracks()', preview.srcObject.getTracks())
        startRecording(preview.captureStream());
      })
      .catch((err) => {
        console.log("recording error: ", err);
      });
  });

  takePhotoButton.addEventListener("click", function (e) {
    takePhoto()
  })
  // 截图
  async function takePhoto() {
    try {
      // 拿到视频轨道
      let videoTracks = preview.srcObject.getVideoTracks()[0]
      console.log('视频轨道', videoTracks)
      // 图像捕获
      imageCapture = new ImageCapture(videoTracks);
      console.log('imageCapture', imageCapture)
      const blob = await imageCapture.takePhoto();
      console.log("Photo taken: " + blob.type + ", " + blob.size + "B");
      const image = document.querySelector('img');
      image.src = URL.createObjectURL(blob);
    } catch (err) {
      console.error("takePhoto() failed: ", err);
    }
  }

</script>

</html>