《WebKit 技术内幕》学习之十一(4):多媒体

 4 WebRTC

4.1 历史

        相信读者都有过使用Tencent QQ或者FaceTime进行视频通话的经历,这样的应用场景相当典型和流行,但是基本上来说它们都是每个公司推出的私有产品,而且通信等协议也都是保密的,这使得一种产品的用户基本上不可能同其他产品的用户进行视频通信。还有一些更大的应用场景,那就是众多用户一起召开视频会议,这比简单的点对点更为复杂,很多公司已投身其中,因为这一市场非常广大。

        几年前,笔者是很难想象这么复杂的需求和应用场景能够在Web领域中被实现,但是现在Chromium和Firefox浏览器都支持Web视频通信,而且神奇的是它们之间也可以相互通信,听起来非常不可思议——只是需要Web开发者使用JavaScript和HTML5技术就可以完成,还是免费的,而且还不需要额外安装应用软件,不需要额外安装插件。现在真是互联网和HTML5技术的好时代,这也是HTML5的多媒体领域的一个重大进展。

        WebRTC(Web Real Time Communication)技术,中文全称为Web实时通信技术,它是一种提供实时视频通信的规范,目前是W3C推荐的规范。它是一个开放的规范,任何人都可以免费使用,目前Chromium/Chrome和Firefox浏览器都支持了该规范。WebRTC是HTML5对多媒体支持的一个重大进展,因为该技术不仅使用了音视频的输入和输出,而且还涉及连接等网络连接,是一个非常复杂但非常有用的技术。图11-19是一个简单的示意图,说明两个支持WebRTC规范的浏览器之间是如何进行视频通信的。事实上,WebRTC既允许使用服务器来进行通信,也支持点对点(Peer-to-Peer)通信,当然需要服务器的辅助。

                图11-19 Chromium/Chrome和Firefox浏览器的视频通信示例图

        不过,很多事情并非是一蹴而就的,何况这么复杂的WebRTC技术,WebRTC发展至今也经历了很长的过程。首先得从一个音视频的捕获需求开始。最初,HTML5希望能够提供一种捕获用户音频和视频的技术,这就是getUserMedia,当然刚开始也不是它,而是使用下面的语句来完成音频和视频的捕获。

    <input type="file" accept="video/*;capture=camcorder"><input type="file" accept="audio/*;capture=microphone">

        但是它们太简单了,只能将捕获的信息保存为一个文件或者一个快照,这显然不能满足很多实际的需求,之后一个新的元素定义诞生,就是使用“device”元素,这一元素很快被抛弃。这就是getUserMedia的前身,但标准化组织很快从“device”元素转向getUserMedia,它的基本使用方式是:

    navigator.getUserMedia({video: true, audio: true}, function (videostream) { … });

        思想很简单,就是在navigator这个全局对象下加入一个新接口,该接口使用两个参数,第一表示它需要捕获视频或者音频或者两者都需要,第二个是一个回调函数,当捕获成功后,将捕获的视频流可以输出到一个视频元素,这就像是一个从服务器加载的视频文件,当然它是一个视频流,所以某些查找(Seek)操作不能工作。这里,不再使用新元素,而是利用原有的“video”元素,实在是一个好的设计。

        在这之后,一个更为大胆和激进的想法诞生了,就是将RTC技术引入到HTML5中来,这就是WebRTC技术,因为getUserMedia是入口,所以自然而然地被使用到WebRTC技术的规范中来。

