Common getUserMedia() Errors 解决

袁志蒙 2701次浏览

摘要:HTML5的getUserMedia API为用户提供访问硬件设备媒体(摄像头、视频、音频、地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览...

HTML5的getUserMedia API为用户提供访问硬件设备媒体(摄像头、视频、音频、地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件下访问硬件媒体设备。 

getUserMedia API最初是navigator.getUserMedia,目前已被最新Web标准废除,变更为navigator.mediaDevices.getUserMedia(),但浏览器支持情况不如旧版API普及。 

MediaDevices.getUserMedia()方法提示用户允许使用一个视频和/或一个音频输入设备,例如相机或屏幕共享和/或麦克风。如果用户给予许可,就返回一个Promise对象,MediaStream对象作为此Promise对象的Resolved[成功]状态的回调函数参数,相应的,如果用户拒绝了许可,或者没有媒体可用的情况下PermissionDeniedError或者NotFoundError作为此Promise的Rejected[失败]状态的回调函数参数。注意,由于用户不会被要求必须作出允许或者拒绝的选择,所以返回的Promise对象可能既不会触发resolve也不会触发 reject。

在你的getUserMedia()开始运行的那一瞬间,就会可能会遇到各种各样的错误:

1. 用户没有摄像头,只有一个麦克风

2. 用户(不小心地)拒绝了浏览器的使用摄像头请求

3. 用户在你的getUserMedia()代码已经初始化之后才将摄像头/麦克风插到电脑上

4. 媒体设备已经被其他的应用所占用了

5. 只针对Firefox:设备已经被Firefox浏览器的其他标签页所占用了


为了解决这些状况,在管理getUserMedia()的媒体捕捉和流规范中定义了几种你可以在代码中处理的错误。

下图列出了几种最常见的错误。在Firefox和Chrome中错误的名称有所不同。规范中还有对AboutError和SecurityError的定义,但是永远触发不了它们。

Common getUserMedia() Errors 解决

NotFoundError


这个问题真的是非常常见,当你通过约束请求一个视频轨道但是用户没有摄像头的时候,这个错误就会出现。还有,当你请求一个音频/麦克风轨道的时候,但是电脑/设备并没有声卡或者录音设备被系统禁用的时候也会出现这个错误。但是这种情况比较罕见。

Common getUserMedia() Errors 解决


Firefox会弹出一个MediaStreamError,其名称属性为“NotFoundError”并显示消息“无法找到该对象”。

Chrome会出现一个NavigatorUserMediaError,其名称属性为“DevicesNotFoundError”。


NotReadableError


这种情况会在Windows系统上发生,当浏览器想要使用网络摄像头或者麦克风的时候却发现他们已经被使用了(比如说Skype正在用)。在Windows上这个错误很常见,因为进程可以独占摄像头的访问权。除了Firefox,它不会在macOS上出现因为mac系统允许几个进程共享摄像头/麦克风的使用权限。


在Windows系统上,Firefox会在其他应用或者Firefox标签页正在使用摄像头或者麦克风的时候弹出这个错误。这个错误类型是MediaStreamError,名称属性被设置为“NotReadableError”,消息属性被设置为“未能分配视频源”。

Windows系统上的Chrome浏览器会弹出一个NavigarUserMediaError,其名称属性被设为“TrackStartError”,非规范的Chrome特定版本,没有消息提示。不同的Chrome标签页可以共享同一个摄像头。

在mac系统上,这个错误只有在Firefox不止一个标签页尝试获取摄像头和麦克风的时候出现。会提示一个消息“当前麦克风进程受限”。


OverconstrainedError


当你请求一个无法用硬件满足的约束时会出现在这个错误,举个例子,当使用min或者exact关键词请求一个比较高的帧速率或者高的分辨率的时候就会出现此错误。

Firefox会提出一个MediaStreamError,其名称属性被设为“OverconstrainedError”。

Chrome会弹出一个NavigatorUserMediaError,其名称属性设为“ConstraintNotSatisfiedErrror”,一个非规范的Chrome特定版本。

Chrome和Firefox会返回请求的分辨率,或者当使用了ideal值的时候返回一个最接近的分辨率,但是如果你开始使用的是min关键字并赋予了比较大的值,或者exact关键字含有不支持的值,你就会立即触发这个错误。

错误项还会通过constraintName属性提醒你约束无法满足,并且会弹出消息“约束无法满足”。


NotAllowedError


当用户拒绝(或者之前拒绝过)摄像头或者麦克风的使用请求时就会出现这个错误。

Firefox会出现MediaStreamError,名称属性设置为“NotAllowedError”,以及弹出消息“用户代理或者当前平台不允许该请求”。

Chrome会出现NavigatorUserMediaError,其名称属性设为“PermissionDeniedError”。


TypeError


当传递给getUserMedia()的约束对象为空或者将所有轨道(音轨,视频轨,或者两者)被设置为false的时候就会出现这个问题。

Firefox会提出MediaStreamError,其名称属性设置为“TypeError”,以及一个消息“音频和/或视频被请求”。

Chrome会出现一条“TypeError:无法在‘MediaDevices’上执行‘getUserMedia’:必须至少请求一个音频和视频”。

解决这些错误,使用基于新的promise的getUserMedia()处理这些错误就很简单了,以使用下面的代码:

// 兼容性检测
function is_supported_get_userMedia() {
	navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
	constraints = { audio: false, video: {width: { ideal: 470 },height: { ideal: 470 }} };
	if (navigator.getUserMedia) {
		navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
			var mediaStreamTrack;
			mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
			mediaStreamTrack && mediaStreamTrack.stop();
		}).catch(function (err) {
			if (err.name == 'NotFoundError' || err.name == 'DevicesNotFoundError'){
				is_supported_userMedia = USERMEDIA_MAP.without_camera;
			} else if(err.name == 'NotReadableError' || err.name == 'TrackStartError'){
				is_supported_userMedia = USERMEDIA_MAP.already_used;
			} else if(err.name == 'OverconstrainedError' || err.name == 'ConstraintNotSatisfiedErrror'){
				is_supported_userMedia = USERMEDIA_MAP.error_constraint;
			} else if(err.name == 'NotAllowedError' || err.name == 'PermissionDeniedError'){
				is_supported_userMedia = USERMEDIA_MAP.not_forbidden;
			} else if(err.name == 'TypeError' || err.name == 'TypeError'){
				is_supported_userMedia = USERMEDIA_MAP.empty_constraint;
			}
			isPlay = false;
		});
	} else {
		is_supported_userMedia = USERMEDIA_MAP.not_suppeort;
		isPlay = false;
	}
};

