diff --git a/package-lock.json b/package-lock.json index 255d2a1..2db8880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "react-redux": "^9.2.0", "react-router-dom": "^7.14.1", "recharts": "^3.8.1", + "socket.io-client": "^4.8.3", "tailwind-merge": "^3.5.0", "vite": "^6.2.0", "vite-plugin-cesium": "^1.2.23", @@ -2015,6 +2016,12 @@ "win32" ] }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, "node_modules/@spz-loader/core": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@spz-loader/core/-/core-0.3.1.tgz", @@ -3838,6 +3845,28 @@ "node": ">= 0.8" } }, + "node_modules/engine.io-client": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz", + "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.18.3", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.20.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", @@ -6677,6 +6706,34 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/socket.io-client": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", + "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7745,6 +7802,35 @@ "node": ">=8" } }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index efe5147..af51d0b 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "react-redux": "^9.2.0", "react-router-dom": "^7.14.1", "recharts": "^3.8.1", + "socket.io-client": "^4.8.3", "tailwind-merge": "^3.5.0", "vite": "^6.2.0", "vite-plugin-cesium": "^1.2.23", diff --git a/src/components/AgoraRtc.tsx b/src/components/AgoraRtc.tsx index 98a246a..d48c4ff 100644 --- a/src/components/AgoraRtc.tsx +++ b/src/components/AgoraRtc.tsx @@ -1,33 +1,47 @@ -import React, { useEffect, useState } from "react"; -import AgoraRTC, { - IMicrophoneAudioTrack, -} from "agora-rtc-sdk-ng"; +import React, { + useEffect, + useRef, + useState, +} from "react"; + +import AgoraRTC from "agora-rtc-sdk-ng"; import { Button, + Input, Card, Badge, message, + Space, } from "antd"; +import { io } from "socket.io-client"; + const APP_ID = "62a87b833b7e48888aca06b625f88c14"; const CHANNEL = "test_rtc_channel"; -const TOKEN = - "007eJxTYGhZyLP1Ekt5av/jV1mPpi98fG75FqcXvDl7/wuUJjNeEVukwGBmlGhhnmRhbJxknmpiAQSJyYkGZklmRqZpFhbJhiYfZjJlNQQyMrDxcrIwMkAgiC/AUJJaXBJfVJIcn5yRmJeXmsPAAABcCyR4"; +const TOKEN = "007eJxTYGhZyLP1Ekt5av/jV1mPpi98fG75FqcXvDl7/wuUJjNeEVukwGBmlGhhnmRhbJxknmpiAQSJyYkGZklmRqZpFhbJhiYfZjJlNQQyMrDxcrIwMkAgiC/AUJJaXBJfVJIcn5yRmJeXmsPAAABcCyR4"; const client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8", }); -export default function AgoraRtcTest() { +// websocket +const socket = + io("http://localhost:3001"); + +export default function AgoraRtcRoom() { const [uid] = useState(() => - String(Math.floor(Math.random() * 100000)) + String( + Math.floor( + Math.random() * 100000 + ) + ) ); const [connected, setConnected] = @@ -36,8 +50,17 @@ export default function AgoraRtcTest() { const [published, setPublished] = useState(false); - const [remoteUsers, setRemoteUsers] = - useState([]); + const [msg, setMsg] = + useState(""); + + const [msgList, setMsgList] = + useState([]); + + const localVideoRef = + useRef(null); + + const remoteVideoRef = + useRef(null); useEffect(() => { @@ -45,24 +68,40 @@ export default function AgoraRtcTest() { try { - // 连接状态 + // websocket 加入房间 + socket.emit( + "join-room", + CHANNEL + ); + + // 收消息 + socket.on( + "receive-message", + (data) => { + + setMsgList(prev => [ + ...prev, + `${data.uid}: ${data.message}` + ]); + } + ); + + // rtc 状态 client.on( "connection-state-change", (state) => { console.log( - "连接状态:", state ); if ( - state === "CONNECTED" + state === + "CONNECTED" ) { - setConnected(true); - - message.success( - "RTC 已连接" + setConnected( + true ); } } @@ -71,10 +110,13 @@ export default function AgoraRtcTest() { // 远端用户发布 client.on( "user-published", - async (user, mediaType) => { + async ( + user, + mediaType + ) => { console.log( - "收到远端流:", + "远端发布", user.uid, mediaType ); @@ -84,40 +126,29 @@ export default function AgoraRtcTest() { mediaType ); + // 视频 if ( - mediaType === "audio" + mediaType === + "video" ) { - user.audioTrack?.play(); - - message.success( - `收到用户 ${user.uid} 音频流` + user.videoTrack?.play( + remoteVideoRef.current! ); } - setRemoteUsers([ - ...client.remoteUsers - ]); + // 音频 + if ( + mediaType === + "audio" + ) { + + user.audioTrack?.play(); + } } ); - // 用户离开 - client.on( - "user-left", - (user) => { - - console.log( - "用户离开:", - user.uid - ); - - setRemoteUsers([ - ...client.remoteUsers - ]); - } - ); - - // 加入频道 + // 加入 rtc await client.join( APP_ID, CHANNEL, @@ -125,17 +156,15 @@ export default function AgoraRtcTest() { uid ); - console.log( - "加入频道成功" + setConnected(true); + + message.success( + "RTC 已连接" ); } catch (err) { console.error(err); - - message.error( - "初始化失败" - ); } }; @@ -144,6 +173,8 @@ export default function AgoraRtcTest() { return () => { client.leave(); + + socket.disconnect(); }; }, []); @@ -154,32 +185,34 @@ export default function AgoraRtcTest() { try { - // 创建麦克风轨道 - const micTrack: - IMicrophoneAudioTrack = + // 创建音频轨道 + const audioTrack = await AgoraRTC.createMicrophoneAudioTrack(); - // 推流 + // 创建视频轨道 + const videoTrack = + await AgoraRTC.createCameraVideoTrack(); + + // 本地播放 + videoTrack.play( + localVideoRef.current! + ); + + // 发布 await client.publish([ - micTrack + audioTrack, + videoTrack, ]); - console.log( - "推流成功" - ); - - message.success( - "开始推流" - ); - setPublished(true); + message.success( + "推流成功" + ); + } catch (err) { - console.error( - "推流失败:", - err - ); + console.error(err); message.error( "推流失败" @@ -187,29 +220,47 @@ export default function AgoraRtcTest() { } }; + // 发消息 + const sendMessage = + () => { + + if (!msg) return; + + socket.emit( + "send-message", + { + roomId: + CHANNEL, + uid, + message: + msg, + } + ); + + setMsg(""); + }; + return ( -
- 当前 UID:{uid} -
-
+
+ UID:{uid} +
-
- -
- - + > + 开始音视频推流 + -
+
- +
-
- -

- 远端用户: -

- - {remoteUsers.map( - (user) => ( +

+ 本地视频 +

- 用户: - {user.uid} -
- ) - )} + ref={ + localVideoRef + } + style={{ + width: 320, + height: 240, + background: + "#000", + }} + /> -
+
+ +
+ +

+ 远端视频 +

+ +
+ +
+ +
+ +
+ +

+ 聊天 +

+ + + + + setMsg( + e.target.value + ) + } + style={{ + width: 300, + }} + /> + + + + + +
+ + {msgList.map( + ( + item, + index + ) => ( + +
+ { + item + } +
+ ) + )} + +
+ +
+ + );