11.4.2 原理和规范

        大家可以在脑海中想象一下如何要构建一个网络视频通信、需要哪些部分的参与及共同工作才能完成整个过程。总体上,这一过程中需要三种类型的技术,其一是视频,其二是音频,其三是网络传输。在这三种技术上,具体需要以下一些部分。

  • 音视频输入和输出设备 :同音视频播放不同,因为它们只是需要输出设备,这里需要输入和输出设备(麦克风和摄像头)。同时,输入使用getUserMedia技术,而输出,基本上可以采用音视频播放的基本框架,当然,需要一些额外的支持。
  • 网络连接的建立 :因为视频通信需要不停地传送大量数据,所以需要建立一种可靠的网络连接来让各个参与方传输数据。
  • 数据捕获、编码和发送 :当用户打开设备之后,需要捕获这些数据并对它们进行编码,因为原始数据的数据量太大,然后需要将编码后的数据通过连接传输出去。
  • 数据接收、解码和显示 :接收来自其他方的数据流并进行解码,然后显示出来,这个需求跟播放媒体文件的需求比较类似。

        根据上面的解释,不难理解图11-20所描述的过程,结合这些主要组成部分,构成了一个比较完整的音视频通信过程。

                                        图11-20 使用WebRTC技术的视频通信详细过程

        下面了解一下规范中如何针对上面的描述来定义相应的JavaScript接口的。根据目前W3C推荐的规范草案,主要包括以下几个部分。

  • Media Capture and Streams规范和WebRTC对它的扩展,这个主要是依赖摄像头和麦克风来捕获多媒体流,WebRTC对它进行扩展,使得多媒体流可以满足网络传输用途,也就是“video”元素可以来源于多媒体流而不仅仅是资源文件。
  • 点到点的连接,也就是规范中的RTCPeerConnection接口,它能够建立端到端的连接,两者直接通过某种方式传输控制信息,至于方式并没有进行规定。
  • RTCDataChannel接口,通过该接口,通信双方可以发送任何类型的消息,例如文本或者二进制数据,这个不是必须的。不过这一功能极大地方便了开发者,其主要思想来源于WebSocket。

11.4.3 实践——一个WebRTC例子

        在介绍内部原理之前,笔者希望通过剖析W3C规范中的一个例子来进一步加深对它的理解。示例代码11-5来源于W3C WebRTC规范中的示例代码,笔者稍微作了一些修改以简化理解,并加入注释作进一步说明。

        这里主要是点对点的直接通信,当然需要借助于网络提供的NAT服务,其中包括三个文件,第一个是双方共享的JavaScript代码,第二个是发起端的HTML代码,第三个是接收端的HTML代码。通常第二个和第三个可以是一样的,这里为了方便理解作了少许区别。因为代码中已经作了较为详细的讲解,所以后面不再赘述其中的原理。

