WebRTC 服務器之Janus視頻會議插件信令交互

?1.基礎知識回顧

WebRTC 服務器之Janus概述和環境搭建-CSDN博客

WebRTC 服務器之Janus架構分析-CSDN博客

2.插件使用流程

我們要使?janus的功能時,通常要執?以下操作:

1. 在你的??引入 Janus.js 庫,即是包含janus.js;

<!-- 網頁頭部或 body 底部引入 -->
<script src="https://your-cdn-path/janus.js"></script>

2. 初始化 Janus 庫,并傳遞其依賴項(依賴項可選);

Janus.init({debug: true,    // 開啟調試日志dependencies: {// 可選依賴(如 adapter.js 用于跨瀏覽器兼容)adapter: adapter},callback: function() {console.log("Janus 庫初始化完成");// 初始化完成后連接服務器connectToJanusServer();}
});

3. 連接服務器 & 創建會話?連接到janus server并創建create?個會話session;

let janusSession;function connectToJanusServer() {const serverUrl = "wss://your-janus-server:8989/janus";new Janus({server: serverUrl,success: function(session) {janusSession = session;console.log("會話創建成功:", session.getId());// 創建插件句柄(例如加入視頻房間)attachToVideoRoomPlugin();},error: function(error) {console.error("連接失敗:", error);}});
}

4. 創建插件句柄 (Handle)?創建?個或多個handle 以attach到插件(plugin)(例如videoroom、videocall等插件);

let pluginHandle;function attachToVideoRoomPlugin() {janusSession.attach({plugin: "janus.plugin.videoroom",  // 插件名稱success: function(handle) {pluginHandle = handle;console.log("成功附加到插件,句柄 ID:", handle.getId());// 發送加入房間請求joinVideoRoom();},error: function(error) {console.error("附加插件失敗:", error);}});
}

5. 信令交互示例 - 加入視頻房間?與創建交互(發送/接收消息,協商PeerConnection);

function joinVideoRoom() {const joinMsg = {request: "join",room: 1234,       // 房間 IDptype: "publisher",display: "用戶1"};pluginHandle.send({ message: joinMsg });
}// 處理服務器事件(如房間通知)
pluginHandle.on("message", (msg, jsep) => {console.log("收到服務器消息:", msg);if (msg["videoroom"] === "joined") {console.log("成功加入房間!");// 處理媒體協商(如創建 Offer)startWebRTCNegotiation();}
});

6. ?WebRTC 協商流程?

function startWebRTCNegotiation() {// 創建媒體配置const mediaConfig = {audio: true,video: true,data: true};// 準備 PeerConnectionpluginHandle.createOffer({media: mediaConfig,success: function(sdp) {// 發送 SDP OfferpluginHandle.sendSDP(sdp);},error: function(error) {console.error("創建 Offer 失敗:", error);}});
}// 處理 ICE Candidate
pluginHandle.on("ice", (candidate) => {// 發送候選到服務器pluginHandle.trickle(candidate);
});

7. 最后 關閉所有的handles并關閉相關的相應的PeerConnections;?消耗destroy會話session。

function cleanup() {// 1. 銷毀插件句柄if (pluginHandle) {pluginHandle.detach();pluginHandle = null;}// 2. 銷毀會話if (janusSession) {janusSession.destroy();janusSession = null;}
}// 頁面關閉時觸發清理
window.onbeforeunload = cleanup;

?完整流程總結

  1. 初始化

    Janus.init({ debug: true, callback: createJanusSession });
  2. 會話與插件

    創建會話 (createSession) → 創建插件句柄 (createHandle) → 注冊事件監聽 (eventHandler).?
  3. 信令交互

    發送消息 (sendMessage) 加入房間 → 接收服務器事件 (handleEvent).
  4. WebRTC 協商

    創建 Offer (createOffer) → 發送 SDP (sendSDP) → 接收 Answer → 創建 Answer (createAnswer).
  5. 收發av數據

  6. 資源釋放

    銷毀句柄 (destroyHandle) → 銷毀會話 (destroySession).

2.1 協議基本類型

"janus"后?的字符串代表消息的類型,主要有:

  1. create:創建?個Janus會話命令;
  2. attach:attach?個插件到Janus會話命令;
  3. success:?個命令的成功結果;
  4. error:?個命令的失敗結果;
  5. ack:?個命令的ack,因為不能直接返回結果,先回ack,后續的結果通過event返回;
  6. event:推送給客戶端的異步事件,主要由插件發出,這些事件需要插件來??定義;
  7. message:客戶端發給插件的消息,message和event就構成了應?協議;
  8. trickle:客戶端發送的candidate,會傳遞給ICE句柄;
  9. keepalive:客戶端發送的?跳;
  10. webrtcup:ICE成功建?通道的通知;
  11. media:?頻、視頻媒體的接收通知;
  12. slowlink:鏈路惡化通知;
  13. hangup:掛斷通知;
  14. detached:插件從Janus會話detach的通知,釋放了?個插件句柄。

3.videoroom插件信令交互分析

Janus中所有插件都遵循以下基本數據流程:

  1. 客戶端發送create創建一個Janus會話;
  2. Janus回復success返回Janus會話句柄
  3. 客戶端發送attach命令在Janus會話上attach指定插件;
  4. Janus回復success返回插件的句柄
  5. 客戶端給指定的插件發送message進行信令控制;
  6. Janus上的插件發送event通知事件給客戶端;
  7. 客戶端收集candidate并通過trickle消息發送給插件綁定的ICE通道;
  8. Janus發送webrtcup通知ICE通道建立;
  9. 客戶端發送媒體數據;
  10. Janus發送media消息通知媒體數據的第一次到達;
  11. Janus進行媒體數據轉發。

    3.總體邏輯

    ?

    1. Janus客戶端->Janus網關: Janus客戶端發送create請求創建會話
      • JBJ-WEBSOCKET RECV: {"janus":"create","transaction":"aAMxRfsTsVVQ"}
        
    2. Janus網關–>>Janus客戶端: Janus網關創建會話,并返回會話IDJ
      1. JBJ-WEBSOCKET responses:Sending Janus API response(
        {"janus": "success","transaction": "aAMxRfsTsVVQ","data": {"id": 5109637625847547}
        }
        ) to janus.transport.websockets (0x7f5cd400d3c0)
    3. Janus客戶端->Janus網關: 客戶端發送attach命令在Janus會話上attach指定插件
      1. JBJ-WEBSOCKET RECV: {"janus": "attach","plugin": "janus.plugin.videoroom","opaque_id": "videoroomtest-jIAzP2ZkPUrn","transaction": "2kuM6pzfX4Zh","session_id": 5109637625847547
        }

    4. Janus網關–>>Janus客戶端:? Janus回復success返回插件的句柄
      1. 
        JBJ-WEBSOCKET responses:Sending Janus API response({"janus": "success","session_id": 5109637625847547,"transaction": "2kuM6pzfX4Zh","data": {"id": 6769547295474368}
        }) to janus.transport.websockets (0x7f5cd400d3c0)

    5. Janus客戶端->Janus網關:?Janus客戶端給指定插件發送message(Join)
      1. JBJ-WEBSOCKET RECV: {"janus": "message","body": {"request": "join","room": 1234,"ptype": "publisher","display": "321"},"transaction": "11JDzIbsbK91","session_id": 5109637625847547,"handle_id": 6769547295474368
        }
        
        JBJ-WEBSOCKET responses:Sending Janus API response({"janus": "ack","session_id": 5109637625847547,"transaction": "11JDzIbsbK91"
        }) to janus.transport.websockets (0x7f5cd400d3c0)

    6. Janus網關–>>Janus客戶端: Janus網關處理message,并將結果通過event事件發送給客戶端
      1. Preparing JSON event as a reply
        JBJ-video.room.event: [6769547295474368] Sending event is: {"janus": "event","session_id": 5109637625847547,"transaction": "11JDzIbsbK91","sender": 6769547295474368,"plugindata": {"plugin": "janus.plugin.videoroom","data": {"videoroom": "joined","room": 1234,"description": "Demo Room","id": 6538458198168085,"private_id": 1041514801,"publishers": []}}} to transport...
        Sending event to janus.transport.websockets (0x7f5cd400d3c0)>> 0 (Success)

    7. Janus客戶端->Janus網關: Janus客戶端給指定插件發送message(Configure & offer)
      1. ####################Configure & offer
        JBJ-WEBSOCKETRECV: {"janus": "message","body": {"request": "configure","audio": true,"video": true},"transaction": "MHTliRCHqY5y","jsep": {"type": "offer","sdp": "v=0\r\no=- 6239954181818903803 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=extmap-allow-mixed\r\na=msid-semantic: WMS 900722df-7e7a-4951-b1bf-1902cb7fe6e0\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:eHT/\r\na=ice-pwd:aAxznBSHiqTXMkZAzJs5xv3B\r\na=ice-options:trickle\r\na=fingerprint:sha-256 75:80:26:F9:EB:47:14:51:61:D3:CD:8B:60:C1:5E:F5:67:53:1E:88:9C:45:53:3B:32:D0:D2:5F:CD:45:63:7F\r\na=setup:actpass\r\na=mid:0\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=sendonly\r\na=msid:900722df-7e7a-4951-b1bf-1902cb7fe6e0 9718362e-2152-4c32-9e79-da62a8a609c5\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:63 red/48000/2\r\na=fmtp:63 111/111\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:2665350871 cname:+3Rknr5a6Axa5msx\r\na=ssrc:2665350871 msid:900722df-7e7a-4951-b1bf-1902cb7fe6e0 9718362e-2152-4c32-9e79-da62a8a609c5\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97 103 104 107 108 109 114 115 116 117 118 39 40 45 46 98 99 100 101 119 120 123 124 125\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:eHT/\r\na=ice-pwd:aAxznBSHiqTXMkZAzJs5xv3B\r\na=ice-options:trickle\r\na=fingerprint:sha-256 75:80:26:F9:EB:47:14:51:61:D3:CD:8B:60:C1:5E:F5:67:53:1E:88:9C:45:53:3B:32:D0:D2:5F:CD:45:63:7F\r\na=setup:actpass\r\na=mid:1\r\na=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:13 urn:3gpp:video-orientation\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\na=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\na=sendonly\r\na=msid:900722df-7e7a-4951-b1bf-1902cb7fe6e0 d97d2702-4a0f-4693-8499-71c66f8c03fe\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 transport-cc\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=rtpmap:103 H264/90000\r\na=rtcp-fb:103 goog-remb\r\na=rtcp-fb:103 transport-cc\r\na=rtcp-fb:103 ccm fir\r\na=rtcp-fb:103 nack\r\na=rtcp-fb:103 nack pli\r\na=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\r\na=rtpmap:104 rtx/90000\r\na=fmtp:104 apt=103\r\na=rtpmap:107 H264/90000\r\na=rtcp-fb:107 goog-remb\r\na=rtcp-fb:107 transport-cc\r\na=rtcp-fb:107 ccm fir\r\na=rtcp-fb:107 nack\r\na=rtcp-fb:107 nack pli\r\na=fmtp:107 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f\r\na=rtpmap:108 rtx/90000\r\na=fmtp:108 apt=107\r\na=rtpmap:109 H264/90000\r\na=rtcp-fb:109 goog-remb\r\na=rtcp-fb:109 transport-cc\r\na=rtcp-fb:109 ccm fir\r\na=rtcp-fb:109 nack\r\na=rtcp-fb:109 nack pli\r\na=fmtp:109 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:114 rtx/90000\r\na=fmtp:114 apt=109\r\na=rtpmap:115 H264/90000\r\na=rtcp-fb:115 goog-remb\r\na=rtcp-fb:115 transport-cc\r\na=rtcp-fb:115 ccm fir\r\na=rtcp-fb:115 nack\r\na=rtcp-fb:115 nack pli\r\na=fmtp:115 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f\r\na=rtpmap:116 rt
        }JBJ-video.room.event: [6769547295474368] Sending event is: {"janus": "event","session_id": 5109637625847547,"transaction": "MHTliRCHqY5y","sender": 6769547295474368,"plugindata": {"plugin": "janus.plugin.videoroom","data": {"videoroom": "event","room": 1234,"configured": "ok","audio_codec": "opus","video_codec": "vp8"}},"jsep": {"type": "answer","sdp": "v=0\r\no=- 6239954181818903803 2 IN IP4 117.72.13.81\r\ns=VideoRoom 1234\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS janus\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 117.72.13.81\r\na=recvonly\r\na=mid:0\r\na=rtcp-mux\r\na=ice-ufrag:0pFN\r\na=ice-pwd:wGcEE+9WQLoHULcXGP8KFn\r\na=ice-options:trickle\r\na=fingerprint:sha-256 C7:C1:43:EE:67:07:A0:6D:42:33:6A:CA:4E:EA:95:E0:55:17:03:CB:88:FD:B6:37:AB:1C:7B:85:65:9A:95:C6\r\na=setup:active\r\na=rtpmap:111 opus/48000/2\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=msid:janus janusa0\r\na=ssrc:3338353236 cname:janus\r\na=ssrc:3338353236 msid:janus janusa0\r\na=ssrc:3338353236 mslabel:janus\r\na=ssrc:3338353236 label:janusa0\r\na=candidate:1 1 udp 2013266431 117.72.13.81 53576 typ host\r\na=candidate:2 1 udp 1677722111 117.72.13.81 53576 typ srflx raddr 172.16.0.4 rport 53576\r\na=candidate:3 1 udp 503316991 172.16.0.4 54497 typ relay raddr 172.16.0.4 rport 53576\r\na=end-of-candidates\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\r\nc=IN IP4 117.72.13.81\r\na=recvonly\r\na=mid:1\r\na=rtcp-mux\r\na=ice-ufrag:0pFN\r\na=ice-pwd:wGcEE+9WQLoHULcXGP8KFn\r\na=ice-options:trickle\r\na=fingerprint:sha-256 C7:C1:43:EE:67:07:A0:6D:42:33:6A:CA:4E:EA:95:E0:55:17:03:CB:88:FD:B6:37:AB:1C:7B:85:65:9A:95:C6\r\na=setup:active\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 transport-cc\r\na=extmap:13 urn:3gpp:video-orientation\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\na=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=msid:janus janusv0\r\na=ssrc:3467980833 cname:janus\r\na=ssrc:3467980833 msid:janus janusv0\r\na=ssrc:3467980833 mslabel:janus\r\na=ssrc:3467980833 label:janusv0\r\na=ssrc:3074101642 cname:janus\r\na=ssrc:3074101642 msid:janus janusv0\r\na=ssrc:3074101642 mslabel:janus\r\na=ssrc:3074101642 label:janusv0\r\na=candidate:1 1 udp 2013266431 117.72.13.81 53576 typ host\r\na=candidate:2 1 udp 1677722111 117.72.13.81 53576 typ srflx raddr 172.16.0.4 rport 53576\r\na=candidate:3 1 udp 503316991 172.16.0.4 54497 typ relay raddr 172.16.0.4 rport 53576\r\na=end-of-candidates\r\n"}
        }#######################trickle
        JBJ-WEBSOCKET RECV: {"janus": "trickle","candidate": {"candidate": "candidate:980779705 1 udp 2122260223 192.168.126.1 60475 typ host generation 0 ufrag eHT/ network-id 2","sdpMid": "0","sdpMLineIndex": 0},"transaction": "0WWSoZXbCxhA","session_id": 5109637625847547,"handle_id": 6769547295474368
        }JBJ-WEBSOCKET RECV: {"janus": "trickle","candidate": {"candidate": "candidate:3993315412 1 udp 2122194687 192.168.248.1 60476 typ host generation 0 ufrag eHT/ network-id 3","sdpMid": "0","sdpMLineIndex": 0},"transaction": "DddvxlDlWuZN","session_id": 5109637625847547,"handle_id": 6769547295474368
        }
        JBJ-WEBSOCKET RECV: {"janus": "trickle","candidate": {"candidate": "candidate:2923601174 1 udp 2122129151 172.25.0.107 60477 typ host generation 0 ufrag eHT/ network-id 1 network-cost 10","sdpMid": "0","sdpMLineIndex": 0},"transaction": "HCdvw7ihHaaZ","session_id": 5109637625847547,"handle_id": 6769547295474368
        }
    8. Janus網關–>>Janus客戶端: Janus網關返回ack消息
      1. JBJ-WEBSOCKET responses:Sending Janus API response({"janus": "ack","session_id": 5109637625847547,"transaction": "MHTliRCHqY5y"
        }) to janus.transport.websockets (0x7f5cd400d3c0)JBJ-WEBSOCKET responses:Sending Janus API response({"janus": "ack","session_id": 5109637625847547,"transaction": "0WWSoZXbCxhA"
        }) to janus.transport.websockets (0x7f5cd400d3c0)JBJ-WEBSOCKET responses:Sending Janus API response({"janus": "ack","session_id": 5109637625847547,"transaction": "DddvxlDlWuZN"
        }) to janus.transport.websockets (0x7f5cd400d3c0)

    學習資料分享

    0voice · GitHub

    ?

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/pingmian/79423.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79423.shtml
    英文地址,請注明出處:http://en.pswp.cn/pingmian/79423.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Go語言中的無鎖數據結構與并發效率優化

    1. 引言 在高并發系統開發中&#xff0c;性能瓶頸往往出現在并發控制上。作為一個有著10年Go開發經驗的后端工程師&#xff0c;我見證了無數因鎖競爭導致的性能問題&#xff0c;也親歷了無鎖編程為系統帶來的巨大提升。 傳統的鎖機制就像是十字路口的紅綠燈——雖然能確保安全…

    STM32部分:2、環境搭建

    飛書文檔https://x509p6c8to.feishu.cn/wiki/DQsBw76bCiWaO4kS8TXcWDs0nAh Keil MDK用于編寫代碼&#xff0c;編譯代碼芯片支持包&#xff0c;用于支持某類芯片編程支持STM32CubeMX用于自動生成工程&#xff0c;減少手動重復工作 STM32F1系列芯片支持包 軟件下載 直接下載&am…

    U3D工程師簡歷模板

    模板信息 簡歷范文名稱&#xff1a;U3D工程師簡歷模板&#xff0c;所屬行業&#xff1a;其他 | 職位&#xff0c;模板編號&#xff1a;B29EPQ 專業的個人簡歷模板&#xff0c;邏輯清晰&#xff0c;排版簡潔美觀&#xff0c;讓你的個人簡歷顯得更專業&#xff0c;找到好工作。…

    Java設計模式: 實戰案例解析

    Java設計模式: 實戰案例解析 在軟件開發中&#xff0c;設計模式是一種用來解決特定問題的可復用解決方案。它們是經過實踐驗證的最佳實踐&#xff0c;能夠幫助開發人員設計出高質量、易于維護的代碼。本文將介紹一些常見的Java設計模式&#xff0c;并通過實戰案例解析它們在實際…

    Vue3源碼學習5-不使用 `const enum` 的原因

    文章目錄 前言? 什么是 const enum? 為什么 Vue 3 不使用 const enum1. &#x1f4e6; **影響構建工具兼容性**2. &#x1f501; **難以做模塊間 tree-shaking**3. &#x1f9ea; **調試困難**4. &#x1f4e6; **Vue 是庫&#xff0c;不掌控用戶配置** ? 官方推薦做法&…

    C++學習:六個月從基礎到就業——C++11/14:lambda表達式

    C學習&#xff1a;六個月從基礎到就業——C11/14&#xff1a;lambda表達式 本文是我C學習之旅系列的第四十篇技術文章&#xff0c;也是第三階段"現代C特性"的第二篇&#xff0c;主要介紹C11/14中引入的lambda表達式。查看完整系列目錄了解更多內容。 引言 Lambda表達…

    AIDC智算中心建設:計算力核心技術解析

    目錄 一、智算中心發展概覽 二、計算力核心技術解析 一、智算中心發展概覽 智算中心是人工智能發展的關鍵基礎設施&#xff0c;基于人工智能計算架構&#xff0c;提供人工智能應用所需算力服務、數據服務和算法服務的算力基礎設施&#xff0c;融合高性能計算設備、高速網絡以…

    IoTDB時序數據庫V2.0.2大版本更新的一些梳理

    一些小知識&#xff1a; 關于事務&#xff1a;時序數據庫是沒有事務的&#xff0c;它和關系數據庫的應用場景不同&#xff0c;通常情況下不需要多點同時操作同一條數據&#xff0c;而且要保證極高的吐出量&#xff0c;事務太消耗資源&#xff0c;并且時序數據庫提供了覆寫的功能…

    CSS定位詳解

    在前端開發中&#xff0c;CSS 定位&#xff08;positioning&#xff09;是一個核心概念&#xff0c;它決定了元素在頁面上的位置和布局方式。無論是構建復雜的交互界面&#xff0c;還是實現簡單的頁面排版&#xff0c;CSS 定位都是不可或缺的工具。本文將全面介紹 CSS 中的五種…

    React 語法擴展

    useReducer鉤子函數 不同action類型返回不同處理行為 useState()函數返回解構為兩個值 state當前狀態 dispatch修改狀態函數 dispatch()函數參數為一個actuon對象 如 &#xff1a; 樣例&#xff1a; import { useReducer } from react; import ./App.css;// 定義一個Reduce…

    MCP協議與Dify集成教程

    一、MCP協議概述 MCP&#xff08;Model Control Protocol&#xff09;是一種新興的開放協議&#xff0c;為大型語言模型&#xff08;LLM&#xff09;與外部應用之間構建了雙向通信通道。它就像是AI的"USB-C"接口&#xff0c;幫助模型發現、理解并安全調用各種外部工…

    學習springboot-條件化配置@Conditional(條件注解)

    前言 在Spring Boot中&#xff0c;Conditional 注解及其相關注解是用于條件化配置的重要工具。它們允許開發者根據特定條件決定是否加載某個Bean或配置類。 注意&#xff1a;Conditional 相關注解&#xff0c;通常和Bean搭配使用 學習springboot-Bean管理&#xff08;Bean 注…

    2025年- H18-Lc126-54.螺旋矩陣(矩陣)---java版

    1.題目描述 2.思路* 思路1&#xff1a; 補充2&#xff1a; directions[1][0] // 表示“下”這個方向的行增量&#xff08;1&#xff09; directions[1][1] // 表示“下”這個方向的列增量&#xff08;0&#xff09; int[][] directions {{0, 1}, {1, 0}, {0, -1}, {-…

    微信小程序連續多個特殊字符自動換行解決方法

    效果圖 .wxml <view class"container"><text>沒轉換{{text}}</text><view style"height: 60rpx;" /><text>轉換后{{convert}}</text> </view>.js Page({data: {text:&#xff01;&#xff01;&#xff01;&am…

    編程速遞-RAD Studio 12.3 Athens四月補丁:關注軟件性能的開發者,安裝此補丁十分必要

    2025年4月22日&#xff0c;Embarcadero發布了針對RAD Studio 12.3、Delphi 12.3以及CBuilder 12.3的四月補丁。此更新旨在提升這些產品的質量&#xff0c;特別關注于Delphi編譯器、C 64位現代工具鏈、RAD Studio 64位IDE及其調試器、VCL庫和其他RAD Studio特性。強烈建議所有使…

    Linux 進程基礎(二):操作系統

    目錄 一、什么是操作系統&#xff1a;用戶和電腦之間的「翻譯官」&#x1f310; OS 的層狀結構&#x1f9e9; 案例解析&#xff1a;雙擊鼠標的「跨層之旅」 二、操作系統的必要性探究&#xff1a;缺乏操作系統的環境面臨的挑戰剖析&#x1f511; OS 的「管理者」屬性&#xff1…

    第 11 屆藍橋杯 C++ 青少組中 / 高級組省賽 2020 年真題,選擇題詳細解釋

    一、選擇題 第 2 題 在二維數組按行優先存儲的情況下&#xff0c;元素 a[i][j] 前的元素個數計算如下&#xff1a; 1. **前面的完整行**&#xff1a;共有 i 行&#xff0c;每行 n 個元素&#xff0c;總計 i * n 個元素。 2. **當前行的前面元素**&#xff1a;在行內&#x…

    1??7??three.js_OrbitControls相機控制器

    17、相機軌道控制器 3D虛擬工廠在線體驗相機軌道控制器OrbitControls 它是 Three.js 中最常用的交互控制器之一,專門用于通過鼠標/觸摸控制相機圍繞一個目標點(target)旋轉、縮放和平移。import {OrbitControls } from three/addons/controls/OrbitControls.js; const cont…

    以下是在 Ubuntu 上的幾款PDF 閱讀器,涵蓋輕量級、功能豐富和特色工具:

    默認工具&#xff1a;Evince&#xff08;GNOME 文檔查看器&#xff09; 特點&#xff1a;Ubuntu 預裝&#xff0c;輕量快速&#xff0c;支持基本標注和書簽。 安裝&#xff1a;已預裝&#xff0c;或手動安裝&#xff1a; sudo apt install evince功能全面&#xff1a;Okular&…

    基于用戶場景的汽車行駛工況構建:數據驅動下的能耗優化革命

    行業現狀&#xff1a;標準工況與用戶場景的割裂 全球汽車行業普遍采用WLTC工況進行能耗測試&#xff0c;但其與真實道路場景差異顯著。據研究&#xff0c;WLTC工況下車輛能耗數據比實際道路低10%-30%&#xff0c;導致用戶對續航虛標投訴激增&#xff08;數據來源&#xff1a;東…