WebRTC 录制视频流
作者:追风剑情 发布于:2024-1-8 14:50 分类:Unity3d
录制媒体流
const mediaRecorder = new MediaRecorder(stream[, options]);
参数: stream,MediaStrem 对象,录制源; options,类型为 MediaRecorderOptions 的可选参数
MediaRecorderOptions 属性说明 | |
属性 | 说明 |
mimeType |
指定录制流的编码格式 调用 MediaRecorder.isTypeSupported()方法检查当前浏览器是否支持指定的编码格式。如果当前浏览器不支持指定的编码格式,则该构造函数抛出异常 NotSupportedError |
audioBitsPerSecond | 指定录制流的音频码率 |
videoBitsPerSecond | 指定录制流的视频码率 |
bitsPerSecond | 指定录制流中音视频的码率,用于替代 audioBitsPerSecond 和 videoBitsPerSecond 属性,如果这两个属性只指定了一个,则 bitsPerSecond 将替代另外一个 |
audioBitrateMode | 指定音频码率模式,取值为 cbr 或 vbr。cbr 指以固定码率进行编码,vbr 指以可变码率进行编码 |
如果没有指定录制流的码率,则默认视频码率为 2.5Mbps,音频码率取决于采样率和通道数。
如下面代码清单所示,创建录制流,指定的视频编码格式是 mp4,如果创建成功则返回 MediaRecorder 对象,创建失败则打印错误信息并返回 null。
function getRecorder(stream) {
const options = {
audioBitsPerSecond : 128000,
videoBitsPerSecond : 2500000,
mimeType : 'video/mp4'
}
let mediaRecorder = null;
try {
mediaRecorder = new MediaRecorder(stream,options);
} catch(e) {
console.error('Exception while creating MediaRecorder: ' + e);
}
return mediaRecorder;
}
MediaRecorder 属性
1.mimeType 只读
返回构造 MediaRecorder 对象时指定的 MIME 编码格式,如果在构造时未指定,则返回浏览器默认使用的编码格式,类型为字符串。
下面代码清单调用 getUserMedia 方法获取音视频流,并指定 mp4 编码格式进行录制。
if (navigator.mediaDevices) {
console.log('getUserMedia supported.');
const constraints = { audio: true, video: true };
const chunks = [];
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
const options = {
audioBitsPerSecond: 128000,
videoBitsPerSecond: 2500000,
mimeType:'video/mp4'
}
const mediaRecorder = new MediaRecorder(stream,options);
console.log(mediaRecorder.mimeType);
}).catch(error => {
console.log(error.message);
});
}
2.state 只读
返回 MediaRecorder 对象的当前状态,类型为 RecordingState。
RecordingState 属性说明 | |
属性 | 说明 |
inactive | 没有进行录制,原因可能是录制没有开始或者已经停止 |
recording | 录制正在进行 |
paused | 录制已开始,当前处于暂停状态 |
下面的代码清单在 onclick 事件的处理函数中启动录制并打印录制的状态
record.onclick = () => {
mediaRecorder.start();
console.log(mediaRecorder.state);
}
3.stream 只读
返回构造 MediaRecorder 对象时指定的媒体流对象,类型为 MediaStream。
4.videoBitsPerSecond 只读
返回当前的视频码率,可能与构造时指定的码率不同,类型为数值。
5.audioBitsPerSecond 只读
返回当前的音频码率,可能与构造时指定的码率不同,类型为数值。
5.audioBitrateMode 只读
返回音频轨道的码率模式,类型为 BitrateMode。
BitrateMode 的枚举值 | |
枚举值 | 说明 |
cbr | cbr指以固定码率进行编码。 |
vbr | vbr指以可变码率进行编码。 |
MediaRecorder 方法
1.isTypeSupported() 静态方法
检查当前浏览器是否支持指定的 MIME 格式。
const canRecord = MediaRecorder.isTypeSupported(mimeType)
参数: mimeType,MIME 媒体格式。
返回值: 类型为 Boolean,如果支持该 mimeType 则返回 true,否则返回 false。
下面的代码清单检测 types 数组中的 mimeType,如果当前浏览器支持此 mimeType,则打印 YES,如果不支持则打印 NO。
const types = [ "video/webm",
"audio/webm",
"video/webm\;codecs=vp8",
"video/webm\;codecs=daala",
"video/webm\;codecs=h264",
"audio/webm\;codecs=opus",
"video/mpeg"];
for (let i in types) {
console.log("Is "+ types[i] + " supported? "+(MediaRecorder.isTypeSupported(types[i]) ? "YES” : "NO"));
}
2.requestData() 方法
该方法触发 dataavailable 事件,事件包含 Blob 格式的录制数据。该方法通常需要周期性调用。
mediaRecorder.requestData()
参数: 无。
返回值: 无。如果 MediaRecorder.state 不是 recording,将抛出异常 InvalidState。
如下代码清单所示,每秒调用一次 requestData() 方法,并在 dataavailable 事件处理函数中获取录制数据。
this.mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
this.recordedChunks .push(event.data);
}
};
this.recorderIntervalHandler = setInterval(() => {
this.mediaRecorder.requestData();
}, 1000);
3.start(timeslice) 方法
启动录制,将录制数据写入 Blob 对象。
mediaRecorder.start(timeslice)
参数: timeslice,可选参数,用于设置录制缓存区时长,单位为毫秒(ms)。如果指定了 timeslice,当 Blob 缓存区写满后,触发 dataavailable 事件,并重新创建一个 Blob 对象。如果未指定 timeslice,则录制数据会始终写人同一个 Blob 对象,直到调用 requestData()方法才会重新创建新的 Blob 对象。
返回值:无。如果调用出错,会抛出异常。
start 异常说明 | |
异常 | 说明 |
InvalidModificationError | 录制源的媒体轨道发生了变化,录制时不能添加或删除媒体轨道 |
InvalidStateError | MediaRecorder 当前状态不是 inactive |
NotSupportedError | 媒体源处于 inactive 状态,或者媒体轨道不可录制 |
SecurityError | 媒体流不允许录制 |
UnknownError | 其他未知错误 |
下面的代码清单启动录制,并将 Blob 缓存区设置为 100ms,缓存区满后触发 dataavailable 事件。
recorder.ondataavailable = (event) => {
console.log(' Recorded chunk of size ' + event.data.size +"B");
recordedChunks.push(event.data);
};
recorder.start(100);
4.MediaRecorder.pause() 方法
暂停录制。当调用该方法时,浏览器将产生如下行为。
- 如果 MediaRecorder.state 的状态为 inactive,则抛出异常 InvalidStateError,不再执 行下面的步骤。
- 将 MediaRecorder.state 设置为 paused。
- 停止向 Blob 追加数据,等待录制恢复。
- 触发 pause 事件。
- 参数: 无。
- 返回值: 无。
5.MediaRecorder.resume() 方法
恢复录制。当调用该方法时,浏览器会产生如下行为。
- 如果 MediaRecorder.state 的状态为 inactive,则抛出异常 InvalidStateError,不再执 行下面的步骤。
- 将MediaRecorder.state 设置为 recording。
- 继续向 Blob 追加数据。
- 触发 resume 事件。
- 参数: 无。
- 返回值: 无。
下面的代码清单展示了暂停/恢复状态的切换。
pause.onclick = () =< {
if(MediaRecorder.state === "recording") {
//暂停录制。
mediaRecorder.pause();
} else if (MediaRecorder.state === "paused") {
//恢复录制
mediaRecorder.resume();
}
}
MediaRecorder 事件
1.start 事件
当调用 MediaRecorder.start() 方法时触发该事件。此时启动录制,录制数据开始写人 Blob,对应事件句柄 onstart。
以下两种语法都可以为 start 事件设置处理函数。
MediaRecorder.onstart = (event) => { ... }
MediaRecorder.addEventListener('start', (event) => { ... })
下面的代码清单启动录制,并在 onstart 事件句柄中处理录制数据。
record.onclick = () => {
mediaRecorder.start();
console.log("recorder started");
}
mediaRecorder.onstart = () => {
//start事件处理流程
}
2.pause 事件
当调用 MediaRecorder.pause() 方法时触发该事件。此时暂停录制数据,对应事件句柄 onpause。
以下两种语法都可以为 pause 事件设置处理函数。
MediaRecorder.onpause = (event) => { ... }
MediaRecorder.addEventListener('pause', (event) => { ... })
下面的代码清单在 onclick 事件中切换录制状态并在相应的事件句柄中输出日志。
pause.onclick = () => {
if (mediaRecorder.state === "recording") {
mediaRecorder.pause();
} else if (mediaRecorder.state === "paused") {
mediaRecorder.resume();
}
}
mediaRecorder.onpause = () => {
console.log("mediaRecorder paused!");
}
mediaRecorder.onresume = () => {
console.log("mediaRecorder resumed!");
}
3.resume 事件
当调用 MediaRecorderresume() 方法时触发该事件。此时由暂停恢复录制,对应事件句柄 onresume。
以下两种语法都可以为 resume 事件设置处理函数。
MediaRecorder.onresume = (event) => { ... }
MediaRecorder.addEventListener('resume', (event) => { ... })
4.stop 事件
当调用 MediaRecorder.stop() 方法或媒体流中止时触发该事件。此时停止录制数据,对 应事件句柄 onstop。
以下两种语法都可以为 stop 事件设置处理函数。
MediaRecorder.onstop = (event) => { ... }
MediaRecorder.addEventListener('stop', (event) => { ... })
下面的代码清单在 ondataavailable 事件句柄中将录制的数据保存到 chunks 数组,当录制 停止时,使用 chunks 生成音频地址,回放录制的数据。
mediaRecorder.onstop = (e) => {
console.log("data available after MediaRecorder.stop() called.");
let audio = document.createElement ('audio');
audio.controls = true;
const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' ));
const audioURL = window.URL.createObjectURL(blob);
audio.srcobject = audioURL;
console.log("recorder stopped");
}
mediaRecorder.ondataavailable = (e) => {
chunks.push(e.data);
}
5.dataavailable 事件
该事件用于处理录制数据,对应事件句柄 ondataavailable,以下情况会触发该事件。
- 媒体流终止,导致获取不到媒体数据。
- 调用了 MediaRecorder.stop() 方法,将所有未处理的录制数据写入 Blob,停止录制。
- 调用了 MediaRecorder.requestData() 方法,将所有未处理的录制数据写入 Blob,继续录制。
- 如果在调用 MediaRecorder.start() 方法时传人了参数 timeslice,则每隔 timeslice (单位毫秒)触发一次该事件。
以下两种语法都可以为 dataavailable 事件设置处理函数。
MediaRecorder.ondataavailable = (event) => { ... }
MediaRecorder.addEventListener('dataavailable', (event) => { ... })
6.error 事件
在创建录制对象或录制过程中出现错误时触发该事件,事件类型为 MediaRecorderErrorEvent,对应事件句柄 onerror。
以下两种语法都可以为 error 事件设置处理函数。
MediaRecorder.onerror = (event) => { ... }
MediaRecorder.addEventListener('error', (event) => { ... })
下表列出了该事件触发时的错误名,错误名可以通过 MediaRecorderErrorEvent.error.name 获取。
MediaRecorder 错误名 | |
错误名 | 说明 |
InvalidStateError | 在活跃状态调用了 start() 方法、resume() 方法以及在不活跃状态调用了 stop() 方法和 pause() 方法都会导致该错误 |
SecurityError | 因为安全问题,该媒体流不允许被录制。比如使用 getUserMedia() 获取媒体流时,用户未通过授权 |
NotSupportedError | 不支持传人 MIME 格式 |
UnknownError | 其他未知错误 |
下面的代码清单实现了录制流函数 recordStream,在该函数中启动录制,保存录制数据并在出错时打印错误信息。
function recordstream(stream) {
let bufferList = [];
let recorder = new MediaRecorder(stream);
recorder.ondataavailable = (event) => {
bufferList.push(event.data);
};
recorder.onerror = (event) => {
let error = event .error;
switch (error.name) {
case InvalidstateError:
console.log("You can't record the video right now. Try again later.");
break;
case SecurityError:
console.log("Recording the specified source is not allowed due to securityrestrictions.");
break;
default:
console.log("A problem occurred while trying to record the video.");
break;
}
};
recorder.start(100);
return recorder;
}
标签: Unity3d
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号