示例代码11-5 使用WebRTC技术的P2P网络视频通信

    JavaScript文件:common.js// 创建消息通道,例如使用XMLHttpRequest或者WebSocket。根据WebRTC规范的说明// 本身WebRTC不提供双方进行控制信息传输的通道,由开发者自行选择合适的方法// 这里,简单使用一个函数表示创建了一个通道,该通道包含一个能够发送消息的“send”var signalChannel = createSignalChannel();// 将ICE的Candidate发送给对方,这个是ICE定义的,主要是ICE协议用来建立连接需// 要的信息。双方需要交互这个信息function sendCandidate(candidate) {if (candidate) signalChannel.send(JSON.stringify({ "candidate": candidate }));}function sendDescription() {signalingChannel.send(JSON.stringify({ "sdp": conn.localDescription }));}signalingChannel.onmessage = function (event) {// 如果没有建立连接,需要创建,在这里表明这是接受者端if (conn == null) start();// 从控制信息中获取信息内容var message = JSON.parse(event.data);// 如果信息类型是设置Description相关的,就调用setRemoteDescriptionif (message.sdp) {conn.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {// 如果受到一个请求(offer),需要答复它,这里应该是接收方处理的if (conn.remoteDescription.type == "offer") {conn.createAnswer(function(desc) {conn.setLocalDescription(desc, sendDescription);});} else if (message.candidate) {conn.addIceCandidate(new RTCIceCandidate(message.candidate));}};// 用来存放RTCPeerConnection对象var conn = null;// 用来显示从自身设备捕获的多媒体流var selfView = document.getElementById("selfView");// 用来显示从对方传送过来的多媒体流var remoteView = document.getElementById("remoteView");// 开始创建连接等function start() {// 创建连接conn = new RTCPeerConnection({ "iceServers": [{ "url": "stun:stun. example.org" }] });// 保存从自身捕获的多媒体流var capturedStream = null;// 捕获音视频navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {// 将捕获的多媒体流使用“video”元素播放出来selfView.src = URL.createObjectURL(stream);capturedStream = stream;}// 将多媒体流加入连接conn.addStream(capturedStream);// 接收到ICE Candidate事件,需要将candidate信息传送给对方conn.onicecandidate = function (event) {sendCandidate(event.candidate);};// 这个是由发起者调用,因为接收者不会发送该事件conn.onnegotiationneeded = function() {// 创建一个Offer,然后发送给接收者conn.createOffer(function (desc) {conn.setLocalDescription(desc, sendDescription););});// 将远端多媒体流使用“video”元素显示出来conn.onaddstream = function (evt) {remoteView.src = URL.createObjectURL(evt.stream);};}发起者HTML文件节选:<video id="selfView" autoplay ></video><video id="remoteView" autoplay></video><script src='common.js'></script><script>// 上面的两个"video"元素分别用来显示自己捕获的多媒体流和对方的多媒体流// 实际情况中,可能是某个用户作为发起者单击了“开始”按钮,启动音视频通信start();</script>接受者HTML文件节选:<video id="selfView" autoplay ></video><video id="remoteView" autoplay></video><script src='common.js' type='javascript'></script>

        相信通过上面的代码介绍,读者应该理解使用WebRTC构建一个P2P视频通信的基本过程,这其中网络连接的部分主要基于ICE协议(NAT)和SDP协议,以及一些支持NAT的辅助设施(STUN和URN),有兴趣的读者可以自行查阅相关技术文档。

