WebRTC本地媒体——媒体捕获与控制

目录

1 媒体捕获getUserMedia

1.1 getUserMedia声明

1.2 getUserMedia内部执行的算法

1.3 简单的示例

1.4 nagevator.mediaDevices.getUserMedia undefined问题

2 媒体的控制


1 媒体捕获getUserMedia


WebRTC扩展了Navigator和MediaDevices的API,以支持向用户发出允许UA使用本地媒体输入设备的请求。其中navigator.getUserMedia是一个历史遗留的API(详述见规范Media Capture and Streams(媒体捕获与流)的10.1节);navigator.mediaDevices.getUserMedia是规范推荐应该使用的API。

1.1 getUserMedia声明


WebRTC本地媒体——媒体捕获与控制_第1张图片

  • 该API将请求用户允许使用摄像头,或其他视频、音频输入设备,在收到用户许可之前,用户代理不能返回对源的访问,而收到用户许可可能需要数秒或更长时间(用户在弹窗界面点击允许使用本地音视频输入设备)。
  • 方法入参:是一个字典类型的对象MediaStreamConstraints,其定义如下所示
    WebRTC本地媒体——媒体捕获与控制_第2张图片
    针对媒体类型音频、视频各有一个约束条件,其类型为MediaTrackConstraints字典类型或者是boolean类型。若为boolean类型时,比如针对视频,video为false,表示不需要获视频媒体;若video为true,表示需要获取视频媒体,并且不对视频流轨道施加约束。若约束的video或audio为MediaTrackConstraints类型时,表示需要获取该类型的媒体,并且需要满足MediaTrackConstraints类型所表达的约束条件。MediaTrackConstraints类型定义如下所示,将在别处对约束进行详细描述。
    WebRTC本地媒体——媒体捕获与控制_第3张图片
  • 方法返回值:方法并非直接返回MediaStream流对象,而是返回一个Promise对象。当方法找到满足约束条件的轨道,并得到用户许可使用设备时,将返回Promise对象,并执行fulfilled方法,方法携带了由满足约束条件的轨道所组成的MediaStream对象;若用户拒绝了使用媒体输入设备的请求或者未找到满足约束条件的有效轨道,那么返回Promise,并且执行rejected方法。

1.2 getUserMedia内部执行的算法


  • 当getUserMedia()被调用时,方法内部,UA将执行如下的步骤:
  1. 让约束constraints成为该方法的第一个参数;

  2. 获取请求媒体类型requestedMediaTypes集合,即入参constraints约束中video若不为false,那么requestedMediaTypes中包含video,若audio不为false,那么requestedMediaTypes包含audiotrue;

  3. 如果requestedMediaTypes是个空集,则返回Promise将rejected,并携带一个错误类型TypeError;

  4. 如果当前“设置”对象的负责文档未处于完全活动状态,则返回Promise将rejected,携带一个DOMException对象,该对象的name属性值为InvalidStateError;

  5. 创建一个新的Promise对象p;

  6. 执行如下步骤:

    1. 用户代理UA必须等待进入下一步,直到当前“设置”对象的负责文档处于完全活动状态且具有焦点;

    2. 初始化finalSet为一个空集;

    3. 对于requestedMediaTypes中的每种媒体类型(音频和视频,或者是其中的一种),执行以下步骤:

      1. 对于该媒体类型的每个可能的源,构造一个无约束轨道MediaStreamTrack以该源为关联源。将这组轨道称为候选集CandidateSet。如果CandidateSet是空集(即没找到可使用的源),则直接返回Promise,执行rejected方法携带一个DOMException对象,该对象的name属性值为NotFoundError,中止以下步骤;

      2. 如果constraints约束条件中的的音频约束或视频约束为true,那么相应的CS将设置为空约束集,否则CS设置为对应条目的值(MediaTrackConstraints类型所表达的约束);

      3. 移除CS可约束属性中不属于对应轨道类型的约束。意味CS若是针对音频轨道的约束,那么移除CS中仅作用于视频的可约束属性,同样CS若是针对视频轨道的约束,那么移除CS中仅作用于音频的可约束属性。不产生过度约束OverconstrainedError的错误;

      4. 对候选集CandidateSet中的每个轨道以CS作为约束设置,使用"SelectSttings"算法。如果算法返回未定义undefined,意味着该轨道无法满足约束条件,那么从候选集CandidateSet中移除该轨道。对所有的轨道都执行完"SelectSttings"算法后,若候选集CandidateSet为空集(意味着没有找到满足约束的轨道),跳到后面Constraint Failure步骤执行。

      5. 获取当前浏览器上下文中,CandidateSet集中没有与活动状态的轨道绑定的所有候选设备的权限(对于已经与活动轨道绑定的设备肯定已经具有了访问权限)。从CandidateSet集中移除用户权限为"denied"的设备。如果CandidateSet现在为空,意味着这个媒体类型的输入设备都是"denied"状态,跳转到后面的Permission Failure 步骤执行。

      6. 添加所有候选CandidateSet中的所有轨道到最终集finalSet。

    4.  可选地,例如,基于先前建立的用户偏好,出于安全原因,或由于平台限制,跳转到Permission Failure 步骤执行。

    5. 像用户发出使用设备的请求(一般通过浏览器的弹窗实现,提供允许与拒绝的按钮),使用PermissionDescriptor对象表征该次权限请求,其name属性为类别(camera,microphone)相关联权限请求名,chrome中一般为"使用您的摄像头","使用您的麦克风";可选的,其deviceId属性设置为设备的deviceId;考虑到在当前浏览器上下文中,已经关联到一个活动的具体同样权限的轨道的所有设备,其权限状态为"granted",那么将导致可提供媒体的一个集合。在上下文中,同样的权限意味着获取的的权限级别和请求的权限级别相同。

      提供的媒体集合必须恰好包含来自finalSet的requestedMediaTypes中每种媒体类型的一个轨道。决定从finalSet中选择哪些设备完全取决于用户代理,并且可以通过询问用户来确定。一旦选定,MediaStreamTrack的源不得更改。用户代理可以使用SelectSettings算法中计算的“适应距离”的值,或任何其他有关设备的内部可用信息,作为选择算法的输入来选择哪些设备。建议用户代理默认使用用户的主要或系统默认摄像头和/或麦克风(如果可能)来生成媒体流。用户代理可以允许用户使用任何媒体源,包括预先录制的媒体文件。

      如果请求的结果为“允许”,则对于提供媒体的每个设备,将对应的[[devicesLiveMap]] [deviceId]以及[[devicesAccessibleMap]] [deviceId]设置为true。如果用户授予权限但硬件错误(例如OS /程序/网页锁定)阻止访问,则中止后续步骤,返回Promise,执行rejected方法,并携带name属性值为NotReadableError的新DOMException对象。如果用户授予权限但设备访问由于上面列出的原因之外的任何原因而失败,则中止后续步骤,返回Promise,执行rejected方法,并携带name属性值为AbortError的新DOMException对象。如果请求的结果为“拒绝”,跳转至Permission Failure 的步骤。如果用户从未响应,则此算法在此步骤停止。

    6. 让stream成为用户授予权限的设备提供的轨道所组合成的MediaStream对象。

    7. 对stream对象中所有的轨道使用合适的约束去执行"ApplyConstraints"算法。如果对轨道应用约束失败,让failedConstraint 成为该算法失败的结果,并跳转至Constraint Failure步骤执行。

    8. 返回Promise,执行resolved方法,携带stream对象。

    9. Permission Failure: 返回Promise,执行rejected方法,携带一个新的DOMException对象,其name属性为NotAllowedError。

    10. Constraint Failure: 让message 要么是undefined,要么是一条用户可读的信息,并返回Promise,执行rejected方法,携带一个新创建的OverconstrainedError对象(该对象通过调用OverconstrainedError(failedConstraint, message)创建)。

  7. Return p.

  • 在上面的算法中,约束被检查两次 - 一次在设备选择时(执行"SelectSttings"算法),一次在访问批准之后(执行"ApplyConstraints"算法)。 在这些检查之间可能已经过了一段时间,因此可以想象所选择的设备不再适用。 在这种情况下,将导致NotReadableError。这两个算法将在WebRTC本地媒体——约束详解中详述。

