如何使用 JavaScript MediaRecorder API 创建视频和音频录制器?

javascriptweb developmentfront end technology

在本教程中,您将学习如何使用 JavaScript MediaRecorder API 创建音频和视频录制器。因此,可以使用 WebRTC 完成此操作。

什么是 WebRTC?

WebRTC 是实时通信的简称。我们可以访问和捕获用户设备中可用的网络摄像头和麦克风设备。

我们可以使用 ECMAScript 对象访问用户设备的网络摄像头和麦克风

navigator.mediaDevices.getUserMedia(constraints)。

因此,getUserMedia 函数默认会寻求用户使用网络摄像头的权限。此函数返回一个promise,一旦您单击"确定"并表示同意,该函数就会被触发并启用系统中的网络摄像头,否则,如果您不允许,它还有一个关闭网络摄像头的 catch 方法。

我们还可以将一个参数传递给函数 getUserMedia(),这可能就像我们想要一张具有特定宽度或高度的图片一样。

前端设计

我们的前端部分将包含以下元素:-

对于视频录制屏幕,将包含以下元素:-

  • 将显示视频媒体屏幕的视频元素

  • 开始按钮将开始视频录制

  • 停止按钮将停止视频录制流。

对于音频录制此外,它还会有两个按钮

  • "开始"按钮将开始录音

  • "停止"按钮将停止录音流。

我们将添加 Font Awesome CDN 来添加开始和停止按钮图标,并且为了让页面更具吸引力,我们将在元素上添加 CSS 样式。

HTML 代码

示例

<!DOCTYPE html>
<html>
<head>
   <title>Video & Audio Recorder</title>
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
   <style>
      body {
         text-align: center;
         color: red;
         font-size: 1.2em;
      }
      /* styling of start and stop buttons */
      #video_st, #video_en, #aud_st, #aud_en{
         margin-top: 10px;
         padding: 10px;
         border-radius: 4px;
         cursor: pointer;
      }
      #vidBox{
         background-color: grey;
      }
      /*video box styling*/
      video {
         background-color: gray;
         display: block;
         margin: 6px auto;
         width: 520px;
         height: 240px;
      }
      /*audio box styling*/
      audio {
         display: block;
         margin: 6px auto;
      }
      a {
         color: green;
      }
   </style>
</head>
<body>
   <h1 style="color:blue"> Video-Audio recorder</h1>
   <div class="display-none" id="vid-recorder">
   
   <h3>Record Video </h3>
   <video autoplay id="vidBox"> </video>
   
   <!-- click this button to start video recording -->
   <button type="button" id="video_st" onclick="start_video_Recording()"> <i class="fa fa-play"></i></button>
   
   <!-- click this button to stop video recording -->
   <button type="button" id="video_en" disabled onclick="stop_Recording(this, document.getElementById('video_st'))">
   
   <i class="fa fa-stop"></i>
   </button>
   
</div>
<!-- ------------ -->
<br>
<hr>
<!-- ------------ -->
   <div class="display-none" id="audio_rec">

      <h3> Record Audio</h3>
      <!-- click this button to start audio recording -->
      <button type="button" id="aud_st"
         onclick="start_audio_Recording()"><i class="fa fa-play"></i>
      </button>
      
      <!-- click this button to stop video recording -->
      <button type="button" id="aud_en"disabled onclick="stop_Recording(this, document.getElementById('aud_st'))"> <i class="fa fa-stop"></i></button>
   </div>
</body>
</html>

当您点击"开始视频"按钮时,它将调用start_video_Recording()函数,"停止"按钮将调用stop_Recording(),同样对于音频,点击开始按钮将触发函数start_audio_Recording(),对于停止按钮将调用stop_Recording()函数。

start_video_Recording()函数

让我们定义一个函数来启动视频并录制它。

function start_video_Recording() {
   // 存储录制的媒体
   let chunksArr= [];
   const startBtn=document.getElementById("video_st");
   const endBtn=document.getElementById("video_en");
   
      // 访问摄像头和麦克风的权限
      navigator.mediaDevices.getUserMedia({audio: true, video: true})
      .then((mediaStreamObj) => {
      
        // 创建一个新的 MediaRecorder 实例
        const medRec =new MediaRecorder(mediaStreamObj);
        window.mediaStream = mediaStreamObj;
        window.mediaRecorder = medRec;
        medRec.start();
        
        //当录制的数据可用时,将其推送到 chunkArr 数组中
        medRec.ondataavailable = (e) => {chunksArr.push(e.data);};
        
        //停止视频录制
        medRec.onstop = () => {
        const blobFile = new Blob(chunksArr, { type:"video/mp4" });
        chunksArr= [];
        
        // 创建视频元素并存储录制的媒体
        const recMediaFile = document.createElement("video");
        recMediaFile.controls = true;
        const RecUrl = URL.createObjectURL(blobFile);
        
        //将录制的 URL 保留为源
        recMediaFile.src = RecUrl;
        document.getElementById(`vid-recorder`).append(recMediaFile);
      };
      document.getElementById("vidBox").srcObject = mediaStreamObj;
      //禁用开始按钮并启用停止按钮
      startBtn.disabled = true;
      endBtn.disabled = false;
   });
}

当按下开始按钮时,它将调用上述函数,该函数将触发 WebRTC 摄像头和麦克风方法来获取录制权限,并启用停止录制并禁用开始录制按钮。

当按下停止按钮时,它将调用 stop() 函数并停止所有媒体流轨道。

然后,为了录制媒体流,我们将创建一个媒体录制器实例,并使媒体流以及媒体重新排序全局化。然后停止视频将停止媒体流,创建视频元素将创建一个新的视频元素并存储录制的媒体数据。