4.4 WebKit和Chromium的实现

        下面来看一看WebKit和Chromium是如何支持WebRTC规范的。笔者首先需要澄清一下关于WebRTC的两种解释,本节中会有两种WebRTC用法:一种是指WebRTC这项技术和规范;另一种是WebRTC这个项目,它是支持WebRTC规范的一个开源项目。默认情况下是指前者,如果是指WebRTC这个开源项目,笔者会明确指出。

        下面来了解一下从webrtc.org上介绍的关于支持WebRTC技术的内部框架和功能模块,图11-21来源于“http://www.webrtc.org/reference/architecture”的架构图,但是缩减了其中一些部分。这里所示的是实现了WebRTC功能的开源项目架构图。

        图11-21中主要包括三大方面,即语音、视频和传输,它们三个构成了WebRTC的主要组成部分。其中iSAC(internet Speech Audio Codec)和iLBC(internet Low Bitrate Codec)是两种不同的音频编码格式,是为了适应互联网的语音传输要求而存在的,前者是针对带宽比较大的情况,后者针对带宽较小的情况,目前都是可以免费使用的。其中VP8同样是Google提供免费视频格式,前面介绍过了。传输部分主要是加入了对前面协议的支持模块。在会话管理中,主要使用一个开源项目libjingle来进行管理。下面灰色部分主要是WebRTC工作时依赖的下层功能的接口,在Chromium浏览器中,它会提供相应接口和功能给WebRTC使用。

                                        图11-21 WebRTC项目的架构图

         上面是WebRTC开源项目的架构图,在Chromium中,通常使用WebRTC项目来完成WebRTC规范的功能,并使用libjingle项目来建立点到点的连接。所以,Chromium主要的目的是将WebRTC和libjingle的能力桥接到浏览器中来,先看WebRTC规范中建立连接所需要的相关基础设施,图11-22是WebKit、Chromium及Chromium中使用libjingle的类的层次图。

                                图11-22 WebKit和Chromium建立连接的基础设施

        基础设施主要分成三个层次,首先是WebKit,也就是最上面的部分。该部分最上面的类是RTCPeerConnection,从名字就可以猜出,该类是对WebRTC连接的接口类,实际上它就是从规范中定义的RTCPeerConnection接口文件生成的基本框架,当然真正和JavaScript引擎打交道还需要一个桥接类。该桥接类包含一个实际实现的连接类句柄m_peerHandler,它是这个连接所包含的本地多媒体流和远端对方的多媒体流。读者可以想象一下视频会议的场景,首先Webkit需要将本地的多媒体流收集起来,通过连接传输给对方,本地可以选择是否通过“video”播放。同时需要接收从对方传输过来的多媒体流,这也是WebRTC的主要部分。当然还包括DataChannel相关对象,这里没有标出。

        至于接下来的部分就是WebKit的实现类,该类能够满足RTCPeerConnection的功能要求,但是它需要通过不同移植的实现才能完成,因为本身WebKit的WebCore并没有这样的能力。在WebKit的Chromium中同样定义了两个类WebRTCPeerConnectionHandler和WebRTCPeerConnectionHandlerClient,根据WebKit的类名定义方式,前者是需要Chromium来实现,而后者则是由Chromium调用,并由WebKit来实现的,这里主要是应用连接事件的监听函数,所以WebKit能够将它们传递给JavaScript引擎。

        之后是Chromium的实现类。RTCPeerConnectionHandler类继承自WebKit的Chromium移植的接口类,并做了具体的实现,这就是content::RTCPeerConnectionHandler,它同时集成自PeerConnectionHandleBase类,而该类拥有了支持建立连接所需的能力,当然它是依赖于libjingle项目提供的连接能力。

        libjingle提供了建立和管理连接的能力,支持透过NAT和防火墙设备、代理等建立连接。libjingle不仅支持点到点的连接,也支持多用户连接。同时还包含了连接所使用的MediaStream接口,这是因为Chromium本身不直接使用WebRTC项目提供的接口,而是调用libjingle来建立连接,并使用libjingle提供的MediaStream接口,而libjingle本身则会使用WebRTC项目的音视频处理引擎。

        接下来要介绍的是多媒体流,它需要一个非常复杂的框架,首先来看WebKit是如何支持getUserMedia这个接口的。图11-23描述了WebKit,以及WebKit的Chromium移植中所定义的接口,图中虚线上半部分是WebKit中的类,下半部分是Chromium中的类。

                                图11-23 WebKit支持多媒体流的基础设施

        最上层是WebKit支持多媒体流编程接口提供的具体实现类,如NavigatorMediaStream类,而直接同V8 JavaScript引擎桥接的类是V8NavigatorUser-MediaSuccessCallback,它是一个绑定类。因为getUserMedia接口主要是返回一个MediaStream对象,而MediaStream类可以提供众多访问数据流的接口,而连接的目的就是需要将MediaStream对应的多媒体流传输出去。图中UserMediaRequest类负责请求创建一个MediaStream对象。在WebKit的Chromium移植中,定义WebUserMediaClient为一个接口类,Chromium需要新建子类来实现这一功能,这就是Chromium中的MediaStreamImpl类,它在后面的介绍中还会出现。

        WebKit中使用MediaStreamRegistry类来注册和管理对应的类,管理类根据ID信息来识别各个多媒体数据流。在接口层中,Chromium移植使用WebMediaStream类来表示多媒体流,使用WebMediaStreamRegistry类来表示注册管理类。

        下面的问题是MediaStream接口需要提供各种事件给网页,因为很多实际的工作是在Chromium中来完成的,所以MediaStreamImpl会将这些事件从Chromium传递给WebKit。同时因为Chromium的多进程和沙箱模型,一些工作需要在Browser进程中完成,所以可以见到如图11-24所描述的跨进程的基础设施。

                                图11-24 Chromium支持MediaStream接口基础设施

        IPC左侧部分是Browser进程中的两个主要类,分别是消息处理类和MediaStream的管理类,该管理类知道MediaStream对应的网页是什么,并将事件(如创建和销毁等)传回Renderer进程。右侧是消息派发类,主要帮助MediaStreamImpl类来完成与Browser进程相关的MediaStream消息的传递。

        实际上,MediaStream可以表示本地的多媒体流,也可以表示远端的多媒体流。对于本地的多媒体流,需要音频和视频的捕获机制,同时使用上面建立的连接传输给远端。对于远端的多媒体流,需要使用连接来接收数据,并使用到音频和视频的解码能力。下面分成四个部分来分别介绍。

        首先是音频的捕获机制,图11-25描述了该机制使用的主要类。当网页需要创建多媒体流的时候,MediaStreamImpl会创建音频捕获类,也就是WebRtcAudioCapturer类,如图中上半部分。因为捕获音频需要音频输入设备,所以使用AudioDeviceFactory工厂类创建一个逻辑上的AudioInputDevice对象。另外一个重要的类是WebRtcAudioDeviceImpl,用来表示音频的设备,该类继承自WebRtcAudioDeviceNotImpl类。这其实是继承自libjingle和WebRTC项目中的抽线接口的一个桥接类,用来表示它们需要的音频设备,当然包括输入设备。同样因为Renderer进程不能访问音频输入设备,所以需要IPC来完成这一功能,Browser进程的AudioInputController会控制和访问设备,而AudioInputDeviceManager可以管理和控制所有输入设备。

                                图11-25 Chromium本地捕获音频的基础设施

