首页 > 其他分享 >第二十一章 实战青龙流式系统问题总结

第二十一章 实战青龙流式系统问题总结

时间:2024-10-10 10:18:13浏览次数:3  
标签:第二十一章 RTC Track 青龙 流式 rtp report type 连接

我们在实际的开发过程会遇到很多的问题,这里总结和归纳,可以帮助各位

流式协议带来的限制

媒体流属性的随机化处理

  • RTC 协议要求接收方在接收到媒体流后复写 media track 上的 id, label, contentHint 等属性以保证流属性不会泄漏发送者的媒体设备信息,并使流在 P2P 网络中唯一.
  • 这导致接收者无法区分流中的同类型 track. 例如发送者将相机,屏幕共享两条视频轨道合在同一条流中发给接受者,发送者不知道这两条流到接受者处时 Id 分别是什么,接受者也无法区分哪个是屏幕共享,哪个是视频流
  • 解决方法:在传输多个 track 需要分离的时建立多条 P2P 连接 (虽然看起来很蠢)

FireFox 禁止两个相同节点之间无法建立多条连接

  • FirFox 禁止两个相同节点做多次媒体协,也就是说 A 节点最多 call B 节点一次.
  • 解决方案:如果需要建立两条流 (例如相机和屏幕共享流) 就让 A, B 互相 call 一次

一旦连接建立,不能添加或者删除 Track

  • 建立 RTC 连接的时候虽然我们传入的是一个流,但是协议会获取流中的所有 Track, 然后传输这些 Track, 这就意味着协议并不会引用流对象,我们为流加入或者删除 Track 无法对 RTC 产生影响.
  • 例如用户目前正在使用前置摄像头,当用户切换到后置摄像头时,如果我们删除流中的前置媒体流,添加后置媒体流,RTC 连接并不会切换轨道,反而会认为无法获取轨道信息
  • 解决方案:在建立连接时创建最大可能使用数量的占位流,在增减设备时使用 RTC API 中的 replaceTrack 方法替换占位流。例如:在传输摄像头和麦克风数据时,我们可能需要采集麦克风,摄像头,背景虚化遮罩的 Track, 那么我们就需要使用一个占位 AudioTrack, 两个占位 VideoTrack. 当启动摄像头时候,将占位 Video Track 切换为实际 Track, 在禁用摄像头时再切换回去

RTC 连接状态统计

  • RTC 并不支持直接汇总全部 RTC 连接状态,只支持统计某一个连接的连接状态。开发者可以通过 RTCPeerConnection.getStats 获取对于一个连接的不同主题的报告。常见的有:
    • 统计比特率:
      • 获取当前连接发出或者接收到的总字节数
      • 求和所有连接的收发的总字节数
      • 比特率 = 8 * 两次检测时的字节数差 / 两次检测间隔
    • 获取收发字节数
      • 获取下行字节数: report.type === 'inbound-rtp' 的报告的 report.bytesReceived
      • 获取上行字节数: report.type === 'outbound-rtp' 的报告的 report.bytesReceived
    • 区分媒体类型
      • 视频: report.mediaType === 'video'
      • 音频: report.mediaType === 'audio'
    • 统计下行丢包率:
    • 一个连接的累计丢包: report.type === 'inbound-rtp' 报告的 report.packetsLost
    • 一个连接的从收包: report.type === 'inbound-rtp' 报告的 report.packageReceived
    • 总下行丢包率: 所有连接的丢包量求和 / (所有连接的丢包量求和 + 所有连接的收包量和)
    • 网络延迟:
    • 一个连接的延迟: report.currentRoundTripTime (单位: s)
    • 总延迟: 所有延迟求和 / 连接数量
    • 视频帧率:
    • 上行连接帧率: report.type === 'outbound-rtp' 报告的 report.framesPerSecond
    • 下行连接帧率: report.type === 'inbound-rtp' 报告的 report.framesPerSecond
    • 总帧率: 连接帧率求和 / 连接数
    • 视频分辨率:
    • 上行连接分辨率: report.type === 'outbound-rtp' 报告的 report.frameWidthreport.frameHeight
    • 下行连接分辨率: report.type === 'inbound-rtp' 报告的 report.frameWidthreport.frameHeight
  • 实现可以参考 conflux-client/src/utils/report.ts at master · KairuiLiu/conflux-client · GitHub
  • 用来调试的 RTC 连接状态报告: chrome://webrtc-internals/

