一、媒体设备
1.1 摄像头
webrtc使用getUserMedia
获取摄像头和话筒对应的媒体流
const Promise = navigator.mediaDevices.getUserMedia(constraints);
参数:constraints,这是一个MediaStreamConstraints对象,指定了获取媒体流的约束需求
返回值:promise,如果方法调用成功则得到一个MediaStream对象。如果调用失败,则抛出DOMException异常
异常说明
- NotAllowedErrot: 请求的媒体源不能使用,以下情况会返回该错误:
- 当前页面内容不安全,没有使用HTTPS
- 没有通过用户授权
- NotFoundError: 没有找到指定的媒体通道
- NoReadableError: 访问硬件设备出错
- OverconstrainedError: 不能满足指定的约束,错误对象包含constraint属性,用于指明不能满足的属性名称
- SecurityError: Document对象禁用了媒体支持
- AbortError: 用户已授权,但是因为其他原因导致访问硬件失败
实例
const constraints = {
audio: true,
video: {width: 1280, height: 720}
};
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
const video = document.querySelector('video');
video.srcObject = stream;
video.onloadedmetadata = (e) => {
video.play();
};
})
.catch((err) =>{
console.log(err.name + ":" + err.message);
});
1.2 共享屏幕
var promise = navigator.mediaDevices.getDisplayMedia(constraints);
参数:constraints,可选参数,MediaStreamConstraints约束对象,用于指定共享屏幕的约束需求。
返回值:pomise,如果调用成功则得到媒体流;如果调用失败,则返回一个DOMEx-ception对象
屏幕共享有可能泄漏用户隐私,处于安全考虑,webrtc规定:
- 每次调用getDisplayMedia方法都要弹出授权提示框,如果通过了授权,则不保存授权状态。
- getDisplayMedia方法必须由用户触发,且当前的document上下文处于激活状态。
异常说明
- InvalidStateError: 由于用户操作(例如事件处理程序)而运行的代码未调用。此事件的另一个潜在原因:
document
在其上下文中getDisplayMedia()
被调用的未完全激活;例如,它可能不是最前面的选项卡。 - NotAllowedError: 用户拒绝访问屏幕区域的权限,或者当前浏览实例无权访问屏幕共享。
- NotFoundError: 没有可供捕获的屏幕视频源。
- NotReadableError: 用户选择了一个屏幕、窗口、选项卡或其他屏幕数据源,但发生了硬件或操作系统级别的错误或锁定,从而阻止了所选源的共享。
- OverconstrainedError: 创建流后,应用指定
constraints
失败,因为无法生成兼容的流。 - TypeError:
constraints
调用时不允许指定的包含约束getDisplayMedia()
。这些不受支持的约束是advanced
和任何约束,这些约束 又具有名为min
or的成员exact
。 - AbortError: 其他失败情况
实例
async function startCapture(displayMediaOption) {
let captureStream = null;
try {
captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
}catch(err) {
console.error("Error:" + err);
}
return captureStream;
}
1.3 查询媒体设备
说明
var enumeratorPromise = navigator.mediaDevices.enumerateDevices();
返回值:enumeratorPromise,如果调用成功则得到一个包含成员MediaDevicesInfo的数组,该数组列出了所有可用的媒体设备;如果调用失败,则得到空值。MediaDevicesInfo的定义如下所示
定义
interface MediaDeviceInfo {
readonly deviceId: string;
readonly groupId: string;
readonly kind: MediaDeviceKind;
readonly label: string;
toJSON(): any;
}
declare var MediaDeviceInfo: {
prototype: MediaDeviceInfo;
new(): MediaDeviceInfo;
};
type MediaDeviceKind = "audioinput" | "audiooutput" | "videoinput";
MediaDeviceInfo属性说明
属性 | 类型 | 说明 |
---|---|---|
deviceId | DOMString | 设备ID |
groupId | DOMString | 组ID |
label | DOMString | 设备的描述信息,如”Full HD webcam (1bcf:2284)” |
kind | MediaDeviceKind | 设备类型,取值为videoinput (视频输入设备)、audioinput (音频输入设备)、audiooutput (音频输出设备) |
使用实例
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("enumerateDevices() not supported.");
return;
}
// List cameras and microphones.
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device.kind + ": " + device.label +
" id = " + device.deviceId);
});
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
找出所有摄像头
function getConnectedDevice(type, callback) {
navigator.mediaDevices.enumerateDevices()
.then(devices => {
const filtered = devices.filter(device => device.kind === type);
callback(filtered);
})
}
getConnectedDevices('videoinput', cameras => console.log('Cameras found', cameras));
1.4 监听媒体设备变化
为了在应用程序中监测媒体设备的变化,WebRTC提供了devicechange事件和ondevicec-hange事件句柄,与navigator.mediaDevices结合即可实时监控媒体设备的热插拔。
使用方法
// 1. 使用addEventListener监听事件
navigator.mediaDevices.addEventListener('devicechange', (event) => {
updateDeviceList();
})
//2.使用ondevicechange事件句柄
navigator.mediaDevices.ondevicechange = (event) => {
updateDeviceList();
}
更新所有摄像头
function updateCameraList(cameras) {
const listElement = document.querySelector('select#availableCameras');
listElement.innerHTML = '';
cameras.map(camera => {
const cameraOption = document.createElement('option');
cameraOption.label = camera.label;
cameraOption.value = camera.deviceId;
}).forEach(cameraOption => listElement.add(cameraOption));
}
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type);
}
//获取初始状态摄像头
const videoCameras = getConnectedDevices('videoinput');
updateCameraList(videoCameras);
// 监听事件并更新设备
navigator.mediaDevices.addEventListener('devicechange', event => {
const newCameraList = getConnectedDevices('videoinput');
updateCameraList(newCameraList);
});
1.5 从canvas获取媒体流
二、媒体约束
媒体约束是指媒体某一项技术特性,如分辨率、帧率等;媒体能力是当前设备能够支持的某个约束的量化指标,如帧率最高30;
媒体约束设定值是指包含了浏览器默认设定值的所有媒体约束。
-
MediaDevices.getSupportedConstraints:获取当前浏览器支持的约束数组。
-
MediaStreamTrack.getCapabilities:有了支持的约束数组,使用该方法获取这些约束的取值范围。
-
MediaStreamTrack.applyConstraints:根据应用程序的需要,调用该方法为约束指定自定义的值。
-
MediaStreamTrack.getConstraints:获取上述applyConstraints()方法传入的值。
-
MediaStreamTrack.getSettings:获取当前轨道上所有约束的实际值。
由于浏览器对约束的支持情况不同,并不是所有的约束所有浏览器都支持。所以在使用约束前,需要先使用方法MediaDevices.getSupportedConstraints进行检查。
let supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
if (supportedConstraints && supportedConstraints.iso) {
//iso约束存在
}
浏览器支持:https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints#properties_specific_to_shared_screen_tracks
2.1 约束类型
媒体约束包括媒体流约束(MediaStreamConstraints)和媒体轨道约束(MediaTrackConstraints)。
类型说明
类型 | 说明 | 示例 |
---|---|---|
DOMString | 字符串 | {cursor: “always”} |
ULongRange | 具有范围的整数值,可指定最大值和最小值 max: 32位整型值,指定属性的最大值 mim: 32位整型值,指定属性的最小值 |
height:{min: 240, ideal: 720, max: 1080} |
DoubleRange | 通ULongRange,但是取值为双精度浮点型 | |
ConstrainDOMString | 字符串的约束,可取值如下: 1. DOMString 2. DOMString对象数组 3. 包含exact、ideal属性的对象,exact指定一个确切值,如果浏览器不能精确匹配则返回错误,而ideal指定理想值,如果浏览器不能精确匹配,则使用最接近的值 |
facingMode:{exact:‘user’} aspectRatio: {ideal:1.77} |
ConstrainBoolean | 布尔值约束 1. true、false 2. 包含exact、ideal属性的对象 |
|
ConstrainULong | 整型约束 1. 整型 2. 包含exact、ideal属性的对象 |
width: {min: 640, ideal:1280, max:1920} |
ConstrainDouble | 浮点型约束 1. 浮点型 2. 包含exact、ideal属性的对象 |
2.1.1 媒体流约束MediaStreamConstraints
interface MediaStreamConstraints {
audio?: boolean | MediaTrackConstraints;
peerIdentity?: string;
video?: boolean | MediaTrackConstraints;
}
audio: 表示是否请求音频 eg: {audio: false}
video: 表示是否使用视频 eg:{video: false}
2.1.2 媒体轨道约束MeidaTrackConstraints
interface MediaTrackConstraints extends MediaTrackConstraintSet {
advanced?: MediaTrackConstraintSet[];
}
interface MediaTrackConstraintSet {
/通用约束
groupId?: ConstrainDOMString; //组ID
deviceId?: ConstrainDOMString; //设备ID,RTCPeerConnection关联的流不包含该越苏
/视频约束
aspectRatio?: ConstrainDouble;//视频宽高比 {aspectRatio: 16/9}
//摄像头可取值
//1. user前置摄像头
//2.environment 后置摄像头
//3. left 左侧摄像头
//4. right 右侧摄像头
//RTCPeerConnection关联的流不包含改约束
//{facingMode: 'user'}
facingMode?: ConstrainDOMString;
//帧率
//{frameRate: {ideal: 10, max: 15}}
frameRate?: ConstrainDouble;
//视频高度
//{height: 720}
height?: ConstrainULong;
//视频宽度
//{width: 1280}
width?: ConstrainULong;
// 调整视频尺寸,可取值如下:
// none:使用摄像头的原生分辨率
// crop-and-scale: 允许对视频进行剪裁
// {resizeMode: "none"}
resizeMode?: ConstrainDOMString;
/音频约束
//自动增益控制,值为true则开启,值为false则关闭
//{autoGainControl:true}
autoGainControl?: ConstrainBoolean;
//音轨数量
//1.单声道
//2.立体声
// {channelCount:2}
channelCount?: ConstrainULong;
//回音消除,true为开启,false表示关闭
//RTCPeerConnection关联的流不包含该约束
//{echoCancellation: true}
echoCancellation?: ConstrainBoolean;
// 延时,单位秒,一般延时越低越好
//RTCPeerConnection关联的流不包含该约束
// {latency: 1}
latency?: ConstrainDouble;
//降噪,true开启,false关闭
//{noiseSuppression: true}
noiseSuppression?: ConstrainBoolean;
//采样率
//{sampleRate: 44100}
sampleRate?: ConstrainULong;
//采样大小
//{sampleSize: 16}
sampleSize?: ConstrainULong;
}
// 共享屏幕
// 在流中如何显示鼠标
// always: 一直显示光标
// motion:当移动鼠标时显示光标,静止时不显示
// never: 不显示光标
// {cursor: 'always'}
cursor ConstrainDOMString
//指定用户可以选择的屏幕内容
//application:应用程序
//browser: 浏览器标签页
//monitor: 显示器
//windows: 某个应用程序窗口
//{displaySurface: 'application'}
displaySurface ConstrainDOMString
//是否开启逻辑显示面
//{logicalSurface: true}
logicalSurface ConstrainBoolean
///图像采集约束
// 白平衡模式
// 1. none关闭白平衡模式
// 2. manual开启手动控制
// 3. single-shot开启一次自动白平衡
// 4. 开启连续自动白平衡
// {whiteBalanceMode:"none"}
whiteBalanceMode ConstrainDOMString
// 曝光模式
// 1. none关闭曝光模式
// 2. manual开启手动控制
// 3. single-shot开启一次自动曝光
// 4. 开启连续自动曝光
// {exposureMode:"none"}
exposureMode ConstrainDOMString
// 聚焦模式
// 1. none关闭聚焦模式
// 2. manual开启手动控制
// 3. single-shot开启一次聚焦
// 4. 开启连续自动聚焦
// {focusMode:"manual"}
focusMode ConstrainDOMString
// 兴趣点,与上面3种模式结合使用
// { pointsOfInterest:{ x: value , y: value } }
pointsOfInterest ConstrainPoint2D
// 曝光补偿 ±3
exposureCompensation ConstrainDouble
//色温
colorTemperature ConstrainDouble
//感光度
iso ConstrainDouble
//亮度
brightness onstrainDouble
//对比度
contrast ConstrainDouble
// 饱和度
saturation CnstrainDouble
// 锐度
sharpness CnstrainDouble
// 聚焦距离
focusDistance CnstrainDouble
// 缩放
zoom CnstrainDouble
// 是否开启补光灯, true,false
torch CnstrainBoolean
2.2 使用方法
//1. 指定值
const constraints = {
width: 1280,
height: 720,
aspectRatio: 3/2
};
//2. 指定最小值和理想值
const constraints = {
frameRate: {min: 20},
width:{min: 640, ideal: 1280},
height:{min: 480, ideal: 720},
aspectRatio: 3/2
};
//3.指定最小值、理想值和最大值
const constraints = {
width: {min: 320, ideal: 1280, max: 1920},
height: {min: 240, ideal: 720, max: 1080},
}
三、媒体流(MediaStream)
媒体流一般由多个媒体轨道组成,如音频轨道、视频轨道
获取媒体流的方式:
- 从摄像头或者麦克风获取流对象。
- 从共享屏幕获取流对象。
- 从canvas(HTMLCanvasElement)内容中获取流对象。
- 从媒体元素(HTMLMediaElement)获取流对象。
定义:
interface MediaStream extends EventTarget {
readonly active: boolean;
readonly id: string;
onaddtrack: ((this: MediaStream, ev: MediaStreamTrackEvent) => any) | null;
onremovetrack: ((this: MediaStream, ev: MediaStreamTrackEvent) => any) | null;
addTrack(track: MediaStreamTrack): void;
clone(): MediaStream;
getAudioTracks(): MediaStreamTrack[];
getTrackById(trackId: string): MediaStreamTrack | null;
getTracks(): MediaStreamTrack[];
getVideoTracks(): MediaStreamTrack[];
removeTrack(track: MediaStreamTrack): void;
addEventListener<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
四、RTCPeerConnection
RTCPeerConnection
接口代表一个由本地计算机到远端的WebRTC连接。该接口提供了创建,保持,监控,关闭连接的方法的实现。
4.1 属性
以下属性均为只读属性:
- canTrickleIceCandidates: 如果远端支持UDP打洞或支持通过中继服务器链接则该属性为true,该属性的值依赖于远端设置且仅在本地RTCPeerConnection.setRemoteDescription被调用时有效,如果该方法没被调用,则其值为null。
- connectionState: 返回对等连接的状态,其值为:new、connecting、connected、disconnected、failed、closed。
- currentLocalDescription: 返回一个连接本地端的RtcSessionDescription对象,包括可能由ICE代理生成的任何ICE候选者的列表。
- currentRemoteDescription: 返回一个连接远程端的RtcSessionDescription对象,包括可能由ICE代理生成的任何ICE候选者的列表。
- icsConnectionState: 返回RTCPeerConnection的ICE代理状态。其值为IcsConnectionState
- icsGatheringState: 返回ICE聚集状态,通过这值可以之道ICE的candidate在什么时候完成,其值可能为: new、gathering、complete。
- localDescription: 返回本地端RTCSessionDescription,如果尚未设置将会返回null。
- peerIdentity: 返回一个RTCIdentityAssertion包括域名(idp)以及一个名称,代表这条连接的远端机器的身份识别信息。如果远端机器还没有被设置以及校验,这个属性会返回null。
- pendingLocalDescription: 返回一个RTCSessionDescription对象,描述连接本地端的pending配置更改。
- pendingRemoteDescription: 返回一个RTCSessionDescription对象,描述连接远程端的pending配置更改。
- remoteDescription: 返回一个RTCSessionDescription对象,描述远程端的会话信息,包括配置和媒体信息。
- sctp: 返回一个RTCSctpTransport对象,描述SCTP传输层,通过该层发送和接受的SCTP数据。如果尚未配置SCTP则此值为null
- singlingState: 返回描述连接或重新连接到另一个对等端连接本地的信令过程状态。其值可能为:stable、hava-local-offer、have-remote-offer、have-local-pranswer、have-remote-pranswer。
最近在跟一个的免费直播,讲音视频开发,讲得不错分享给大家
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137649.html