其次是处理远端多媒体流中的音频解码和播放功能。图11-26是Chromium处理远端音频流所需要的一些主要类及关系图。这里不涉及连接如何接收传输的数据,因为Chromium是使用libjingle和WebRTC项目来完成连接的功能。Chromium使用WebRtcAudioRender类来完成音频渲染,该桥接类会被WebMediaPlayer作为渲染音频的实现类,其作用主要是将MediaStream的数据同实际的音频渲染类结合起来。

                                图11-26 Chromium处理远端音频基础设施

再次是从视频输入设备请求捕获本地视频流,图11-27是该功能依赖的一些主要类。

                                图11-27 Chromium本地捕获视频的基础设施

        首先看虚线右侧Renderer进程中的设施。同样是MediaStreamImpl类发起,由辅助工厂类MeidaStreamDependencyFactory帮助创建一个RtcVideoCapaturer,用来获取视频。该类有两个作用,其一是实现libjingle和WebRTC项目中的接口类,因为需要视频输入的实现,这个同音频部分非常类似。另外就是将调用请求交给一个代理类来完成,这就是RtcVideoCaptureDelegate类。下面的就比较好理解了,分别是管理类VideoCaptureImplManager和视频捕获类VideoCaptureImpl,并包括一个发送消息到Browser进程的辅助类。在Browser进程使用控制类VideoCaptureController来获取VideoCaptureDevice,该类会使用摄像头等视频输入设备,效果都相对比较简单直观。

        最后是处理远端多媒体流中的视频解码和播放功能。当MediaStreamImpl对象接收到远端的多媒体流之后,它会使用WebRTC来对视频数据进行解码,因为可以使用硬件来解码,所以提高了处理的性能。

                                        图11-28 Chromium处理远端视频基础设施

把WebRTC整个过程综合起来分析,可以有一种更为整体和直观的感受,如图11-29所示。读者可以结合这个图来回味一下之前所描述的众多细节。图中没有本地捕获的音视频的播放过程,因为它们不是必须的,而且同播放远端多媒体流类似,这里便不再赘述。

                图11-29 WebKit、Chromium、libjingle和WebRTC等项目支持WebRTC规范的框架

        目前,在Chrome浏览器中,基于WebRTC的网页已经可以在移动操作系统(如Android)上获得支持,移动领域的进展必将推动该技术的进一步发展。回顾本章介绍的多媒体各个方面的技术,读者可以看出,HTML5技术不仅引入了多媒体的支持,而且加入了之前插件也不能支持的众多更新更复杂的技术,但是却极大提升了HTML5的应用范围。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/643622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【时间序列篇】基于LSTM的序列分类-Pytorch实现 part3 化为己用