同样,start_audio_Recording() 函数也类似于 start_video_Recording() 函数,但需要进行一些更改。

stop_Recording() 函数

现在让我们定义一个函数来停止录制。

function stop_Recording(end, start) {
    window.mediaRecorder.stop();
    
    // 停止所有曲目
    window.mediaStream.getTracks() .forEach((track) => {track.stop();});
    //禁用停止按钮并启用开始按钮
    end.disabled = true;
    start.disabled = false;
}

该函数将停止存储在媒体流中的所有媒体轨道。

示例

让我们将上述函数添加到 HTML 代码中,以使视频和音频录制功能可用。

<!DOCTYPE html>
<html>
<head>
   <title>Video & Audio Recorder</title>
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
   <style>
      body {
         text-align: center;
         color: red;
         font-size: 1.2em;
      }
      //视频开始和结束,音频开始和结束按钮样式
      #video_st, #video_en, #aud_st, #aud_en{
         margin-top: 10px;
         padding: 10px;
         border-radius: 4px;
         cursor: pointer;
      }
      #vidBox{
         background-color: grey;
      }
      video {
         background-color: gray;
         display: block;
         margin: 6px auto;
         width: 420px;
         height: 240px;
      }
      audio {
         display: block;
         margin: 6px auto;
      }
      a {
         color: green;
      }
   </style>
</head>
<body>
  <h1 style="color:blue"> Video-Audio recorder</h1>
   <div class="display-none" id="vid-recorder">
      <h3>Record Video </h3>
      <video autoplay id="vidBox"> </video>
      <button type="button" id="video_st" onclick="start_video_Recording()"> <i class="fa fa-play"></i></button>
      <button type="button" id="video_en" disabled onclick="stop_Recording(this, document.getElementById('video_st'))">
         <i class="fa fa-stop"></i>
      </button>
   </div>
   <!-- ------------ -->
   <br>
   <hr>
   <!-- ------------ -->
   <div class="display-none" id="audio_rec">
      <h3> Record Audio</h3>
      <button type="button" id="aud_st"
      onclick="start_audio_Recording()"><i class="fa fa-play"></i>
      </button>
      <button type="button" id="aud_en"
      disabled onclick="stop_Recording(this, document.getElementById('aud_st'))"> <i class="fa fa-stop"></i></button>
   </div>
<script>

//----------------------Video-------------------------------------
function start_video_Recording() {
    //存储录制的媒体
    let chunks = [];
    const startBtn=document.getElementById("video_st");
    const endBtn=document.getElementById("video_en");
    
    // 访问摄像头和麦克风
    navigator.mediaDevices.getUserMedia({audio: true, video: true})
    .then((mediaStreamObj) => {
   
        // 创建一个新的 MediaRecorder 实例
        const medRec =new MediaRecorder(mediaStreamObj);
        window.mediaStream = mediaStreamObj;
        window.mediaRecorder = medRec;
        medRec.start();
        
        //当录制的数据可用时,将其推送到 chunkArr 数组中
        medRec.ondataavailable = (e) => {
        chunks.push(e.data);
        };
        
        //停止视频录制
        medRec.onstop = () => {
            const blobFile = new Blob(chunks, { type:"video/mp4" });chunks = [];
            
            // 创建视频元素并存储录制的媒体
            const recMediaFile = document.createElement("video");
            recMediaFile.controls = true;
            const RecUrl = URL.createObjectURL(blobFile);
            
            //将录制的 url 保留为源
            recMediaFile.src = RecUrl;
            document.getElementById(`vid-recorder`).append(recMediaFile);
      };
      document.getElementById("vidBox").srcObject = mediaStreamObj;
      startBtn.disabled = true;
      endBtn.disabled = false;
   });
}
//--------------------audio---------------------------------------

function start_audio_Recording() {
    //存储录制的媒体
    let chunksArr = [];
    const startBtn=document.getElementById("aud_st");
    const endBtn=document.getElementById("aud_en");
    
    //访问摄像头和麦克风
    navigator.mediaDevices.getUserMedia({audio: true, video: false})
    .then((mediaStream) => {
        const medRec = new MediaRecorder(mediaStream);
        window.mediaStream = mediaStream;
        window.mediaRecorder = medRec;
        medRec.start();
        
        //当录制的数据可用时,将其推送到 chunkArr 数组中
        medRec.ondataavailable = (e) => {
            chunksArr.push(e.data);
        };
    
    //停止录音
      medRec.onstop = () => {
         const blob = new Blob(chunksArr, {type: "audio/mpeg"});
         chunksArr = [];
         
         // 创建音频元素并存储录制的媒体
         const recMediaFile = document.createElement("audio");
         recMediaFile.controls = true;
         const RecUrl = URL.createObjectURL(blob);
         recMediaFile.src = RecUrl;
         document.getElementById(`audio_rec`).append(
         recMediaFile);
      };
      startBtn.disabled = true;
      endBtn.disabled = false;
   });
}
function stop_Recording(end, start) {
   //停止所有曲目
   window.mediaRecorder.stop();
   window.mediaStream.getTracks() .forEach((track) => {track.stop();});
      //禁用停止按钮并启用开始按钮
      end.disabled = true;
      start.disabled = false;
   }
</script>
</body>
</html>

从输出中可以看出,当单击视频开始按钮时,它会调用start_video_Recording()函数,在该函数中,navigator.mediaDevices.getUserMedia()方法被调用,并打开一个权限菜单,该菜单寻求视频和麦克风权限。它返回一个解析媒体流的承诺。在收到音频或视频媒体流后,它会创建一个媒体记录器实例,并通过调用上述代码中的函数medRec.start()开始录制。

因此,您将了解使用WebRTC创建视频和音频录制的完整过程。


相关文章