• 在web页面音视频录制并下载到本地——MediaRecorder


    音视频录制前需要获取到流,使用 navigator.mediaDevices 来完成。

    navigator.mediaDevices

    MediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。

    简单介绍一下MediaDevices API。

    • 方法
    名称说明
    getDisplayMedia()提示用户选择显示器或显示器的一部分(例如窗口)以捕获为 MediaStream 以便共享或记录。返回解析为 MediaStreamPromise
    getUserMedia()在用户通过提示允许的情况下,打开系统上的相机或屏幕共享和/或麦克风,并提供 MediaStream 包含视频轨道和/或音频轨道的输入

    官方示例如下:

    "use strict";
    
    // Put variables in global scope to make them available to the browser console.
    var video = document.querySelector("video");
    var constraints = (window.constraints = {
      audio: false,
      video: true,
    });
    var errorElement = document.querySelector("#errorMsg");
    
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(function (stream) {
        var videoTracks = stream.getVideoTracks();
        console.log("Got stream with constraints:", constraints);
        console.log("Using video device: " + videoTracks[0].label);
        stream.onended = function () {
          console.log("Stream ended");
        };
        window.stream = stream; // make variable available to browser console
        video.srcObject = stream;
      })
      .catch(function (error) {
        if (error.name === "ConstraintNotSatisfiedError") {
          errorMsg(
            "The resolution " +
              constraints.video.width.exact +
              "x" +
              constraints.video.width.exact +
              " px is not supported by your device.",
          );
        } else if (error.name === "PermissionDeniedError") {
          errorMsg(
            "Permissions have not been granted to use your camera and " +
              "microphone, you need to allow the page access to your devices in " +
              "order for the demo to work.",
          );
        }
        errorMsg("getUserMedia error: " + error.name, error);
      });
    
    function errorMsg(msg, error) {
      errorElement.innerHTML += "

    " + msg + "

    "
    ; if (typeof error !== "undefined") { console.error(error); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    要实现web页面录制,需要请求获取音视频流的媒体许可,代码如下:

    const button = document.querySelector("button");
    button.addEventListener("click", async () => {
      // 音视频都录制
      const stream = await navigator.mediaDevices.getDisplayMedia({
        video: true,
        audio: true
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这样通过button实现如下效果:
    stream

    MediaRecorder

    MediaRecorderMediaStream Recording API 提供的用来进行媒体轻松录制的接口,他需要通过调用 MediaRecorder() 构造方法进行实例化。

    简单介绍一下 MediaRecorder API。

    • 构造函数
    名称说明
    MediaRecorder()创建一个新的 MediaRecorder 对象,对指定的 MediaStream 对象进行录制,支持的配置项包括设置容器的 MIME 类型 (例如"video/webm" 或者 “video/mp4”) 和音频及视频的码率或者二者同用一个码率
    • 配置项
    名称说明
    mimeType返回 MediaRecorder 对象创建时选择器选择的录制容器的 MIME type
    state返回录制对象 MediaRecorder 的当前状态 (闲置中,录制中或者暂停 ) (inactive, recording, or paused.)
    strem返回录制对象 MediaRecorder 创建时构造函数传入的 stream 对象
    • 方法
    名称说明
    isTypeSupported()返回一个 Boolean 值,来表示设置的 MIME type 是否被当前用户的设备支持
    start()开始录制媒体,这个方法调用时可以通过给 timeslice 参数设置一个毫秒值,如果设置这个毫秒值,那么录制的媒体会按照你设置的值进行分割成一个个单独的区块,而不是以默认的方式录制一个非常大的整块内容
    pause()暂停媒体录制
    resume()继续录制之前被暂停的录制动作
    stop()停止录制。同时触发 dataavailable 事件,返回一个存储Blob内容的录制数据。之后不再记录
    • 事件处理
    名称说明
    ondataavailable调用它用来处理 dataavailable 事件,该事件可用于获取录制的媒体资源 (在事件的 data 属性中会提供一个可用的 Blob 对象.)
    onstart用来处理 start 事件,该事件在媒体开始录制时触发
    onpause用来处理 pause 事件,该事件在媒体暂停录制时触发
    onresume用来处理 resume 事件,该事件在暂停后回复录制视频时触发
    onstop用来处理 stop 事件,该事件会在媒体录制结束时、媒体流(MediaStream)结束时、或者调用 MediaRecorder.stop() 方法后触发
    • 事件

    Listen to these events using addEventListener() or by assigning an event listener to the oneventname property of this interface.

    通过以上介绍,可以调用 MediaRecorder.isTypeSupported() 这个API来测试当前浏览器的支持情况。官方代码如下:

    const types = [
      "video/webm",
      "audio/webm",
      "video/webm;codecs=vp8",
      "video/webm;codecs=daala",
      "video/webm;codecs=h264",
      "audio/webm;codecs=opus",
      "video/mpeg",
    ];
    
    for (const type of types) {
      console.log(
        `Is ${type} supported? ${
          MediaRecorder.isTypeSupported(type) ? "Maybe!" : "Nope :("
        }`,
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    返回结果如图:
    type

    返回值为 True 的情况下,此代码显示Maybe,原因是即使编码格式支持,但是如果没有足够的资源来支持录制和编码过程,录制仍可能失败。所以仅作为参考判断,仍需要自己写错误处理。

    之后通过监听来进行下载操作,代码如下:

    const chunks = [];
    mediaRecorder.ondataavailable = e => chunks.push(e.data);
    
    mediaRecorder.onstop = () => {
      const blob = new Blob(chunks, { type: chunks[0].type });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "screen.webm";
      a.click();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样就实现了屏幕录制功能了,并且通过该方法实现了音视频下载的功能。

    完整代码

    完整代码下载地址

  • 相关阅读:
    主动调度是如何发生的
    mysql底层是如何存放数据的
    Github每日精选(第12期):去中心化的社交平台mastodon
    Unity简单实现对话功能
    数据库连接池
    国联易安:网络反不正当竞争,要防患于未然
    PHP危险函数
    C刊级 | Matlab实现GWO-BiTCN-BiGRU-Attention灰狼算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测
    Java 线程的调度与时间片
    python线程
  • 原文地址:https://blog.csdn.net/qq_16525279/article/details/134260185