媒体流的处理与兼容性问题

媒体权限的获取与浏览器兼容性问题

  • 在首次 navigator.mediaDevices.getUserMedia() 浏览器会提示用户授权。但是这会导致设备列表只有在获取用户设备时才刷新。不方便 UI 展示。建议采用如下方式:
    • 判断是否授权:
      • 现代化的方法:使用 navigator.permissions
      • 但是该 API 存在兼容性问题,只有 Chrome 与 Safari 支持 microphone 与 camera 这两个 permissionName, FireFox 会报错
      • 兜底方法:检查 navigator.mediaDevices.enumerateDevices() 中某类 type 是否没有或者 Label 为空。如果是则证明要么用户没有这类设备,要么没有授权。该函数不会让浏览器弹出授权
      • 总结:
    • 申请授权:
    • 监控授权状态变化
    • 监控设备变化

指定音频输出设备

  • 注意:仅桌面 Chrome 与 FireFox 浏览器支持支持,TS 也没有这个方法
// @ts-ignore
audioElement?.setSinkId?.(speaker.deviceId);

指定音视频采集设备

const constraints: MediaStreamConstraints = {[type]: { deviceId: { exact: deviceId } },};
const stream = await navigator.mediaDevices.getUserMedia(constraints);

音频轨道音量统计

  • 注意:音量取值是 [0,1], 当麦克风离得比较远时采集的音量一直很小,进度条展示出来一直处于低点。可以采用 softmax 对结果做变化,让用户可以明显看到音量变化
  • 注意: AudioContext 并不能指定音频播放设备,因此不能用它来顺便播放音频.
  • 原理:
    • 创建 AnalyserNode 用于实时获取音频信号的时间域和频率域数据 (默认使用 FFT 采样)
    • 使用 getByteTimeDomainData 获取最近的时域数据,值代表振幅值 (取值 0-256, 128 为静音)
    • 每个样本值减去 128, 使得波形数据中心化到 0 (静音为 0)
    • 将每个去中心化后的值求平方,得到每个样本的能量,计算所有样本能量的平均值
    • 计算平均能量的平方根,得到均方根值,(当音量最大时,均方根为 255)

如何解决ontrack事件不触发的问题?

1、确保正确绑定了事件,检查代码中的语法错误,并确保使用正确的轨道类型和流对象。

const localStream = await navigator.mediaDevices.getUserMedia({ video: true });
localStream.addEventListener('ontrack', (event) => {
  console.log('ontrack event triggered');
});

2、如果仍然无法触发事件,尝试使用不同的轨道类型或流对象进行测试。

Web 通话过程中出现回声、杂音、噪声、声音小?

通话双方的设备相距太近的时候,属于正常现象,测试时请相互距离远一点。当其他端听到 Web 端的声音存在回声、噪声、杂音等情况时,说明 Web 端的 3A 处理没有生效。

若使用了浏览器原生 getUserMedia API 进行自定义采集,则需要手动设置 3A 参数:

  • echoCancellation:回声消除开关
  • noiseSuppression:噪声抑制开关
  • autoGainControl:自动增益开关? 详细设置参考 媒体追踪约束 。

标签:第二十一章,RTC,Track,青龙,流式,rtp,report,type,连接
From: https://blog.csdn.net/ms44/article/details/142814208