系列文章目录 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part1 案例复现 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part2 自有数据集构建 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part3 化为己用 在一个人体姿态估计的任务中&#xff0c;需要用深度学习模型…

天天酷跑-C语言搭建童年游戏(easyx)

游戏索引 游戏名称&#xff1a;天天酷跑 游戏介绍&#xff1a; 本游戏是在B站博主<程序员Rock>的视频指导下完成 想学的更详细的小伙伴可以移步到<程序员Rock>视频 【程序员Rock】C语言项目&#xff1a;手写天天酷跑丨大一课程设计首选项目&#xff0c;手把手带你用…

【linux】Debian挂起和休眠

一、挂起和休眠 在Debian桌面系统中&#xff0c;挂起和休眠是两种不同的状态&#xff0c;它们之间有一些区别。 挂起&#xff08;Suspend&#xff09;是将当前系统的状态保存到RAM&#xff08;内存&#xff09;中&#xff0c;然后关闭所有硬件设备&#xff0c;除了RAM之外。在…

如何用H5+CSS+JS写一个简单的招聘网站

大家好&#xff0c;我是猿码叔叔&#xff0c;一个 Java 语言开发者。应网友要求&#xff0c;写一个简单的招聘页面。由于技术原因&#xff0c;页面相对简单&#xff0c;朋友们可以选择性的阅读&#xff0c;如果对您有帮助&#xff0c;也可直接拿去使用&#xff0c;因为接下来除…

数据分析的理念、流程、方法、工具(下)

四、用户分群 1、用户分群 用户分群是精细化运营的基础要求&#xff0c;也是数据分析的最基础方式。对用户进行分群&#xff0c;能帮助我们了解每个细分群体用户的变化情况&#xff0c;进而了解用户的整体现状及发展趋势。同时&#xff0c;由于运营资源本身有限&#xff0c;不…

技术变革下职业危机

方向一&#xff1a;技术变革 1.人工智能&#xff08;AI&#xff09;&#xff1a;AI技术的快速发展正在改变各个行业。AI在医疗诊断、金融分析、客户服务以及物流管理等方面都有广泛应用&#xff0c;提高了效率和准确性。但同时也引发了一些道德和道德问题&#xff0c;比如隐私…

玩法与画面全面升级,艾尔莎H311-PRO和你玩转《如龙8:无尽财富》

作为经典的日系开放式世界游戏系列&#xff0c;《如龙》至今已经推出了有十多部作品&#xff0c;它凭借着经典的日式RPG玩法吸引了不少忠实粉丝。早在2022年9月的时候&#xff0c;世嘉就已经公布了最新的正统续作《如龙8》&#xff0c;而在经历了一年半的等待以后&#xff0c;我…

jvs-rules(规则引擎)1.23功能更新说明,新增SQL变量、数据源等

规则引擎更新功能 新增: 1、新增SQL变量&#xff1a; SQL变量通常指的是在执行SQL查询时使用的动态变量。这些变量允许在查询中注入或更改某些值&#xff0c;以便根据不同的条件或输入执行不同的查询。 1.1 新增自定义SQL语言进行数据查询&#xff1b; 用户可以使用自定义的…

强化学习12——策略梯度算法学习

Q-learning、DQN算法是基于价值的算法&#xff0c;通过学习值函数、根据值函数导出策略&#xff1b;而基于策略的算法&#xff0c;是直接显示地学习目标策略&#xff0c;策略梯度算法就是基于策略的算法。 策略梯度介绍 将策略描述为带有参数 θ \theta θ 的连续函数&#…

