[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"content-capture_video_on_web":3,"$f1t7wr8fkvdhl2":22},{"id":4,"type":5,"slug":6,"title":7,"date":8,"category":9,"tags":10,"body_markdown":13,"permalink":14,"excerpt_src":15,"media_type":15,"media_title":15,"media_author":15,"media_url":15,"rating":15,"layout":15,"pv":16,"admin_only":16,"created_at":17,"updated_at":17,"deleted_at":15,"status":18,"html":19,"excerpt":20,"cover":21},165,"article","capture_video_on_web","如何使用web录制视频","2016-09-25 19:58","web",[11,12],"Video","WebRTC","\n最近在某个需求的评审会上，产品同学脑洞大开，提出了**使用web录制视频**的想法。并兴致勃勃地说“看，XXX网站可以调用摄像头，还能聊天呢！”本着负（Zhuang）责（Bi）的原则，我们也对该方案做了认真的预研。大致结论：\n\n1. 非实时录制时（文件上传框），兼容性相对较好，且API和性能稳定\n2. 实时录制视频在Chrome for Android中可行，其它机型和浏览器均不可使用。考虑到相关标准仍处于不稳定状态，不建议在产品中使用\n3. 微信有非公开接口可以调用实时视频录制（微证券使用）\n\n详细方案如下：\n\n\u003C!-- more -->\n\n## 方案一：使用文件上传框\n\n文件上传框`\u003Cinput type=\"file\">`是前端同学非常熟悉的一个HTML控件，它的主要作用是用来上传文件。而在移动端，这个文件上传框被赋予了更多的使命，除了可以选择文件上传之外，还可以调用摄像头来拍摄照片或者视频并上传。\n\n具体的使用方式：\n\n```html\n\u003Cinput type=\"file\" accept=\"video\u002F*\"\u002F>\n```\n\n或者\n\n```html\n\u003Cinput type=\"file\" accept=\"video\u002Fmp4,video\u002Fx-m4v,video\u002F*\"\u002F>\n```\n\n这两种写法的区别在于对不同机型来说兼容性可能略有区别，但是具体的情况未做一一测试总结。经过初步测试，该方案可以在以下环境中运行：\n\n- Android 4.4+\n- iOS 6.0+\n- 微信webview\n- Chrome for Android\n\n> 注：该兼容性列表是我们简单测试一部分机器后的结论，不做任何保证。事实上我们也碰到一部分Android机器是例外。下文兼容性列表同理。\n\n该方案API简单易用，且功能由浏览器或webview原生实现，性能比较稳定。\n\n\n该方案缺点：非实时录制视频，无法确定用户是录制的还是选取的已有的视频文件。\n\n相关demo \u003Chttp:\u002F\u002Fcodepen.io\u002FTooBug\u002Fembed\u002FRRZQxr\u002F>\n\n## 方案二：视频录制\n\n要使用web录制视频，需要两个相关API，一个用于调用摄像头，一个用于录制。调用摄像头后会产生一个视频流，然后调用录制API将这个视频流压缩和保存。\n\n其中调用摄像头的API叫作`getUserMedia()`，以前属于`navigator`对象（Chrome 21-49），后来规范修改，现在属于`MediaDevices`（Chrome 49+）。该API还负责提示用户授权。\n\n视频流叫作`MediaStream`。拿到`MediaStream`后，可配合`ObjectURL`，产生一个虚拟URL，供浏览器`video`标签调用，实现视频回放（回显）。\n\n用于录制视频的API叫作`MediaRecorder`。该API在Chrome 49+可用。\n\n该方案兼容性：\n\n- Chrome 49+\n- Firefox 29+\n- Chrome for Android\n\n相关Demo地址：\u003Chttps:\u002F\u002Fsimpl.info\u002Fmediarecorder\u002F>\n\n## 方案三：WebRTC视频流远程录制\n\nWebRTC是指实现web实时通信的一系列规范，一般可以通俗地理解为“P2P视频聊天”。实现这个功能依赖于上方说的摄像头调用API `getUserMedia()`取到`MediaStream`，同时还依赖一个P2P网络连接和传输的API来实现视频流数据的传输，这个API叫作`RTCPeerConnection`。\n\n在实际运作时，需要服务额外处理两个浏览器在P2P通信之前的Session建立相关的逻辑：\n\n![WebRTC实际原理图](\u002Fassets\u002Fcapture_video_on_web\u002F1.png)\n\n同时，还需要服务端支持来完成浏览器在NAT等复杂网络环境中的通信“打洞”需求：\n\n![WebRTC实际原理图](\u002Fassets\u002Fcapture_video_on_web\u002F2.png)\n\n使用该方案录制视频的原理是通过服务端模拟一个浏览器（Peer），实现相关视频流接收解码协议以及`RTCPeerConnection`协议。\n\nSession管理的服务端和打洞的服务端实现和维护比较麻烦，但有例可循，而模拟Peer的部分则实现过于复杂，因此，虽然该方案理论上可行，且浏览器兼容性稍好，但仍然认为该方案在实际操作中不可行。\n\n这个方案的兼容性\n\n- Firefox 17+\n- Chrome 21+\n- Edge 12+\n- Chrome for Android\n\n## 方案四：截图上传\n\n该方案原理：在使用`getUserMedia()`获取视频流之后，将该视频流定时投映到一张2d画布中（`canvas`），然后将画布中的画面提取成图片数据（`base64`）。\n\n该方案原理比较简单，兼容性\n\n- Firefox 17+\n- Chrome 21+\n- Edge 12+\n- Chrome for Android\n\n但同时也有明显缺陷：\n\n- 无法获取声音数据，只能获取到图片数据\n- 需要上传后由后台转换成视频\n- 帧数多时图片可能较大，造成性能问题（比如崩溃）\n- 帧数多时图片可能较大，造成网络传输慢\n\n## 相关文档\n\n- [MDN上的navigator.getUserMedia文档](https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FAPI\u002FNavigator\u002FgetUserMedia)\n- [MDN上的MediaDevices.getUserMedia文档](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FMediaDevices\u002FgetUserMedia)\n- [MDN上的MediaStream文档](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FMediaStream)\n- [MDN上的MediaRecorder文档](https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FAPI\u002FMediaRecorder)\n- [W3C Media Capture and Streams规范（发布候选状态）](https:\u002F\u002Fwww.w3.org\u002FTR\u002Fmediacapture-streams\u002F)\n- [W3C MediaRecording规范（Working Draft草稿状态）](https:\u002F\u002Fw3c.github.io\u002Fmediacapture-record\u002FMediaRecorder.html)\n- [W3C webrtc规范（Working Draft草稿状态）](http:\u002F\u002Fw3c.github.io\u002Fwebrtc-pc\u002F)\n- [webrtc官方网站](https:\u002F\u002Fwebrtc.github.io)\n- [教程：webrtc入门](https:\u002F\u002Fcodelabs.developers.google.com\u002Fcodelabs\u002Fwebrtc-web\u002F)\n- [文章：真实世界中的webrtc](http:\u002F\u002Fwww.html5rocks.com\u002Fen\u002Ftutorials\u002Fwebrtc\u002Finfrastructure\u002F)\n","\u002Farticle\u002Fcapture_video_on_web.html",null,0,"2026-08-28 04:37:17","published","\u003Cp>最近在某个需求的评审会上，产品同学脑洞大开，提出了\u003Cstrong>使用web录制视频\u003C\u002Fstrong>的想法。并兴致勃勃地说“看，XXX网站可以调用摄像头，还能聊天呢！”本着负（Zhuang）责（Bi）的原则，我们也对该方案做了认真的预研。大致结论：\u003C\u002Fp>\n\u003Col>\n\u003Cli>非实时录制时（文件上传框），兼容性相对较好，且API和性能稳定\u003C\u002Fli>\n\u003Cli>实时录制视频在Chrome for Android中可行，其它机型和浏览器均不可使用。考虑到相关标准仍处于不稳定状态，不建议在产品中使用\u003C\u002Fli>\n\u003Cli>微信有非公开接口可以调用实时视频录制（微证券使用）\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>详细方案如下：\u003C\u002Fp>\n\u003Ch2>方案一：使用文件上传框\u003C\u002Fh2>\n\u003Cp>文件上传框\u003Ccode>&lt;input type=&quot;file&quot;&gt;\u003C\u002Fcode>是前端同学非常熟悉的一个HTML控件，它的主要作用是用来上传文件。而在移动端，这个文件上传框被赋予了更多的使命，除了可以选择文件上传之外，还可以调用摄像头来拍摄照片或者视频并上传。\u003C\u002Fp>\n\u003Cp>具体的使用方式：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;input type=&quot;file&quot; accept=&quot;video\u002F*&quot;\u002F&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>或者\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;input type=&quot;file&quot; accept=&quot;video\u002Fmp4,video\u002Fx-m4v,video\u002F*&quot;\u002F&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这两种写法的区别在于对不同机型来说兼容性可能略有区别，但是具体的情况未做一一测试总结。经过初步测试，该方案可以在以下环境中运行：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Android 4.4+\u003C\u002Fli>\n\u003Cli>iOS 6.0+\u003C\u002Fli>\n\u003Cli>微信webview\u003C\u002Fli>\n\u003Cli>Chrome for Android\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cblockquote>\n\u003Cp>注：该兼容性列表是我们简单测试一部分机器后的结论，不做任何保证。事实上我们也碰到一部分Android机器是例外。下文兼容性列表同理。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>该方案API简单易用，且功能由浏览器或webview原生实现，性能比较稳定。\u003C\u002Fp>\n\u003Cp>该方案缺点：非实时录制视频，无法确定用户是录制的还是选取的已有的视频文件。\u003C\u002Fp>\n\u003Cp>相关demo \u003Ca href=\"http:\u002F\u002Fcodepen.io\u002FTooBug\u002Fembed\u002FRRZQxr\u002F\">http:\u002F\u002Fcodepen.io\u002FTooBug\u002Fembed\u002FRRZQxr\u002F\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2>方案二：视频录制\u003C\u002Fh2>\n\u003Cp>要使用web录制视频，需要两个相关API，一个用于调用摄像头，一个用于录制。调用摄像头后会产生一个视频流，然后调用录制API将这个视频流压缩和保存。\u003C\u002Fp>\n\u003Cp>其中调用摄像头的API叫作\u003Ccode>getUserMedia()\u003C\u002Fcode>，以前属于\u003Ccode>navigator\u003C\u002Fcode>对象（Chrome 21-49），后来规范修改，现在属于\u003Ccode>MediaDevices\u003C\u002Fcode>（Chrome 49+）。该API还负责提示用户授权。\u003C\u002Fp>\n\u003Cp>视频流叫作\u003Ccode>MediaStream\u003C\u002Fcode>。拿到\u003Ccode>MediaStream\u003C\u002Fcode>后，可配合\u003Ccode>ObjectURL\u003C\u002Fcode>，产生一个虚拟URL，供浏览器\u003Ccode>video\u003C\u002Fcode>标签调用，实现视频回放（回显）。\u003C\u002Fp>\n\u003Cp>用于录制视频的API叫作\u003Ccode>MediaRecorder\u003C\u002Fcode>。该API在Chrome 49+可用。\u003C\u002Fp>\n\u003Cp>该方案兼容性：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Chrome 49+\u003C\u002Fli>\n\u003Cli>Firefox 29+\u003C\u002Fli>\n\u003Cli>Chrome for Android\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>相关Demo地址：\u003Ca href=\"https:\u002F\u002Fsimpl.info\u002Fmediarecorder\u002F\">https:\u002F\u002Fsimpl.info\u002Fmediarecorder\u002F\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2>方案三：WebRTC视频流远程录制\u003C\u002Fh2>\n\u003Cp>WebRTC是指实现web实时通信的一系列规范，一般可以通俗地理解为“P2P视频聊天”。实现这个功能依赖于上方说的摄像头调用API \u003Ccode>getUserMedia()\u003C\u002Fcode>取到\u003Ccode>MediaStream\u003C\u002Fcode>，同时还依赖一个P2P网络连接和传输的API来实现视频流数据的传输，这个API叫作\u003Ccode>RTCPeerConnection\u003C\u002Fcode>。\u003C\u002Fp>\n\u003Cp>在实际运作时，需要服务额外处理两个浏览器在P2P通信之前的Session建立相关的逻辑：\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fcapture_video_on_web\u002F1.png\" alt=\"WebRTC实际原理图\">\u003C\u002Fp>\n\u003Cp>同时，还需要服务端支持来完成浏览器在NAT等复杂网络环境中的通信“打洞”需求：\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fcapture_video_on_web\u002F2.png\" alt=\"WebRTC实际原理图\">\u003C\u002Fp>\n\u003Cp>使用该方案录制视频的原理是通过服务端模拟一个浏览器（Peer），实现相关视频流接收解码协议以及\u003Ccode>RTCPeerConnection\u003C\u002Fcode>协议。\u003C\u002Fp>\n\u003Cp>Session管理的服务端和打洞的服务端实现和维护比较麻烦，但有例可循，而模拟Peer的部分则实现过于复杂，因此，虽然该方案理论上可行，且浏览器兼容性稍好，但仍然认为该方案在实际操作中不可行。\u003C\u002Fp>\n\u003Cp>这个方案的兼容性\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Firefox 17+\u003C\u002Fli>\n\u003Cli>Chrome 21+\u003C\u002Fli>\n\u003Cli>Edge 12+\u003C\u002Fli>\n\u003Cli>Chrome for Android\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>方案四：截图上传\u003C\u002Fh2>\n\u003Cp>该方案原理：在使用\u003Ccode>getUserMedia()\u003C\u002Fcode>获取视频流之后，将该视频流定时投映到一张2d画布中（\u003Ccode>canvas\u003C\u002Fcode>），然后将画布中的画面提取成图片数据（\u003Ccode>base64\u003C\u002Fcode>）。\u003C\u002Fp>\n\u003Cp>该方案原理比较简单，兼容性\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Firefox 17+\u003C\u002Fli>\n\u003Cli>Chrome 21+\u003C\u002Fli>\n\u003Cli>Edge 12+\u003C\u002Fli>\n\u003Cli>Chrome for Android\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>但同时也有明显缺陷：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>无法获取声音数据，只能获取到图片数据\u003C\u002Fli>\n\u003Cli>需要上传后由后台转换成视频\u003C\u002Fli>\n\u003Cli>帧数多时图片可能较大，造成性能问题（比如崩溃）\u003C\u002Fli>\n\u003Cli>帧数多时图片可能较大，造成网络传输慢\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>相关文档\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FAPI\u002FNavigator\u002FgetUserMedia\">MDN上的navigator.getUserMedia文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FMediaDevices\u002FgetUserMedia\">MDN上的MediaDevices.getUserMedia文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FMediaStream\">MDN上的MediaStream文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FAPI\u002FMediaRecorder\">MDN上的MediaRecorder文档\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.w3.org\u002FTR\u002Fmediacapture-streams\u002F\">W3C Media Capture and Streams规范（发布候选状态）\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fw3c.github.io\u002Fmediacapture-record\u002FMediaRecorder.html\">W3C MediaRecording规范（Working Draft草稿状态）\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"http:\u002F\u002Fw3c.github.io\u002Fwebrtc-pc\u002F\">W3C webrtc规范（Working Draft草稿状态）\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fwebrtc.github.io\">webrtc官方网站\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fcodelabs.developers.google.com\u002Fcodelabs\u002Fwebrtc-web\u002F\">教程：webrtc入门\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"http:\u002F\u002Fwww.html5rocks.com\u002Fen\u002Ftutorials\u002Fwebrtc\u002Finfrastructure\u002F\">文章：真实世界中的webrtc\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n","\u003Cp>最近在某个需求的评审会上，产品同学脑洞大开，提出了\u003Cstrong>使用web录制视频\u003C\u002Fstrong>的想法。并兴致勃勃地说“看，XXX网站可以调用摄像头，还能聊天呢！”本着负（Zhuang）责（Bi）的原则，我们也对该方案做了认真的预研。大致结论：\u003C\u002Fp>\n\u003Col>\n\u003Cli>非实时录制时（文件上传框），兼容性相对较好，且API和性能稳定\u003C\u002Fli>\n\u003Cli>实时录制视频在Chrome for Android中可行，其它机型和浏览器均不可使用。考虑到相关标准仍处于不稳定状态，不建议在产品中使用\u003C\u002Fli>\n\u003Cli>微信有非公开接口可以调用实时视频录制（微证券使用）\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>详细方案如下：\u003C\u002Fp>\n","https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fcapture_video_on_web\u002F1.png",{"total":23,"totalRoots":24,"comments":25,"pv":16},2,1,[26,34],{"id":27,"content":28,"user_id":29,"nick":30,"link":31,"date":32,"rid":16,"vote_up":16,"vote_down":16,"visible":33},142,"\u003Cp>还有种靠谱的方法 用 截图然后用 图片diff算法 只传 改变的部分. 用websocket传输.\u003Cbr>在某开源浏览器vnc实现下看到.\u003C\u002Fp>",11,"巫书轶","","2016-10-14 17:25:43",true,{"id":35,"content":36,"user_id":23,"nick":37,"link":31,"date":38,"rid":27,"vote_up":16,"vote_down":16,"visible":33},143,"\u003Cp>嗯。是一种思路。但是这里同样需要考虑性能的问题。图片的diff是比较耗内存和CPU的，移动端的机器能否受得了是个问题。之前试过纯js做jpeg压缩（只有算，没有canvas的那种压缩），iOS上随便一张图就要20多s了，有一种随时会崩溃的感觉。\u003C\u002Fp>","TooBug","2016-10-17 01:56:45"]