【问题标题】:HTML 5 video recording and storing a streamHTML 5 视频录制和存储流
【发布时间】:2013-08-29 11:12:05
【问题描述】:

使用 Html 5 我想录制视频并将流保存到本地文件中。下面给出的是代码。在单击按钮时,它已经调用了相机并在 HTML 的“VIDEO”标签中捕获了视频。我可以将流存储到本地文件中吗?或者我可以将它存储为 MP4 文件吗?

<!DOCTYPE html>
<html>
<head>

<script type="text/javascript">

function enter() {

    if (navigator.mozGetUserMedia) { 
       navigator.myGetMedia=navigator.mozGetUserMedia;
       navigator.myGetMedia({video: true}, connect, error); 
    } 
    else {
       alert("NO");
    }

    function connect(stream) {

        var video = document.getElementById("my_video");
            video.src = window.URL ? window.URL.createObjectURL(stream) : stream;
            video.play();

        var canvas = document.getElementById("c"); 
    }

    function error(e) { console.log(e); }

}

</script>

</head>    
<body>
    <canvas width="640" height="480" id="c"></canvas>
    <input type="button" value="RECORD" onClick="enter()"/>
    <input type="button" value="SAVE" />
    <video id="my_video" width="640" height="480"/>
</body>
</html>

我想在单击保存按钮时保存流。

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    RecordRTC:WebRTC 音频/视频录制

    https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC

    • Chrome 和 Firefox 的录音
    • Chrome 的视频/Gif 录制; (Firefox 有一点问题,很快就会恢复)

    演示:https://www.webrtc-experiment.com/RecordRTC/


    从 getUserMedia() 创建 .webm 视频

    http://ericbidelman.tumblr.com/post/31486670538/creating-webm-video-from-getusermedia

    演示:http://html5-demos.appspot.com/static/getusermedia/record-user-webm.html


    在 HTML5 中捕获音频和视频

    http://www.html5rocks.com/en/tutorials/getusermedia/intro/

    【讨论】:

    • 良好的链接,有趣的解决方案。但请注意,这些仍然是依赖于拍摄画布元素的快照并使用 whammy 逐一编码帧的解决方法。
    • 它在 chrome 中被静音,并且 firfox 不支持视频如何在 firfox 中录制我的声音和视频
    • 还有其他人遇到 Gill 的问题吗?在我尝试这些解决方案之前想知道。
    • 这并没有说明实际保存任何东西
    【解决方案2】:

    MediaRecorder API 是您正在寻找的解决方案,

    Firefox 已经支持它有一段时间了,并且传闻是 Chrome 将在其下一个版本(Chrome 48)中实现它,但猜你可能仍然需要启用实验标志,显然该标志不会从 Chrome 版本 49 开始需要,有关更多信息,请查看此Chrome issue

    同时,一个如何在 Firefox 中执行此操作的示例:

    var video, reqBtn, startBtn, stopBtn, ul, stream, recorder;
    video = document.getElementById('video');
    reqBtn = document.getElementById('request');
    startBtn = document.getElementById('start');
    stopBtn = document.getElementById('stop');
    ul = document.getElementById('ul');
    reqBtn.onclick = requestVideo;
    startBtn.onclick = startRecording;
    stopBtn.onclick = stopRecording;
    startBtn.disabled = true;
    ul.style.display = 'none';
    stopBtn.disabled = true;
    
    function requestVideo() {
      navigator.mediaDevices.getUserMedia({
          video: true,
          audio: true
        })
        .then(stm => {
          stream = stm;
          reqBtn.style.display = 'none';
          startBtn.removeAttribute('disabled');
          video.src = URL.createObjectURL(stream);
        }).catch(e => console.error(e));
    }
    
    function startRecording() {
      recorder = new MediaRecorder(stream, {
        mimeType: 'video/mp4'
      });
      recorder.start();
      stopBtn.removeAttribute('disabled');
      startBtn.disabled = true;
    }
    
    
    function stopRecording() {
      recorder.ondataavailable = e => {
        ul.style.display = 'block';
        var a = document.createElement('a'),
          li = document.createElement('li');
        a.download = ['video_', (new Date() + '').slice(4, 28), '.webm'].join('');
        a.href = URL.createObjectURL(e.data);
        a.textContent = a.download;
        li.appendChild(a);
        ul.appendChild(li);
      };
      recorder.stop();
      startBtn.removeAttribute('disabled');
      stopBtn.disabled = true;
    }
    <div>
    
      <button id='request'>
        Request Camera
      </button>
      <button id='start'>
        Start Recording
      </button>
      <button id='stop'>
        Stop Recording
      </button>
      <ul id='ul'>
        Downloads List:
      </ul>
    
    </div>
    <video id='video' autoplay></video>

    【讨论】:

    • @jim,应该是https的问题,可以试试mido22.github.io/MediaRecorder-sample
    • 知道为什么我在第 47 行得到“NotSupportedError: Operation is not supported”,即recorder = new MediaRecorder(stream, {mimeType:'video/mp4' });
    • Firefox 62 在我的 HTTPS 本地主机上说 MediaStreamError{name: "NotFoundError",message:"The object can not be found here."}
    • 它支持 safari 吗?
    • video.srcObject = stm 而不是 video.src,参考下面的文章fxsitecompat.dev/en-CA/docs/2018/…
    【解决方案3】:

    目前没有可用于在网络上录制视频的生产就绪仅限 HTML5 解决方案。目前可用的解决方案如下:

    HTML 媒体捕捉

    适用于移动设备并使用操作系统的视频捕获应用程序捕获视频并将其上传/发布到网络服务器。您将在 iOS 上获得 .mov 文件(这些在我尝试过的 Android 上无法播放)和在 Android 上获得 .mp4 和 .3gp。至少编解码器是相同的:在 99% 的设备中,视频的 H.264 和音频的 AAC。

    图片由https://addpipe.com/blog/the-new-video-recording-prompt-for-media-capture-in-ios9/提供

    桌面上的 Flash 和媒体服务器

    Flash 中的视频录制工作如下:从网络摄像头和麦克风捕获音频和视频数据,使用 Sorenson Spark 或 H.264(视频)和 Nellymoser Asao 或 Speex(音频)对其进行编码,然后将其流式传输 (rtmp) 到保存在 .flv 或 .f4v 文件中的媒体服务器(Red5、AMS、Wowza)。

    MediaStream 录制提案

    MediaStream Recording 是 Media Capture Task Force(WebRTC 和设备 API 工作组之间的联合工作组)提出的一个 JS API 提案,其目的是让浏览器中的基本视频录制变得非常简单。

    主流浏览器不支持。当它被实现时(如果会的话)你很可能最终会得到不同的文件类型(至少 .ogg 和 .webm)和音频/视频编解码器,具体取决于浏览器。

    商业解决方案

    有一些 SaaS 和软件解决方案可以处理上述部分或全部问题,包括 addpipe.com、HDFVR、Nimbb 和 Cameratag。

    进一步阅读:

    【讨论】:

      【解决方案4】:

      这是一个优雅的库,可以在所有支持的浏览器中录制视频并支持上传:

      https://www.npmjs.com/package/videojs-record

      【讨论】:

      【解决方案5】:

      以下示例展示了如何在 HTML5 中捕获和处理视频帧:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8">
          <title>Capturing & Processing Video in HTML5</title>
      </head>
      <body>
          <div>
              <h2>Camera Preview</h2>
              <video id="cameraPreview" width="240" height="180" autoplay></video>
              <p>
                  <button id="startButton" onclick="startCapture();">Start Capture</button>
                  <button id="stopButton" onclick="stopCapture();">Stop Capture</button>
              </p>
          </div>
      
          <div>
              <h2>Processing Preview</h2>
              <canvas id="processingPreview" width="240" height="180"></canvas>
          </div>
      
          <div>
              <h2>Recording Preview</h2>
              <video id="recordingPreview" width="240" height="180" autoplay controls></video>
              <p>
                  <a id="downloadButton">Download</a>
              </p>
          </div>
      
          <script>
      
          const ROI_X = 250;
          const ROI_Y = 150;
          const ROI_WIDTH = 240;
          const ROI_HEIGHT = 180;
          
          const FPS = 25;
          
          let cameraStream = null;
          let processingStream = null;
          let mediaRecorder = null;
          let mediaChunks = null;
          let processingPreviewIntervalId = null;
      
          function processFrame() {
              let cameraPreview = document.getElementById("cameraPreview");
              
              processingPreview
                  .getContext('2d')
                  .drawImage(cameraPreview, ROI_X, ROI_Y, ROI_WIDTH, ROI_HEIGHT, 0, 0, ROI_WIDTH, ROI_HEIGHT);
          }
          
          function generateRecordingPreview() {
              let mediaBlob = new Blob(mediaChunks, { type: "video/webm" });
              let mediaBlobUrl = URL.createObjectURL(mediaBlob);
              
              let recordingPreview = document.getElementById("recordingPreview");
              recordingPreview.src = mediaBlobUrl;
      
              let downloadButton = document.getElementById("downloadButton");
              downloadButton.href = mediaBlobUrl;
              downloadButton.download = "RecordedVideo.webm";
          }
              
          function startCapture() {
              const constraints = { video: true, audio: false };
              navigator.mediaDevices.getUserMedia(constraints)
              .then((stream) => {
                  cameraStream = stream;
                  
                  let processingPreview = document.getElementById("processingPreview");
                  processingStream = processingPreview.captureStream(FPS);
                  
                  mediaRecorder = new MediaRecorder(processingStream);
                  mediaChunks = []
                  
                  mediaRecorder.ondataavailable = function(event) {
                      mediaChunks.push(event.data);
                      if(mediaRecorder.state == "inactive") {
                          generateRecordingPreview();
                      }
                  };
                  
                  mediaRecorder.start();
                  
                  let cameraPreview = document.getElementById("cameraPreview");
                  cameraPreview.srcObject = stream;
              
                  processingPreviewIntervalId = setInterval(processFrame, 1000 / FPS);
              })
              .catch((err) => {
                  alert("No media device found!");
              });
          };
          
          function stopCapture() {
              if(cameraStream != null) {
                  cameraStream.getTracks().forEach(function(track) {
                      track.stop();
                  });
              }
              
              if(processingStream != null) {
                  processingStream.getTracks().forEach(function(track) {
                      track.stop();
                  });
              }
              
              if(mediaRecorder != null) {
                  if(mediaRecorder.state == "recording") {
                      mediaRecorder.stop();
                  }
              }
              
              if(processingPreviewIntervalId != null) {
                  clearInterval(processingPreviewIntervalId);
                  processingPreviewIntervalId = null;
              }
          };
          </script>
      </body>
      </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-11
        • 1970-01-01
        • 2011-09-22
        • 1970-01-01
        • 2011-06-29
        • 2016-10-18
        • 1970-01-01
        相关资源
        最近更新 更多