相关文章

  • 基于WebRTC的流式系统揭秘
    序言最近几年远程办公开始涌现之际,越来越多的应用在云端进行支持,从性能表现和画质表现来看,基于WebRTC开源框架的流式系统开始主流,用户数,开发人员,产品数量大幅上升。本文基于这种业界现状,向大家阐述各个方面的技术细节和内容,希望能给到大家一些产品研发过程中的心得和技术要点......
  • 青龙源码解析MPC
    1.全身运动学青龙全身共31个自由度。2个7自由度臂,2个头部自由度,3个腰部自由度,每个腿是6个自由度(髋关节3DOF,膝关节1DOF,踝关节2DOF)共7+7+2+3+6+6=31再加上浮动基座6自由度,总共37自由度。2.变量:输入:13*3=39的纬度;约束:32*3的纬度Ac,Bc,A,B,Cc,C:状态空间矩阵Ac,A......
  • 前端如何接收SSE流式数据传输(大模型网站常用)
    使用fetchEventSource参考:https://blog.csdn.net/qq_43750656/article/details/131591198https://zhuanlan.zhihu.com/p/686618062首先安装:npminstall--save@microsoft/fetch-event-source我参考各个资料写的函数://流式传输处理函数exportfunctionsseRequest(url:s......
  • 限流式保护器在低压配电系统中电气火灾的重要性
    随着人类进入现代文明社会,电气的普及深入千家万户,广泛应用于社会的各个领域但是每年因电气而导致的火灾却给国家和人民的生命财产带来巨大的损失,据统计,因低压配电系统中的短路发的火灾几乎达到了电气火灾总数的60%以上,因此加强低压配电系统管理,防止短路故障的发分析掌握短路的......
  • ChatGPT流式数据传输探索
    文章目录背景介绍目标技术细节1、客户端2、服务端总结背景介绍用过GPT类语言模型的同学都知道,其在返回数据时都是一个字或几个字的显示,你是否思考过它是怎么传输的?经过一番查询学习,了解到了SSE,GPT就是通过SSE流式传输方式进行传输的。SSE全称为Server-sent-even......
  • Node.js 实现流式渲染
    什么是流式渲染?流式渲染的核心理念是将HTML文档分割成小块(chunk),并逐步地发送给客户端,而非等待整个页面完整生成后再进行传输。这种方式能够极大地提升用户的初始加载体验,特别是在网络条件不佳或者页面内容复杂的情况下。流式渲染并非新兴技术,早在90年代,网页浏览器就已开......
  • Attention Sinks 入门指南 - 实现无限长度文本生成的高效流式语言模型
    AttentionSinks简介AttentionSinks是一种新的注意力机制,可以让预训练语言模型生成无限长度的连贯文本,同时保持恒定的内存使用。它通过保留初始token的注意力信息(称为"注意力池"),并使用滑动窗口来处理最近的token,从而实现了高效的长文本生成。AttentionSinks......
  • PaddleSpeech TTS API与流式速度对比(windows Java版)
    首先本地环境要安装部署PaddleSpeech语音识别系统,参考Windows10系统部署PaddleSpeech本地部署好后,根据官方文档启动TTS的流式服务,参考PaddleSpeech语音启用流式服务1、相关服务的启动 1.1本机启动TTSAPI服务paddlespeech_serverstart--config_file./demos/speech_ser......
  • 使用SSE发送和接收流式数据
    背景早期去玩了一下各个Ai厂商的免费额度(主要是国内的),虽然不是很给力,但是还是蛮好玩的。建立长连接我们通常使用WebSocket,而对于流式数据发送,只需要服务器返回数据,而不需要客户端发送数据的情况下,SSE是一个不错的选择。介绍SSE(Server-SentEvents)。数据格式大致如下,如果不写......
  • 推荐一个Python流式JSON处理模块:streaming-json-py
    每天,我们的设备、应用程序和服务都在生成大量的数据流,这些数据往往大多是以JSON格式存在的。如何高效地解析和处理这些JSON数据流是一大挑战。今天,我要为大家介绍一个能极大简化这一过程的利器:streaming-json-pystreaming-json-py介绍streaming-json-py是一个专为实时......