Licode—基于webrtc的SFU/MCU实现
1. webrtc浅析
webrtc的前世今生、编译方法、行业应用、最佳实践等技术与产业类的文章在网上卷帙浩繁,重复的内容我不再赘述。对我来讲,webrtc的概念可以有三个角度去解释:
(1).一个W3C和IETF制定的标准,约定了Web间实时音视频通信机制,通过该标准可开发基于浏览器的、无插件的web多媒体应用(一般是js),该标准仅设定了点对点无中心的实时会话场景,没有强制约束信令协议与内容,没有要求有媒体处理的中心服务器,主要目标是形成开发者与浏览器厂商良好的生态环境,并积极向HTML5靠拢争取被纳入进去;
(2).一群音视频算法和网络适应性算法,这些算法囊括了视频会议几乎所有的核心技术,包括音视频的采集、编解码、网络传输、播放显示、安全等功能,还提供了操作系统系统调用跨平台封装的实现,包含Windows,Linux,Mac,Android,iOS;
(3).一个开源工程,核心由c++实现,可通过修改、封装、提取代码等方式实现一套视频会议系统,客户端可实现为Web js、App或Windows应用程序等多种形式,服务端可实现包括业务外的所有服务,包括媒体服务、信令服务、穿墙服务、中继服务等等,这些服务稍微调整后可轻易支持分布式部署、容器部署、云部署等。
对webrtc的理解与使用,我认为有三个境界:
(1).能搭建一个简易的视频会议系统,其中客户端部分可以这样做: Windows端Mac端Linux(x86)端在自带的peerconnection client或libjingle改一下(取决于信令是http还是sip家族信令);Android/iOS端在apprtc或licodeAndroidClient及Licode-ErizoClientIOS改一下;web端用webrtc 自带js api实现一下。服务端部分可以这样做:信令服务器在apprtc的collider改一下;穿墙服务器用自带的stun server,turn server部署一下;中继服务器在自带的relay server改一下;媒体服务器在kurentos、licode、jitsi、Intel Collaboration Suite for WebRTC或janus改一下;如果需要和传统的SIP体系互通则在webrtc2sip改一下;如果需要关注实时通信过程中的延时、丢包、接通率、掉线率等质量问题,可以部署callstats来进行专业监测;把所有服务都再部署于云平台的多个虚拟主机上或阿里云的容器云服务,完成以上操作就搭建起初级规模的云上视频会议系统原型了。
(2).能提取、理解并使用webrtc的算法模块,即或将算法模块融入到自己的代码中,或将自己的算法添加至webrtc里作为开源贡献或自己产品的差异性优势。值得提取的算法模块包括音视频编解码与处理框架(vp8、vp9、voice engine、video engine),音视频采集呈现封装、音视频预处理(NetEq、NS、AEC、Video Jitter Buffer)、网络适应性(GCC算法、ARQ、FEC)、安全性(Dtls、Srtp/Srtcp)等,自己可添加的有视频编码模块(x265、nvenc、intel qsv、xavs2、以及其他定制化的网络传输策略)。
(3).能够结合基于rtmp-cdn/p2p等直播技术,构建既支持交互互动,又支持海量围观,可商用、能运营、易扩展、全兼容的音视频PaaS服务平台,完成一个多媒体通信的终极产品。
Licode是达到第一境界技术层面所需要了解的开源工程,它从webrtc代码中提取出了SFU/MCU媒体服务所用到的音视频、媒体传输、信令的功能代码,结合libnice与libav实现了ICE与媒体转发功能,并封装成了可被调用的js API,此外还用js实现了包含全局管理服务、数据库服务、业务逻辑服务与信令媒体的调用服务的业务代码。Licode实现了webrtc开源工程没直接实现的中心侧的媒体服务功能,并提供了简单的业务模型与分布式部署方式,从而得到了多媒体通信工程师的广泛关注。但是Licode的相关文档与资料非常少,故本文是在我个人观察运行调试代码后总结所写的,不正确之处希望在留言中能够得以指正。
2. Licode系统分析
2.1 系统架构
Licode的系统架构如下,有客户端和服务端,客户端包括ErizoClient和NuveClient,分别用来进行信令与音视频交互和业务操作,类似于终端和会控集成在一起;服务端包括Nuve、ErizoController、ErizoAgent和MessageBus,分别用来实现业务服务与全局管理服务、信令服务、媒体服务和服务通信,其中ErizoController类似于MC、ErizoAgent类似于MP。