Pycharm运行提示(运行‘Python测试(00.py内)‘(u)

为什么有时候我在pycharm中运行代码会出现图片中的问题&#xff1f; 我们该如何改过来&#xff1f; 很简单 点击文件-设置 点击Python集成工具&#xff0c;在默认测试运行程序里修改为Unittest即可 再次运行代码就会显示正常的运行 你的pycharm可能是英文 如何英文变中文&…

鸿蒙APP的应用场景

鸿蒙APP可以用于多种场合和设备类型&#xff0c;这是鸿蒙系统的分布式能力和多终端适配的优势。以下是一些鸿蒙APP的应用场景&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.智能手机和平板电脑&am…

开源:两个免费的年会抽奖项目

前言 年会抽奖项目平常基本不用&#xff0c;只有到年终才会排上用场。开发的时长也不会给太久&#xff0c;而且也只是自家公司内部使用的&#xff0c;所以不需要部署&#xff0c;数据库后端甚至都可以省略&#xff1b;然后我就找了个开源的 符合我要求的年会抽奖项目进行二次开…

CSS 图片遮罩学习小节

概念&#xff1a;-webkit-mask-image是一项用于制作镂空图形和图形遮罩效果的CSS样式属性。 -webkit-mask-image 的值既可以是渐变色也可以是图片地址。 -webkit-mask-image 的起源很早&#xff0c;但兼容性不好&#xff0c;因此用途并不广泛。 效果如下&#xff1a; 底图&…

Spring Security 6 学习-1

什么是 Spring Security Spring Security文档 Spring Security中文文档 Spring Security 是 Spring 家族中的安全型开发框架&#xff0c;主要解决三大方面问题&#xff1a;认证&#xff08;你是谁&#xff09;、授权&#xff08;你能干什么&#xff09;、常见攻击保护&#xff…

深度强化学习Task3:A2C、A3C算法

本篇博客是本人参加Datawhale组队学习第三次任务的笔记 【教程地址】 文章目录 Actor-Critic 算法提出的动机Q Actor-Critic 算法A2C 与 A3C 算法广义优势估计A3C实现建立Actor和Critic网络定义智能体定义环境训练利用JoyRL实现多进程 练习总结 Actor-Critic 算法提出的动机 蒙…

Tableau1 安装基础知识

参考内容&#xff1a; 戴师兄-戴你玩转数据分析菜菜菊花酱数据分析课程 1 安装注意事项 若下次打开发现软件损坏&#xff0c;可以重新安装&#xff1b;后期激活码可以去淘宝上购买&#xff08;选择1key两机&#xff09;&#xff1b;若买了1key1机的密钥&#xff0c;需要在两台…

深度学习记录--mini-batch gradient descent

batch vs mini-batch gradient descent batch&#xff1a;段&#xff0c;块 与传统的batch梯度下降不同&#xff0c;mini-batch gradient descent将数据分成多个子集&#xff0c;分别进行处理&#xff0c;在数据量非常巨大的情况下&#xff0c;这样处理可以及时进行梯度下降&…

力扣精选算法100题——在排序数组中查找元素的第一个和最后一个位置(二分查找专题)

目录 第一步&#xff1a;了解题意 第二步&#xff1a;算法原理 &#x1f6a9;查找区间左端点值 ❗处理细节 循环条件&#xff1a; 求中点 &#x1f6a9;查找区间右端点值 ❗处理细节 循环条件 求中点 &#x1f6a9;总结 第三步&#xff1a;代码实现 第四步:总结模…

OpenHarmony 鸿蒙使用指南——概述

简介 OpenHarmony采用多内核&#xff08;Linux内核或者LiteOS&#xff09;设计&#xff0c;支持系统在不同资源容量的设备部署。当相同的硬件部署不同内核时&#xff0c;如何能够让设备驱动程序在不同内核间平滑迁移&#xff0c;消除驱动代码移植适配和维护的负担&#xff0c;…

技术驱动宠物健康:宠物在线问诊系统的高效搭建手册

在数字化时代&#xff0c;技术正在催生出许多创新的医疗服务&#xff0c;而宠物在线问诊系统便是其中一项引领潮流的创举。本文将为你提供一份高效搭建宠物在线问诊系统的手册&#xff0c;通过技术代码示例&#xff0c;让你轻松打造一套技术驱动的宠物健康管理系统。 1. 架构…