1.3 简单的示例


WebRTC本地媒体——媒体捕获与控制_第4张图片

当在浏览器打开capture.html文件时,将执行如图的js代码,调用getUserMedia API。该方法将查找满足约束条件vgaConstraints的设备(无音频流,视频流满足指定的分辨率),并向用户发出请求,如下图所示

WebRTC本地媒体——媒体捕获与控制_第5张图片

在获取用户许可的情况下(点击“允许”),getUserMedia将返回Promise,执行gotStream方法,该方法的入参为一个MediaStream对象,可以直接赋值给video标签的srcObject属性,从而渲染出视频流来。

WebRTC本地媒体——媒体捕获与控制_第6张图片

1.4 nagevator.mediaDevices.getUserMedia undefined问题


通过 MediaDevices.getUserMedia() 获取用户多媒体权限时,需要注意其只工作于以下三种环境:

  • localhost 域
  • 开启了 HTTPS 的域
  • 使用 file:/// 协议打开的本地文件

其他情况下,比如在一个 HTTP 站点上,navigator.mediaDevices 的值为 undefined

如果想要 HTTP 环境下也能使用和调试 MediaDevices.getUserMedia(),可通过开启 Chrome 的相应参数。

通过相应参数启动 Chrome

传递相应参数来启动 Chrome,以 http://example.com 为例,

 --unsafely-treat-insecure-origin-as-secure="http://example.com"

开启相应 flag

通过传递相应参数来启动 Chrome Insecure origins treated as secure flag 并填入相应白名单。

  • 打开 chrome://flags/#unsafely-treat-insecure-origin-as-secure
  • 将该 flag 切换成 enable 状态
  • 输入框中填写需要开启的域名,譬如 http://example.com",多个以逗号分隔。
  • 重启后生效。

2 媒体的控制


媒体的捕获和选择通过上述的getUserMedia()方法进行,在媒体选择完毕之后,如果要对选择的轨道的可约束属性进行修改,那么就得使用轨道的applyConstraints()方法,该方法的定义如WebRTC本地媒体——媒体模型中所示。至于约束以及applyConstraints()方法中使用的算法流程可以在WebRTC本地媒体——约束详解中描述。

你可能感兴趣的:(Webrtc,Webrtc,Javascript,API)