function check_network_protocol_support() {
	is_supported_get_userMedia();
	if (is_supported_userMedia == USERMEDIA_MAP.not_suppeort) {
		video.pause();
		layer.alert('请使用谷歌(Chrome)或火狐(Firefox)浏览器', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.without_camera) {
		video.pause();
		layer.alert('当前设备未安装网络摄像头', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.already_used) {
		video.pause();
		layer.alert('摄像头或者麦克风已经被占用', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.error_constraint) {
		video.pause();
		layer.alert('太高的帧速率或者高的分辨率', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.not_forbidden) {
		video.pause();
		layer.alert('用户拒绝(或者之前拒绝过)摄像头或者麦克风的使用权限', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.empty_constraint) {
		video.pause();
		layer.alert('当传递给getUserMedia()的约束对象为空或者将所有轨道', { icon: 5 });
		return false;
	} else if (is_supported_userMedia == USERMEDIA_MAP.unknown) {
		video.pause();
		layer.alert('未知错误', { icon: 5 });
		return false;
	}
	return true;
};


随机内容

表情

共2条评论
  • 网友评论:

    网友 : 大神,官网怎么打不开了呢,还在继续开发吗,特别喜欢这个系统,简洁流畅,希望继续加油啊。 管理员:放心吧,yzmcms系统一直在更新

    2020-12-30 22:50:33 回复

    点击加载
  • 网友评论:

    大神,官网怎么打不开了呢,还在继续开发吗,特别喜欢这个系统,简洁流畅,希望继续加油啊。

    2020-12-28 11:56:00 回复

    点击加载