图1 系统架构图
2.2 客户端与服务端交互流程
客户端与服务端的交互流程如下图所示,其中客户端代码集中在N.API.js与Client.js上,服务端代码集中在nuve.js与erizoController.js上。

图2 信令交互图
3. 系统组成与模块划分
3.1 系统组成
本系统组成仅指服务端的系统组成,包括Nuve业务管理服务,ErizoController信令服务,ErizoAgent媒体服务,ErizoJS媒体转发实体。个人觉得代码在文件命名与文件组织结构上比较乱,初学者不易理解,如erizo_controller文件夹包括了除nuve以及webrtc的js api之外的所有js代码,不仅仅是erizoController,此外webrtc核心部分命名为erizo,也让人与整个系统相混淆。系统组成如下图所示,一个Nuve管理多个ErizoController(以下简称EC),一个EC管理多个ErizoAgent(以下简称EA),一个EA管理多个ErizoJS(以下简称EJ),一个EJ就是一个SFU,封装了C++实现的webrtc、libav与libnice。

图3 服务端系统组成图
3.2 Nuve业务管理服务

图4 Nuve业务管理服务

图5 Nuve各模块用途及对应文件
此外,这篇文章Licode(二):Nuve源码分析 - CSDN博客 对Nuve做了更详细的分析。
3.3 ErizoController信令服务

图6 ErizoController信令服务

图7 ErizoController各模块用途及对应文件
3.4 ErizoAgent媒体服务

图8 ErizoAgent媒体服务

图9 ErizoAgent各模块用途及对应文件
3.5 ErizoJS媒体转发实体

图10 ErizoJS媒体转发实体

图11 ErizoJS各模块用途及对应文件
3.6 webrtc
由于webrtc工程代码本身非常庞大,编译工具也很独特,Licode并未全部引入,仅仅抽取了webrtc的部分代码,如下图所示

图12 webrtc各组件用途及对应目录
由此可见,所抽取的代码没有webrtc自带的音视频处理框架(voice engine/video engine/media engine),这是由于SFC只在RTP层进行转发并不解码,只需要check一下媒体流属性(如I帧头)即可。抽取代码的亮点在于将webrtc强大的抵抗网络时延和丢包的网络适应性算法和协议都提炼出来了,可以供广大研究视频传输的网络适应方向的开发者们单独学习、实验并快速集成到自己非webrtc-based的产品中来。
webrtc的网络适应性手段包括丢包重传(ARQ)、前向纠错(FEC)和拥塞控制(GCC),其中自动码率(ARC)在GCC中。对网络适应性有兴趣的朋友可对照代码看如下几篇博文:
(1). 丢包重传 (ARQ)
RFC4585 RTP/AVPF 传输层反馈;
RFC4588 4585补充 重传包格式;
RFC5104 4585补充 负载层反馈;
RFC5124 RTP/SAVPF
RFC5450 4585补充 Jitter报告
(2). 前向纠错 (FEC)
RFC2198 WebRTC中的前向纠错编码 - Red Packet
RFC5109 WebRTC 的前向纠错编码 - XOR FEC
(3). 带宽检测 (BWE)
传统的基于RTCP RR报文中丢包数来进行带宽检测的算法目前被认为是最low的了,因为属于事后处理;先进的算法是需要事前感知的(突发情况除外),假定带宽是逐渐变窄的,根据信号估计理论可以在网络链路发生丢包以前就监测到网络拥塞,
GCC草案
REMB草案
GCC算法与函数调用 WebRTC基于GCC的拥塞控制(上) - 算法分析 WebRTC基于GCC的拥塞控制(下) - 实现分析
带宽估计 WebRTC之带宽控制部分学习(1) ------基本demo的介绍
带宽检测 WebRTC 中的带宽侦测 - CSDN博客
接收缓冲区延迟估计 WebRTC视频接收缓冲区基于KalmanFilter的延迟模型
3.7 libav、libnice、libsrtp
libav是从ffmpeg分离出的开发者发布的开源工程,与早期ffmpeg有很大相似性,对于仅调用api的开发者来说就简单看成是代码量更小、第三方依赖库更少、编译更简单的轻量级ffmpeg吧。这个库在Licode编译过程中有处问题,Licode使用版本较旧的libav的接口,其中avcodec_alloc_frame和avcodec_free_frame都已经遗弃,改为av_frame_alloc/av_frame_free才可编译通过。
libnice库基于ICE协议实现的网络层库,Licode使用libnice库来实现端到端的ICE连接和数据流发送接收,以及candidates(候选地址)和SDP(媒体描述文件)的相互交换。
libsrtp库主要是是用来加密rtp/rtcp的。
4. 关键技术
4.1 网络收发流水线架构技术
网络收发或一个SFU实现,并非简单的从一个源地址收到若干个数据包再复制多份发送给多个目的地址,正如3.6所描述,除了需要堆栈式的ICE地址转换、DTLS/SRTP的解密,还需要流水线式的RTP/RTCP的丢包检测与重传、FEC处理、带宽检测与估计、包缓冲区调整以及平滑发送等若干个复杂步骤,这个流程在Licode代码中是通过Pipeline-Handler这样的架构实现的,由于webrtc仅提供底层算法并未提供SFU架构,所以我认为这种架构是Licode最重要的关键技术,可供未来想成为软件架构师的开发者参考学习。日后我也再详细分析这个架构,看看是否能抽象出一个新的设计模式来。
整个网络收发的层级模型图如下图所示,其中每一层右侧标注出了关键类。

