【问题标题】:How to capture the video to the server using getusermedia如何使用 getusermedia 将视频捕获到服务器
【发布时间】:2013-05-10 05:59:05
【问题描述】:

在我的应用程序中,我希望用户录制他的视频。然后应该将视频下载到服务器磁盘。但它正在下载到客户端浏览器。如何将 2 或 3 分钟的视频保存到服务器。我为此使用了getusermedia。我写了这样的代码:

(function(exports) {
exports.URL = exports.URL || exports.webkitURL;
exports.requestAnimationFrame = exports.requestAnimationFrame ||
    exports.webkitRequestAnimationFrame || exports.mozRequestAnimationFrame ||
    exports.msRequestAnimationFrame || exports.oRequestAnimationFrame;

exports.cancelAnimationFrame = exports.cancelAnimationFrame ||
    exports.webkitCancelAnimationFrame || exports.mozCancelAnimationFrame ||
    exports.msCancelAnimationFrame || exports.oCancelAnimationFrame;

navigator.getUserMedia = navigator.getUserMedia ||
    navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
    navigator.msGetUserMedia;

var ORIGINAL_DOC_TITLE = document.title;
var video = $('video');
var canvas = document.createElement('canvas'); 
var rafId = null;
var startTime = null;
var endTime = null;    

function $(selector) {
    return document.querySelector(selector) || null;
}

function toggleActivateRecordButton() {
    var b = $('#record-me');
    b.textContent = b.disabled ? 'Record' : 'Recording...';
    b.classList.toggle('recording');
    b.disabled = !b.disabled;
}

function turnOnCamera(e) {
    e.target.disabled = true;
    $('#record-me').disabled = false;

    video.controls = false;

    var finishVideoSetup_ = function() {

        setTimeout(function() {
            video.width = 320;
            video.height = 240;           
            canvas.width = video.width;
            canvas.height = video.height;
        }, 1000);
    };       

    navigator.getUserMedia({video: true}, function(stream) {
        video.src = window.URL.createObjectURL(stream);
        finishVideoSetup_();
    }, function(e) {           
        video.src = 'Chrome_ImF.mp4';
        finishVideoSetup_();
    });

    if (navigator.getUserMedia) {
        navigator.getUserMedia({ audio: true }, onRecordSucces, onFail);
    } else {
        console.log('navigator.getUserMedia not to present');
    }


};

function record() {
    var elapsedTime = $('#elasped-time');
    var ctx = canvas.getContext('2d');
    var CANVAS_HEIGHT = canvas.height;
    var CANVAS_WIDTH = canvas.width;
    frames = []; // clear existing frames;
    startTime = Date.now();
    toggleActivateRecordButton();
    $('#stop-me').disabled = false;
    function drawVideoFrame_(time) {
        rafId = requestAnimationFrame(drawVideoFrame_);
        ctx.drawImage(video, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
        document.title = 'Recording...' + Math.round((Date.now() - startTime) / 1000) + 's';  
        var url = canvas.toDataURL('image/webp', 1); 
        frames.push(url);
    };
    rafId = requestAnimationFrame(drawVideoFrame_);
    startRecording();
};

function stop() {
    cancelAnimationFrame(rafId);
    endTime = Date.now();
    $('#stop-me').disabled = true;
    document.title = ORIGINAL_DOC_TITLE;
    toggleActivateRecordButton();    
    embedVideoPreview();
};


function embedVideoPreview(opt_url) {
    var url = opt_url || null;
    var video = $('#video-preview video') || null;
    var downloadLink = $('#video-preview a[download]') || null;

    if (!video) {
        video = document.createElement('video');
        video.autoplay = true;
        video.controls = true;       
        video.style.width = canvas.width + 'px';
        video.style.height = canvas.height + 'px';
        $('#video-preview').appendChild(video);

        downloadLink = document.createElement('a');
        downloadLink.download = 'capture.webm';
        downloadLink.textContent = '[ download video ]';
        downloadLink.title = 'Download your .webm video';
        var p = document.createElement('p');
        p.appendChild(downloadLink);

        $('#video-preview').appendChild(p);

    } else {
        window.URL.revokeObjectURL(video.src);
    }



    if (!url) {
        webmBlob = Whammy.fromImageArray(frames, 1000 / 60);
        url = window.URL.createObjectURL(webmBlob);

    video.src = url;
    downloadLink.href = url;
}

function initEvents() {
    $('#camera-me').addEventListener('click', turnOnCamera);
    $('#record-me').addEventListener('click', record);
    $('#stop-me').addEventListener('click', stop);
}

initEvents();

exports.$ = $;

})(window);

当我单击下载链接时,它会下载到用户浏览器。但我想将数据发送到服务器并将其保存在服务器磁盘中。我试图将webmblob 数据传递给控制器​​并检索。但它没有访问。我写过类似的代码

 $.ajax({
     url: '/Home/VideoData',
     type: 'POST',
     dataType: 'blob',
     cache: false,
     data: {
           data: webmblob
           },
     contentType: "application/json; charset=utf-8",
     error: function (xhr, status, error) {
     },
     success: function () {

     },
   });

在我定义的控制器中

  public ActionResult VideoData(string data)
  {
      return Json("success", JsonRequestBehavior.AllowGet);
  }

但是像[object blob] 这样的控制器的数据。 对不起我的英语不好。希望你能理解我的问题。我怎样才能把它转换成视频。任何帮助肯定会受到赞赏。

【问题讨论】:

  • 您的 contentType 标头(在第二个代码块中)应该是 video/webm 而不是“application/json”。
  • 您找到解决方案了吗?

标签: c# jquery html html5-canvas getusermedia


【解决方案1】:

Chrome (49+) 和 Firefox (30+) 现在都支持 Media Recorder API,它依赖 getUserMedia() 来访问网络摄像头。

视频数据本地存储在 JavaScript video/webm Blob object 中,可以是:

  • <video> 元素中播放
  • .webm 文件的形式下载到客户端计算机
  • 已上传(发布)到网络服务器进行存储和转换

This article 详细介绍了规范,这里是live demo + GitHub project。 规格是avb。在w3c

【讨论】:

  • MediaRecorder API 的问题在于它不是实时的
  • @xybrek 怎么不是“实时”的?
  • 我的意思是与通过 Canvas 捕获视频流相比,您将流渲染到画布中,例如requestAnimationFrame 然后从每一帧中获取图像并做一些事情。使用 MediaRecorder 会有一点延迟,至少在开始时是这样。因此,如果您将该 API 用于实时视频,例如视频通话,那么延迟就会增加。至少这是我的经验,让我知道你的想法?
  • @xybrek 一开始你需要考虑相机初始化时间varies a lot with hardware。此外,Media Recorder API 为您提供编码流(H.264、VP8、Opus 等),这肯定需要一些时间。
【解决方案2】:

MediaStreamRecorder 是一个用于记录 getUserMedia() 流的 WebRTC API。它允许网络应用从实时音频/视频会话中创建文件。

<video autoplay></video>

<script language="javascript" type="text/javascript">
function onVideoFail(e) {
    console.log('webcam fail!', e);
  };

function hasGetUserMedia() {
  // Note: Opera is unprefixed.
  return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia || navigator.msGetUserMedia);
}

if (hasGetUserMedia()) {
  // Good to go!
} else {
  alert('getUserMedia() is not supported in your browser');
}

window.URL = window.URL || window.webkitURL;
navigator.getUserMedia  = navigator.getUserMedia || 
                         navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia || 
                           navigator.msGetUserMedia;

var video = document.querySelector('video');
var streamRecorder;
var webcamstream;

if (navigator.getUserMedia) {
  navigator.getUserMedia({audio: true, video: true}, function(stream) {
    video.src = window.URL.createObjectURL(stream);
    webcamstream = stream;
//  streamrecorder = webcamstream.record();
  }, onVideoFail);
} else {
    alert ('failed');
}

function startRecording() {
    streamRecorder = webcamstream.record();
    setTimeout(stopRecording, 10000);
}
function stopRecording() {
    streamRecorder.getRecordedData(postVideoToServer);
}
function postVideoToServer(videoblob) {

    var data = {};
    data.video = videoblob;
    data.metadata = 'test metadata';
    data.action = "upload_video";
    jQuery.post("http://www.foundthru.co.uk/uploadvideo.php", data, onUploadSuccess);
}
function onUploadSuccess() {
    alert ('video uploaded');
}

</script>

<div id="webcamcontrols">
    <button class="recordbutton" onclick="startRecording();">RECORD</button>
</div>

规格:

http://www.w3.org/TR/mediastream-recording/

您可以获取记录器媒体文件,将其发送到服务器。

【讨论】:

  • webcamstream.record(); //测试代码时没有这样的方法。是插件还是扩展
  • @ifeanyiChukwu 你看过 W3C 规范了吗?请看一下规范,这个 Record API 仍在实施中。
  • dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/…。我认为 api 是在 8 月 9 日更新的。查看上面的链接后,我注意到没有 .record() 方法。它被删除或替换为 .start() 方法。
  • 我更新了我的浏览器.......但是没有找到 .record() 方法。引发类型错误。
  • 我对引用相同 API 的不同规范文档感到困惑,从您的链接中您可以使用 .start() 开始录制。无论如何,您必须等到 chrome 实施。
猜你喜欢
  • 2015-02-27
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-22
  • 2012-09-17
  • 2014-02-11
相关资源
最近更新 更多