SuperAPI AI 工具集

media-capture-device-contracts

前端与建站

查看项目

更新于 10-16 07:46

技能介绍

用途

该技能面向浏览器摄像头或麦克风采集流程的调试与修复。它强调采集是一个会话生命周期,而不是一次性的权限检查。其契约包括:请求预期的轨道、如实呈现实际失败、在不承诺浏览器会重新弹出权限提示的前提下恢复、在不泄漏采集的情况下替换设备,以及释放页面拥有的每一条轨道。

主要能力

  • 在受支持的浏览器中,使用真实源、浏览上下文、请求约束和设备状态复现问题,并在将拒绝解释为用户拒绝之前,记录上下文是否安全以及 navigator.mediaDevices 是否存在。
  • 追踪一次从 getUserMedia() 到流附加与拆除的请求,识别每个返回轨道、克隆、事件监听器和媒体元素由哪个组件或会话拥有。
  • 对实际异常进行分类,而不是把所有失败都映射为“权限被拒绝”:先区分 API 可用性(不安全上下文可能导致 navigator.mediaDevices 不可用,需先处理缺失 API 或由此产生的 TypeError);NotAllowedError 可能表示采集被拒绝或适用的能力策略(iframe 策略失败应转交 iframe-embed-contracts);NotFoundError 表示请求的轨道类型没有匹配来源;NotReadableError 表示即使有权限也无法启动采集,包括浏览器、操作系统或硬件访问失败;OverconstrainedError 表示没有候选能满足约束,浏览器提供时应记录所报告的约束;AbortError、InvalidStateError、TypeError 等应按捕获到的浏览器证据处理,而不是重新贴标签。
  • 建模显式状态,如 idle、requesting、live、interrupted、denied、no-device、unreadable、constraints-failed 和 stopped。只有在当前流已附加且所需轨道处于 live 且未静音时才提交 live。用户可能不回答浏览器提示,因此不要把仍在等待的请求转换为拒绝;让 UI 取消或取代该尝试,然后处置任何延迟解析的流。
  • 保持恢复的真实性:拒绝后提供显式重试和准确的浏览器设置帮助,不要声称 JavaScript 能强制重新打开权限提示;对于无设备或设备移除,在目标浏览器暴露 devicechange 时使用它,在显式重试时再次协调,并让用户选择可用设备;对于不可读设备,在重试前释放会话拥有的轨道,避免告诉用户权限一定缺失;只有在产品接受回退时才放宽过度约束的请求,并报告降级模式而不是静默更改。
  • 仅在浏览器暴露相关描述符时,将 Permissions API 用作可选诊断上下文。权限查询可能拒绝或省略部分采集决策;getUserMedia() 结果和实时轨道状态仍是权威依据。
  • 将设备替换定义为明确的归属转移。不要仅仅为了预览来源而打开第二次采集,如果拥有的轨道或有意拥有的克隆能满足用例。如果替换需要新流,附加被接受的替换流,并恰好一次停止/分离旧的拥有流。如果平台无法同时打开两者,在释放旧来源时表示中断。
  • 分别处理临时和永久中断。拥有的轨道可能在其来源暂时无法提供媒体时保持 readyState === "live" 且 muted === true。静音时,将 UI 移至真实的中断状态,而不声明轨道已停止;取消静音时,仅当同一当前轨道仍被拥有、live 且未静音时才返回 live。使用 ended 事件处理来源结束路径。调用 stop() 会将 readyState 设为 ended,但不会触发该事件,因此所有者必须自行执行停止状态转换和清理。在 devicechange 后协调设备列表,不要在所需轨道静音时报告采集健康。
  • 在替换、取消、路由变化或卸载时,移除监听器、清除待处理请求的归属、分离媒体元素(页面赋值处设 srcObject = null),并对本会话拥有的每条轨道调用 stop()。如果延迟请求在处置后解析,立即停止其轨道而不是附加它们。将 mute、unmute 和 ended 处理器注册和移除为一个幂等的每轨道归属单元,以便被替换的轨道无法更新当前会话。
  • 没有归属契约时,不要停止借用的轨道。停止一条轨道会结束该轨道,但共享的摄像头或麦克风来源在另一条轨道仍使用时可能保持活动。