图13 网络收发层级模型
Pipeline的类图如下图

图14 Pipeline相关类图
对Pipeline来说,需要全局管理、长时处理或非逐个包处理的流程,实现对象叫Service,包括Handler的管理、RTCP的计算与处理、当前状态的处理、网络质量的管理以及包缓冲的管理都是Service;而需要每次逐包处理的流程,实现对象叫Handler,包括19项Handler,其代码都位于erizo\src\erizo\rtp目录下
//新增全局处理的Service
pipeline_->addService(handler_manager_);
pipeline_->addService(rtcp_processor_);
pipeline_->addService(stats_);
pipeline_->addService(quality_manager_);
pipeline_->addService(packet_buffer_);
//新增单次处理的Handler
pipeline_->addFront(std::make_shared<RtcpProcessorHandler>());
pipeline_->addFront(std::make_shared<FecReceiverHandler>());
pipeline_->addFront(std::make_shared<LayerBitrateCalculationHandler>());
pipeline_->addFront(std::make_shared<QualityFilterHandler>());
pipeline_->addFront(std::make_shared<IncomingStatsHandler>());
pipeline_->addFront(std::make_shared<RtpTrackMuteHandler>());
pipeline_->addFront(std::make_shared<RtpSlideShowHandler>());
pipeline_->addFront(std::make_shared<RtpPaddingGeneratorHandler>());
pipeline_->addFront(std::make_shared<PliPacerHandler>());
pipeline_->addFront(std::make_shared<BandwidthEstimationHandler>());
pipeline_->addFront(std::make_shared<RtpPaddingRemovalHandler>());
pipeline_->addFront(std::make_shared<RtcpFeedbackGenerationHandler>());
pipeline_->addFront(std::make_shared<RtpRetransmissionHandler>());
pipeline_->addFront(std::make_shared<SRPacketHandler>());
pipeline_->addFront(std::make_shared<SenderBandwidthEstimationHandler>());
pipeline_->addFront(std::make_shared<LayerDetectorHandler>());
pipeline_->addFront(std::make_shared<OutgoingStatsHandler>());
pipeline_->addFront(std::make_shared<PacketCodecParser>());
pipeline_->addFront(std::make_shared<PacketWriter>(this));
4.2 分布式保活技术
Licode的系统设计如3.1所述,Nuve管理多个EC,EC管理多个EA,EA启动多个EJ进程;在资源上,Nuve负责EC的负载均摊,EC负责EA和EJ的负载均摊(毕竟EJ在EA内,EA除了监控OS性能并未太多其他工作),故Nuve需要EC分布式保活,EC需要EA分布式保活。Licode实现比较简单,代码可参考CloudHandler.js与ecCloudHandler.js。
例如Nuve每启动一个EC立刻分配id,并加入到ECList中,并在DB中写入id作为key,且在该key对应的value上进行累加,此后Nuve的秒级循环中不断check这个value并继续累加,如果超过阈值,则认为该EC失效,将此EC从list中删除。Nuve同时提供keepalive接口,EC通过RPC调用此接口不断对数据库中本id的value清零,从而实现了分布式保活。EC与EA间方法一样。
4.3 资源管理技术
这里定义的资源有三个含义:设备资源(设备简单分为发布设备、接收设备、收发设备)、内容资源(某地的实时视频或已录制视频)以及server处理能力余量(例如还能转发的路数,还能容纳的新成员)。
Licode的publish-subscribe模型将信令交互、内容管理(源站管理)、媒体分发三者分开,从而可实现多维度的资源管理。
Client 1 发的第一个信令仅起到了一个资源注册的作用,即room中存在Client 1的id了;
Client 1 发的第二个信令表明该id可以发布新内容了,内容为Stream 1;
Client 2 同理,room记录了Client 2的id与Stream 2;
Client 1发的第三个信令表明对Client 2的Stream 2内容感兴趣开始订阅了,于是启动了SFU过程;
Client 3加入room后,可以发布资源(Stream3),可以订阅资源(Stream1、Stream2),也可以什么都不做,因为任何在该room中注册的设备都可以pubilsh内容资源或subscirbe已publish的内容资源。完全解耦带来的好处是内容资源同设备资源一样也可以轻易管理了,在启动SFU过程中,server处理能力余量也能得到较好的管理。
H.323是紧耦合的,信令交互后必须开启媒体交互(电路交换的思维,信道容量有限,申请资源赶紧用,用完赶紧释放),对内容管理过于依赖于会议逻辑的实现,为了实现更灵活的互听互看,其逻辑会堆砌的很复杂。
然而好的方法也不是万能的,publish-subscribe的完全解耦虽带来极大的可扩展性,但对于某些传统业务更复杂了。比如MCU两个终端互看,就需要启动两个erizoJS,互相订阅发布,根据负载均摊的算法,可能两个erizoJS都不在一个erizoAgent里(不在同一台物理机或虚拟机上)。MCU轮询模式也稍复杂,轮询者需要不断的subscribe room中的发布者,发布者也要不断的去remove、add,切换速度比接收所有流+I Frame Check的传统方式要慢的多。
5. 总结
本文先介绍了自己对webrtc的概念理解与使用参考,接下来从系统架构、交互流程、系统组成与模块划分几个角度对Licode进行概要设计级别的分析,最后对自己觉得Licode比较有特色的三大技术,即网络收发流水线架构技术、分布式保活技术与资源管理技术进行了浅层次的解释。文中表述内容可能会有不准确之处,希望能与读者们交流并及时改正。
原文https://zhuanlan.zhihu.com/p/40462946
★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。
见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
相关文章:

Licode—基于webrtc的SFU/MCU实现
1. webrtc浅析webrtc的前世今生、编译方法、行业应用、最佳实践等技术与产业类的文章在网上卷帙浩繁,重复的内容我不再赘述。对我来讲,webrtc的概念可以有三个角度去解释:(1).一个W3C和IETF制定的标准,约定…...

开发运维工具推荐 --- 解决远程访问局域网服务的问题。开发调试推荐
一、FastNat 可为您解决的问题1. 没公网服务器,需要发布本地的站点或网络程序到公网上,供他人访问;此项功能大大方面开发人员进行远程调试,微信小程序等开发工作进行。2. 需要远程到在其他网络中的设备,但两处的网络不…...
【华为OD机试 】单词倒序(C++ Java JS Python)
文章目录 题目描述输入描述输出描述备注用例题目解析C++ 解法JavaScript算法源码Java算法源码Python解法题目描述 输入单行英文句子,里面包含英文字母,空格以及,.?三种标点符号,请将句子内每个单词进行倒序,并输出倒序后的语句。 输入描述 输入字符串S,S的长度 1 ≤ N…...
PLC 诊断故障的基本原理
(1)东欢坨选煤厂机电设备故障信号主要取自开关量信号,PLC 通过开关量的通和断对设备进行故障诊断。PLC 对开关量的识别是通过输入模块来实现的。PLC 控制设备运行时,设备中的温度、压力、急停、跑偏、速度、过热以及各种按钮和行程开关的传感器与 PLC 输入模块相连接,输入模块的…...
QT打开外部程序并嵌入Qt子窗口的缺点
首先可以参考如下文章: QT打开外部程序并嵌入Qt界面_qt界面嵌入外部应用程序_初学小白Lu的博客-CSDN博客 Qt嵌入外部程序界面初探_qt嵌入其他程序窗口_liming4675的博客-CSDN博客 QT 如何把外部程序嵌入到QT界面_qt嵌入其他程序窗口_hellokandy的博客-CSDN博客 Qt界…...

如何系统地学习 C++ 语言?
C作为具有广泛适用性的编程语言,学习C的人越来越多,但是如何系统地学习C还是个问题,下面我们一起来看一下C学习的方法有哪些吧。 首先,要学习C,最重要的就是掌握C的基础知识。 比如数据结构、算法、微积分等。这些都是…...

