第 11 期 - WebRTC 与 RecordRTC 在车主认证拍摄功能中的应用
摘要
文章围绕车主认证项目,阐述多端拍摄需求下存在的平台适配等问题,介绍 WebRTC 和 RecordRTC 技术,详细讲解在项目中借助二者实现拍摄功能的流程,包括初始化、拍摄、上传操作。
一、车主认证项目背景与问题
车主认证项目以 H5 形式存在多端投放,包括哈啰 App、车主 App 等。存在多端场景调用拍摄能力的需求,但面临诸多问题。
- 多平台适配:要确保拍摄功能在哈啰 App、车主 App、货运车主 App、支付宝小程序、微信小程序和 H5 外投页面等各个平台上有良好适配。
- 小程序兼容性:支付宝小程序借助自身拍摄能力,但微信小程序未提供视频拍摄方案,需解决在小程序环境下正常调用拍摄功能的问题。
- 外投页面兼容性:H5 外投页面面临不同浏览器和设备的兼容性挑战,要确保在各种浏览器中正常加载和运行。
二、WebRTC 简介
WebRTC (Web Real - Time Communications)是实时通讯技术,能建立浏览器间点对点连接,是实现实时通信的开放标准和协议。
- 核心模块
- getUserMedia:用于获取用户音频和视频流,应用场景包括视频和音频录制、视频通话等。
- RTCPeerConnection:建立点对点连接,支持音频和视频实时传输,应用于实时音视频通话等。
- RTCDataChannel:在两个对等体间传输任意数据,用于文件传输等。
- API 封装:由于 API 多样,其他贡献者做了有效封装,recordRTC 就是基于 getUserMedia API 实现媒体设备访问并封装视频流函数的一个。
三、recordRTC 简介
recordRTC 是 JavaScript 库,提供录制媒体流功能,基于 WebRTC 的 getUserMedia API。
- 主要能力
- 获取访问权限:通过 getUserMedia,recordRTC 可请求用户授予摄像头和麦克风访问权限。
- 获取媒体流:getUserMedia 返回包含实时音视频数据的媒体流对象。
- 媒体流配置:可指定获取媒体流特性,如选择摄像头、分辨率、音频输入设备等。
- 实时预览:允许获取媒体流后进行实时音视频预览。
- 动态更新媒体流:提供在运行时动态更新媒体流配置的方法。
- 支持的浏览器及常用参数:介绍了其支持的浏览器和如 type、recorderType 等常用参数。
- 方法:包括 startRecording()、stopRecording(callback)等多个方法,如 startRecording()用于启动录制过程。
四、WebRTC 拍摄具体实现
- 拍摄流程 - 安装:安装 recordrtc 库,引入 RecordRTCPromisesHandler 类。
npm install recordrtc import { RecordRTCPromisesHandler } from'recordrtc';
- 拍摄流程 - 使用:在车主认证项目中将操作 js 拍摄化封装为 video - recorder 组件,内部处理方法调用分三部分。
- 初始化:因为手机后置摄像头场景问题,初始化时获取所有后置摄像头让用户选择。通过 getVideoConstraints 方法获取后置拍摄设备配置列表。
async getVideoConstraints() { let deviceId = ''; // 只有第一次时需要遍历镜头列表 if (!this.activeCamera) { // 获取所有设备列表 const deviceList = await navigator.mediaDevices.enumerateDevices(); // 过滤出视频输入设备列表 const videoDeviceList = deviceList.filter((deviceInfo) => deviceInfo.kind === 'videoinput').reverse(); // 发送视频设备列表到父组件 this.$emit('output - list', videoDeviceList); // 遍历视频输入设备列表 for (const device of videoDeviceList) { // 获取特定设备的视频流 const stream = await navigator.mediaDevices.getUserMedia({ video: { deviceId: device.deviceId }, audio: false }); // 检查摄像头是否为环境(后置)摄像头 const isEnvironment = stream.getVideoTracks()[0].getSettings().facingMode === 'environment'; // 停止获取的视频流上的所有轨道,释放资源 stream.getTracks().forEach((track) => { track.stop(); }); // 如果是环境(后置)摄像头,则记录设备 ID,并跳出循环 if (isEnvironment) { deviceId = device.deviceId; break; } } } // 设置视频约束 const result: MediaTrackConstraints = { frameRate: { ideal: 6, max: 10 }, width: this.env.isAndroid? { ideal: 960, min: 480, max: 960 } : { ideal: 480, min: 480, max: 960 }, height: this.env.isAndroid? { ideal: 1280, min: 640, max: 1280 } : { ideal: 640, min: 640, max: 1280 }, facingMode: 'environment', deviceId: this.activeCamera? this.activeCamera.deviceId : deviceId, aspectRatio: 3 / 4 }; if (!deviceId &&!this.activeCamera) { delete result.deviceId; } // 返回视频约束 return result; }
- **拍摄**:点击录制按钮调用 recorder 对象的 startRecording 方法开启录制,开启后倒计时 5s 停止录制,获取 Blob 对象。
async record() { if (this.recorder) { await this.recorder.startRecording(); this.isRecording = true; } }
- **上传**:视频使用 aliyun 的 oss 上传,获取 Blob 对象后上传,根据返回文件名获取预览 Url 并跳转到 Ocr 识别页。
扩展阅读
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有