使用方式

该技能以检查清单、快速探针、边界划分和 PR 价值门的形式使用。快速探针包括:在每次转换时记录请求代次、约束、异常名称、所报告的约束、轨道 ID、readyState 和拥有会话,避免记录设备标签或标识符,除非调试环境允许;在采集前、设备替换后和卸载后统计拥有的 live 轨道数,最终计数必须归零;拒绝采集,从恢复 UI 重试,验证 UI 在附加 live 轨道之前从不显示摄像头处于活动状态;拔下或禁用所选设备,然后恢复或选择另一台,验证一条恢复路径且没有重复监听器或流;在不结束轨道的情况下临时中断来源,断言 readyState === "live" 且 muted === true 产生中断 UI,然后确认取消静音恢复同一当前会话而不重新获取或复制轨道;延迟 getUserMedia(),在其解析前卸载,断言延迟流被停止且从未分配给媒体元素。

适用场景

适用于前端音视频采集流程中出现的权限拒绝后仍被阻止、恢复提示不准确、设备拔出或切换时失败、组件卸载后采集仍活动、重复采集、设备争用、轨道克隆与清理等问题。

限制

该技能与相邻技能有明确边界:iframe-embed-contracts 负责父文档与访客文档之间的 allow、sandbox 和 Permissions Policy 能力委托;webview-bridge-pages 负责原生应用权限和 WebView 宿主生命周期;仅凭 getUserMedia() 拒绝不会路由到 user-activation-contracts,只有当不同的手势门控操作(如播放或全屏)失败且可信事件时序或激活消耗边界有证据时才使用该技能;录制收尾、编码块和 MediaRecorder 停止/数据事件顺序需要录制专用工作流,本技能仅负责输入轨道;通用地理定位、通知和无关权限提示不在范围内。

PR 价值门要求:需要真实的浏览器采集序列,识别所请求的媒体类型、异常或轨道转换、拥有会话以及用户可见的错误状态或泄漏资源。修复必须保持真实恢复,并为失败的拒绝、静音/取消静音、设备变更、替换或拆除序列添加回归。实时路径使用物理或受控虚拟摄像头/麦克风,拒绝使用浏览器控制的权限状态;模拟单元测试是补充,不是浏览器采集行为的证明。当声明包含原生权限 UI、操作系统指示器或硬件时,使用 references/real-device-validation.md。

捆绑的 localhost Chromium 假设备案例集练习真实 getUserMedia() 获取以及页面内流附加、替换、延迟解析和拆除检查。第二个 Playwright 矩阵在捆绑的 Chromium、Firefox 和 WebKit 引擎中,使用浏览器创建的合成 MediaStream 轨道运行相同的应用拥有生命周期。该矩阵是跨引擎应用生命周期证据,不是原生权限、getUserMedia()、品牌 Safari、操作系统权限 UI、物理拔出/静音或真实摄像头/麦克风硬件证据。

应拒绝的弱发现:仅存在 getUserMedia()、enumerateDevices() 或权限查询;权限前空或脱敏的设备标签;所有者有意保持来源活动的已停止借用轨道;没有目标浏览器证据的不受支持浏览器声明;或属于另一工作流的 iframe、原生 WebView 或录制收尾缺陷。没有不同门控 API 失败和可信事件时序证据的点击处理器、await 或采集拒绝不是激活发现。当 UI、当前轨道守卫和拆除保持真实且幂等时,单个静音或取消静音监听器不是缺陷。

输出形状:以处置开始——confirmed、candidate/needs evidence、reject 或 route。报告浏览器/上下文和请求约束、观察到的异常或轨道转换、readyState 和 muted 证据、当前 UI 状态与真实轨道状态、归属和监听器/媒体元素证据、最小的恢复或拆除更改、适用时的相邻交接,以及确认预期结果的真实浏览器/设备回归。说明任何未测试的拒绝、静音/取消静音、拔出、切换或延迟解析路径,而不是假设其有效。