【数据结构】单链表
链表1.为什么存在链表2.链表的概念3.单链表的实现4.测试1.为什么存在链表 我们在学习顺序表的时候,了解到顺序表有一定的缺陷:(1)在中间插入数据和删除数据需要挪动数据,时间复杂度是O(N)&…...

Windows 右键菜单扩展容器 [开源]
今天给大家分享一个我做的小工具,可以自定义扩展右键菜单的功能来提高工作效率,效果图如下: 如上图,右键菜单多了几个我自定义的菜单: 复制文件路径 复制文件夹路径 我的工具箱 <走配置文件动态创建子菜单&#x…...

爆文制造机!小红书热榜3个方向,告诉你选题诀窍!
我们知道,不论是达人创作内容,还是品牌制定Brief,都需要提前调研筛选海量信息,这时候如果有一个自己的内容素材库,就省事多啦。按照内容需求,我们可以按3个角度划分小红书内容素材:笔记类型、竞…...

【Web安全社工篇】——水坑攻击
作者名:白昼安全主页面链接: 主页传送门创作初心: 以后赚大钱座右铭: 不要让时代的悲哀成为你的悲哀专研方向: web安全,后渗透技术每日鸡汤:努力赚钱不是因为爱钱“水坑攻击”,黑客攻…...
SpringBoot 整合 MongoDB 实现数据的增删改查!
一、介绍在 MongoDB 中有三个比较重要的名词:数据库、集合、文档!数据库(Database):和关系型数据库一样,每个数据库中有自己的用户权限,不同的项目组可以使用不同的数据库集合(Colle…...

VUE前端常问面试题
文章目录一、VUE前端常问面试题二、文档下载地址一、VUE前端常问面试题 1、MVC和MVVM 区别 MVC:MVC全名是 Model View Controller,即模型-视图-控制器的缩写,一种软件设计典范。 Model(模型):是用于处理应用程序数据逻辑部分。通…...
c++中map/unordered_map的不同遍历方式以及结构化绑定
文章目录方式一:值传递遍历方式二:引用传递遍历方式三:使用迭代器遍历方式四:结构化绑定(c17特性)结构化绑定示例(1)元组tuple结构化绑定(2)结构体结构化绑定(3ÿ…...
Kafka系列之:Kraft模式
Kafka系列之:Kraft模式 一、Kraft架构二、Kafka的Kraft集群部署三、初始化集群数据目录四、创建KafkaTopic五、查看Kafka Topic六、创建生产者七、创建消费者一、Kraft架构 Kafka元数据存储在zookeeper中,运行时动态选举controller,由controller进行Kafka集群管理。Kraft模式…...

动态规划:leetcode 139.单词拆分、多重背包问题
leetcode 139.单词拆分leetcode 139.单词拆分给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你可以假设字典中没有重复的单词。示例 1&…...

Stable Diffusion原理详解
Stable Diffusion原理详解 最近AI图像生成异常火爆,听说鹅厂都开始用AI图像生成做前期设定了,小厂更是直接用AI替代了原画师的岗位。这一张张丰富细腻、风格各异、以假乱真的AI生成图像,背后离不开Stable Diffusion算法。 Stable Diffusion…...

webpack高级配置
摇树(tree shaking) 我主要是想说摇树失败的原因(tree shaking 失败的原因),先讲下摇树本身效果 什么是摇树? 举个例子 首先 webpack.config.js配置 const webpack require("webpack");/**…...

jQuery 事件
jQuery 事件 Date: February 28, 2023 Sum: jQuery事件注册、处理、对象 目标: 能够说出4种常见的注册事件 能够说出 on 绑定事件的优势 能够说出 jQuery 事件委派的优点以及方式 能够说出绑定事件与解绑事件 jQuery 事件注册 单个时间注册 语法:…...
【批处理脚本】-2.3-解析地址命令arp
"><--点击返回「批处理BAT从入门到精通」总目录--> 共2页精讲(列举了所有arp的用法,图文并茂,通俗易懂) 目录 1 arp命令解析 1.1 询问当前协议数据,显示当前 ARP 项...

改进 YOLO V5 的密集行人检测算法研究(论文研读)——目标检测
改进 YOLO V5 的密集行人检测算法研究(2021.08)摘 要:1 YOLO V52 SENet 通道注意力机制3 改进的 YOLO V5 模型3.1 训练数据处理改进3.2 YOLO V5 网络改进3.3 损失函数改进3.3.1 使用 CIoU3.3.2 非极大值抑制改进4 研究方案与结果分析4.1 实验…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...