推拉流视频成功
This commit is contained in:
86
package-lock.json
generated
86
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<any[]>([]);
|
||||
const [msg, setMsg] =
|
||||
useState("");
|
||||
|
||||
const [msgList, setMsgList] =
|
||||
useState<string[]>([]);
|
||||
|
||||
const localVideoRef =
|
||||
useRef<HTMLDivElement>(null);
|
||||
|
||||
const remoteVideoRef =
|
||||
useRef<HTMLDivElement>(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 (
|
||||
|
||||
<Card
|
||||
title="Agora RTC 推拉流测试"
|
||||
title="Agora RTC 音视频 + 聊天"
|
||||
style={{
|
||||
width: 700,
|
||||
margin: "30px auto",
|
||||
width: 1000,
|
||||
margin:
|
||||
"20px auto",
|
||||
}}
|
||||
>
|
||||
|
||||
<div
|
||||
<Space
|
||||
direction="vertical"
|
||||
style={{
|
||||
marginBottom: 12,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
当前 UID:{uid}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 12,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
UID:{uid}
|
||||
</div>
|
||||
|
||||
<Badge
|
||||
color={
|
||||
@@ -224,63 +275,132 @@ export default function AgoraRtcTest() {
|
||||
}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 20,
|
||||
}}
|
||||
>
|
||||
|
||||
<Badge
|
||||
color={
|
||||
published
|
||||
? "green"
|
||||
: "orange"
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={
|
||||
startPublish
|
||||
}
|
||||
text={
|
||||
disabled={
|
||||
published
|
||||
? "已推流"
|
||||
: "未推流"
|
||||
}
|
||||
/>
|
||||
>
|
||||
开始音视频推流
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: 20,
|
||||
}}
|
||||
>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={startPublish}
|
||||
disabled={
|
||||
!connected ||
|
||||
published
|
||||
}
|
||||
>
|
||||
开始推流
|
||||
</Button>
|
||||
<div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginTop: 30,
|
||||
}}
|
||||
>
|
||||
|
||||
<h3>
|
||||
远端用户:
|
||||
</h3>
|
||||
|
||||
{remoteUsers.map(
|
||||
(user) => (
|
||||
<h3>
|
||||
本地视频
|
||||
</h3>
|
||||
|
||||
<div
|
||||
key={user.uid}
|
||||
>
|
||||
用户:
|
||||
{user.uid}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
ref={
|
||||
localVideoRef
|
||||
}
|
||||
style={{
|
||||
width: 320,
|
||||
height: 240,
|
||||
background:
|
||||
"#000",
|
||||
}}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
远端视频
|
||||
</h3>
|
||||
|
||||
<div
|
||||
ref={
|
||||
remoteVideoRef
|
||||
}
|
||||
style={{
|
||||
width: 320,
|
||||
height: 240,
|
||||
background:
|
||||
"#000",
|
||||
}}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
聊天
|
||||
</h3>
|
||||
|
||||
<Space>
|
||||
|
||||
<Input
|
||||
value={msg}
|
||||
onChange={e =>
|
||||
setMsg(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
style={{
|
||||
width: 300,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={
|
||||
sendMessage
|
||||
}
|
||||
>
|
||||
发送
|
||||
</Button>
|
||||
|
||||
</Space>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginTop: 20,
|
||||
height: 200,
|
||||
border:
|
||||
"1px solid #ddd",
|
||||
padding: 10,
|
||||
overflowY:
|
||||
"auto",
|
||||
}}
|
||||
>
|
||||
|
||||
{msgList.map(
|
||||
(
|
||||
item,
|
||||
index
|
||||
) => (
|
||||
|
||||
<div
|
||||
key={
|
||||
index
|
||||
}
|
||||
>
|
||||
{
|
||||
item
|
||||
}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</Space>
|
||||
|
||||
</Card>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user