第 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 版权所有