都是官方文档,仅供我自己巩固
1、准出
- 有个项目 vue(别的项目也行 react啥的)
- 注册声网,在控制台创建个应用获取 appID(必须)
2、开始创建
- 这段代码是视频的时候,会将视频插入的dom,可以把这段dom放到你要视频的页面中;
- videoIdList 这个变量是我自己定义的,主要是存放远端视频(别人的视频)的id
- local_stream 这个元素id是我要插入本地视频的地方,也可以叫别的名字;(下面会讲)
- remote_video_ + 远端视频id ,这个元素id是我要插入远端视频的地方,也可以叫别的名字;(下面会讲)
- 注意 这两个最好包在一个id为video的元素下 不然总会插入到别的地方 (我也不会调 哈哈哈哈)*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<div id='video' :style="{height:'100%',width:'100%'}">
<div class="video-view review-right-video">
<div id="local_stream" :style="{height:'100%',width:'100%'}"></div> // 本地的视频会插入到这个ID下
<div id="local_video_info" class="video-profile hide"></div>
<div id="video_autoplay_local" class="autoplay-fallback hide"></div>
</div>
<div
v-for="item in videoIdList" :key="item"
:id="`remote_video_panel_`+item" // 远端的视频会插入到这个id 下
:class="['video-view review-center-video',imageUrl ? 'active' : '']"
>
<div
:style="{height:'100%',width:'100%'}"
:id="`remote_video_`+item"
></div>
<div :id="`remote_video_info_`+item" class="video-profile hide"></div>
<div :id="`video_autoplay_`+item" class="autoplay-fallback hide"></div>
</div>
</div>
3、对接声网
安装
npm install agora-rtc-sdk
;也可以使用CDN
CDN
<script src="https://cdn.agora.io/sdk/release/AgoraRTCSDK-3.0.0.js"></script>
;引入
import AgoraRTC from 'agora-rtc-sdk'
;
4、整个声网的文件
*
*
*
- 完整的代码在最下面,直接看代码就行
- 我建了一个文件 叫 agoraRTCfunct(都是网易翻译来的)
1.引入 sdkimport AgoraRTC from 'agora-rtc-sdk'
;
2.设置两个参数变量
主要的就是appID
频道是自己定义的,就像设置一个房间,别人会根据你的频道号加入到你的视频当中
1 | const rtc = { |
3.开始声网
- 开始监听的代码在下面 , 监听视频过程中的很多事件
- 创建本地流的代码也在下面
- 主要是创建了一个频道,
- 初始化一个频道
- 加入到这个频道
- 在页面中引入 import agora from ‘./agoraRTCfunct.js’; 创建的这个文件*
- thet是vue页面的this,我在页面初始化(mounted)的时候调用了 agora.agoraFunction(this); 传入了this*
- 因为有用户加入的时候会用到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25const agoraFunction = function(thet){
if(rtc.joined){
Notification.info("您已经加入频道");
return;
};
// 创建客户端
rtc.client = AgoraRTC.createClient({mode: "live", codec: "vp8"});
rtc.params = {mode:'live', codec: 'vp8'}; // 赋值输入框的值
Listening(thet); // 开始监听
// 初始化
rtc.client.init(option.appID, function () {
console.log("初始化成功");
//加入频道
rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {
console.log("成功----频道号码: " + option.channel + "你的id: " + uid);
rtc.joined = true;
rtc.params.uid = uid; // 获取到自己的id
createStream(); // 创建本地流
}, function(err) {
console.error("加入频道失败", err)
})
}, (err) => {
console.error(err);
});
};
4.创建本地流(就是打开摄像头能看到自己)
重要的是
- rtc.localStream.play(‘local_stream’); // 插入到这个id中
- local_stream 这个是我自己定义的ID 本地的视频会插入到这个元素中
- 发布本地流是把,本地的视频推到远端 、要不别人看不见
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const createStream = function(){ //创建本地流
// 创建本地流
rtc.localStream = AgoraRTC.createStream({
streamID: rtc.params.uid, // 在上一步获取到的自己的视频id
audio: true,
video: true,
screen: false, // 是不是需要共享屏幕 这个只在谷歌浏览器有用 不咋好使
});
// 初始化本地流
rtc.localStream.setVideoProfile("360p_1"); // 640X360 15 400 视频清晰度
rtc.localStream.init(function () {
console.log("本地流-初始化-成功",rtc.localStream);
// 发布本地流
rtc.localStream.play('local_stream'); // 插入到这个id中
publish(); // 发布本地流
}, function (err) {
console.error("本地流-初始化-失败", err);
});
} - 发布根底流*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const publish = function () { // 发布本地流
if (!rtc.client) {
Notification.info("您还没加入频道");
return;
}
if (rtc.published) {
Notification.info("您已经发布频道");
return;
}
const oldState = rtc.published;
// publish localStream
rtc.client.publish(rtc.localStream, function (err) {
rtc.published = oldState;
console.log("publish failed");
Toast.error("publish failed")
console.error(err);
})
Notification.success("发布频道成功");
rtc.published = true
}
5.监听视频过程中的事件
- 重要的是有别人加入你的视频中的事件(和离开)
- 主要是有用户加入频道的时候,要及时创建一个指定的对方id的元素*
- remoteStream.play(“remote_video_” + id); // 插入到 id为 remote_video_ + id 元素中
- “remote_video_” + id 这个就是我定义的元素, 对方的视频会插入到这里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86const Listening = function(thet){ // 订阅事件
// ---- 订阅开始
rtc.client.on("error", (err) => {
console.log("===>",err)
});
rtc.client.on("peer-leave", function(evt) { // 有用户离开时
var uid = evt.uid;
var reason = evt.reason; // 离线原因 Quit -- 主动离开 ServerTimeOut -- 超时掉线(也有可能是主动离开)
if (uid != rtc.params.uid) {
thet.deleteView(uid);
};
Notification.info("用户离开");
console.log("用户离线" , uid, "reason: ", reason);
});
rtc.client.on("stream-published", function(evt){ // 发布视频流本地触发
var remoteStream = evt.stream;
var id = remoteStream.getId();
thet.myId = id;
});
rtc.client.on("stream-added", function (evt) { //有远程流加入时
var remoteStream = evt.stream;
var id = remoteStream.getId();
if (id !== rtc.params.uid) {
rtc.client.subscribe(remoteStream, function (err) { // 订阅加入的远程端视频
console.log("订阅远程端视频失败", err);
})
};
console.log('加入的远程端视频流: ', id);
});
rtc.client.on("stream-subscribed", function (evt) { //订阅远程流
var remoteStream = evt.stream;
var id = remoteStream.getId();
rtc.remoteStreams.push(remoteStream); // 不知道干啥的
Notification.success("用户加入"+id);
thet.addView(id);
setTimeout(()=>{ // vue创建元素 是异步的 (一会处理)
remoteStream.play("remote_video_" + id); // 插入到 id为 remote_video_ + id 元素中
},300);
console.log('接收到的远程端视频: ', id);
});
rtc.client.on("stream-removed", function (evt) { // 对方取消发布
var remoteStream = evt.stream;
var id = remoteStream.getId();
remoteStream.stop("remote_video_" + id);
rtc.remoteStreams = rtc.remoteStreams.filter(function (stream) {
return stream.getId() !== id;
})
thet.deleteView(id);
console.log('stream-removed remote-uid: ', id);
});
rtc.client.on("onTokenPrivilegeWillExpire", function(){ // token过期前30秒调用
// client.renewToken(token);
console.log("token即将过期")
});
rtc.client.on("onTokenPrivilegeDidExpire", function(){ // token已经失效
// client.renewToken(token);
console.log("token已经失效");
});
rtc.client.on("network-quality", function(stats) { // 本地用户的网络质量
console.log("下行", callQuality[stats.downlinkNetworkQuality]);
console.log("上行", callQuality[stats.uplinkNetworkQuality]);
});
rtc.client.on("mute-audio", function(evt) { // 对方关闭了语音
var uid = evt.uid;
Notification.info("用户"+uid+"已静音");
console.log("mute audio:" + uid);
//alert("mute audio:" + uid);
});
rtc.client.on("unmute-audio", function (evt) { // 对方打开了语音
var uid = evt.uid;
Notification.info("用户"+uid+"打来了语音");
console.log("unmute audio:" + uid);
});
rtc.client.on("mute-video", function (evt) { // 对方关闭摄像头
var uid = evt.uid;
Notification.info("用户"+uid+"关闭了摄像头");
console.log("mute video" + uid);
//alert("mute video:" + uid);
});
rtc.client.on("unmute-video", function (evt) { // 对方打开了摄像头
var uid = evt.uid;
Notification.info("用户"+uid+"打开了了摄像头");
console.log("unmute video:" + uid);
});
// ---- 订阅结束
}; - 我在监听到有用户加入的时候,把用户的id插入到一个数组里,循环渲染出了有特定id的元素(thet.addView(id);)
- 我在监听到有用户离开的时候,把用户的id从这个数组中去除掉,在循环渲染出了有特定id的元素(thet.deleteView(id);)
1
2
3
4
5
6
7
8
9
10
11
12addView(id){
if(id == this.myId || this.videoIdList.indexOf(id) != -1) return;
const list = this.videoIdList;
list.push(id);
this.videoIdList = list;
},
deleteView(id){
const index = this.videoIdList.indexOf(id);
const list = this.videoIdList;
list.splice(index,1);
this.videoIdList = list;
},
其他的就没有比较重要的了
- 导出了这几个方法
1
2
3
4
5
6
7
8
9export default {
rtc, // 参数
option, // 参数
agoraFunction, // 声网开始的方法 创建 初始化 加入频道
publish, // 发布本地流
unpublish, // 停止发布本地流
leave, // 离开频道
getDevices, // 获取可用的 摄像头 麦克风
}; - 完整的代码*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286import AgoraRTC from 'agora-rtc-sdk';
import {Notification} from 'element-ui';
const callQuality = { // 通话质量
0:"质量未知",
1:"质量极好",
2:"用户主观感觉和极好差不多,但码率可能略低于极好",
3:"用户主观感受有瑕疵但不影响沟通",
4:"勉强能沟通但不顺畅",
5:"网络质量非常差,基本不能沟通",
6:"网络连接断开,完全无法沟通",
}
const rtc = {
client: null,
joined: false, //是否已经加入频道
published: false, // 是否已经发布
localStream: null,
remoteStreams: [],
params: {}
};
const option = {
appID: "f3e69727bee94580be65eb6193a72b89",
channel: "123", // 频道
uid: 1123, // 用户id
token: "" // 手机app上用的 没用
};
const leave = function () { // 离开频道
if (!rtc.client) {
Notification.info("您还没加入频道");
return;
}
if (!rtc.joined) {
Notification.info("您还没加入频道(2)");
return;
}
rtc.client.leave(function () {
rtc.localStream.stop();
rtc.localStream.close();
while (rtc.remoteStreams.length > 0) {
var stream = rtc.remoteStreams.shift();
var id = stream.getId();
stream.stop();
removeView(id);
}
rtc.localStream = null;
rtc.remoteStreams = [];
rtc.client = null;
rtc.published = false;
rtc.joined = false;
Notification.info("离开频道成功");
}, function (err) {
Notification.error("离开频道失败");
console.error(err);
})
}
function unpublish (rtc) { // 取消发布本地流
if (!rtc.client) {
Notification.info("您还没加入频道");
return;
}
if (!rtc.published) {
Toast.error("您已经发布频道");
return;
}
var oldState = rtc.published;
rtc.client.unpublish(rtc.localStream, function (err) {
rtc.published = oldState;
console.error(err);
})
Notification.info("取消发布成功");
rtc.published = false;
}
const createStream = function(){ //创建本地流
// 创建本地流
rtc.localStream = AgoraRTC.createStream({
streamID: rtc.params.uid,
audio: true,
video: true,
screen: false,
});
// 初始化本地流
rtc.localStream.setVideoProfile("360p_1"); // 640X360 15 400
rtc.localStream.init(function () {
console.log("本地流-初始化-成功",rtc.localStream);
// 发布本地流
rtc.localStream.play('local_stream'); // 插入到这个id中
publish(); // 发布本地流
}, function (err) {
console.error("本地流-初始化-失败", err);
});
}
const publish = function () { // 发布本地流
if (!rtc.client) {
Notification.info("您还没加入频道");
return;
}
if (rtc.published) {
Notification.info("您已经发布频道");
return;
}
const oldState = rtc.published;
// publish localStream
rtc.client.publish(rtc.localStream, function (err) {
rtc.published = oldState;
console.log("publish failed");
Toast.error("publish failed")
console.error(err);
})
Notification.success("发布频道成功");
rtc.published = true
}
const Listening = function(thet){ // 订阅事件
// ---- 订阅开始
rtc.client.on("error", (err) => {
console.log("===>",err)
});
rtc.client.on("peer-leave", function(evt) { // 有用户离开时
var uid = evt.uid;
var reason = evt.reason; // 离线原因 Quit -- 主动离开 ServerTimeOut -- 超时掉线(也有可能是主动离开)
if (uid != rtc.params.uid) {
thet.deleteView(uid);
};
Notification.info("用户离开");
console.log("用户离线" , uid, "reason: ", reason);
});
rtc.client.on("stream-published", function(evt){ // 发布视频流本地触发
var remoteStream = evt.stream;
var id = remoteStream.getId();
thet.myId = id;
});
rtc.client.on("stream-added", function (evt) { //有远程流加入时
var remoteStream = evt.stream;
var id = remoteStream.getId();
if (id !== rtc.params.uid) {
rtc.client.subscribe(remoteStream, function (err) { // 订阅加入的远程端视频
console.log("订阅远程端视频失败", err);
})
};
console.log('加入的远程端视频流: ', id);
});
rtc.client.on("stream-subscribed", function (evt) { //订阅远程流
var remoteStream = evt.stream;
var id = remoteStream.getId();
rtc.remoteStreams.push(remoteStream); // 不知道干啥的
Notification.success("用户加入"+id);
thet.addView(id);
setTimeout(()=>{ // vue创建元素 是异步的 (一会处理)
remoteStream.play("remote_video_" + id); // 插入到 id为 remote_video_ + id 元素中
},300);
console.log('接收到的远程端视频: ', id);
});
rtc.client.on("stream-removed", function (evt) { // 对方取消发布
var remoteStream = evt.stream;
var id = remoteStream.getId();
remoteStream.stop("remote_video_" + id);
rtc.remoteStreams = rtc.remoteStreams.filter(function (stream) {
return stream.getId() !== id;
})
thet.deleteView(id);
console.log('stream-removed remote-uid: ', id);
});
rtc.client.on("onTokenPrivilegeWillExpire", function(){ // token过期前30秒调用
// client.renewToken(token);
console.log("token即将过期")
});
rtc.client.on("onTokenPrivilegeDidExpire", function(){ // token已经失效
// client.renewToken(token);
console.log("token已经失效");
});
rtc.client.on("network-quality", function(stats) { // 本地用户的网络质量
console.log("下行", callQuality[stats.downlinkNetworkQuality]);
console.log("上行", callQuality[stats.uplinkNetworkQuality]);
});
rtc.client.on("mute-audio", function(evt) { // 对方关闭了语音
var uid = evt.uid;
Notification.info("用户"+uid+"已静音");
console.log("mute audio:" + uid);
//alert("mute audio:" + uid);
});
rtc.client.on("unmute-audio", function (evt) { // 对方打开了语音
var uid = evt.uid;
Notification.info("用户"+uid+"打来了语音");
console.log("unmute audio:" + uid);
});
rtc.client.on("mute-video", function (evt) { // 对方关闭摄像头
var uid = evt.uid;
Notification.info("用户"+uid+"关闭了摄像头");
console.log("mute video" + uid);
//alert("mute video:" + uid);
});
rtc.client.on("unmute-video", function (evt) { // 对方打开了摄像头
var uid = evt.uid;
Notification.info("用户"+uid+"打开了了摄像头");
console.log("unmute video:" + uid);
});
// ---- 订阅结束
};
// 开始声网
const agoraFunction = function(thet){
// 创建客户端
if(rtc.joined){
Notification.info("您已经加入频道");
return;
};
rtc.client = AgoraRTC.createClient({mode: "live", codec: "vp8"});
rtc.params = {mode:'live', codec: 'vp8'}; // 赋值输入框的值
Listening(thet); // 开始监听
// 初始化
rtc.client.init(option.appID, function () {
console.log("初始化成功");
//加入频道
rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {
console.log("成功----频道号码: " + option.channel + "你的id: " + uid);
rtc.joined = true;
rtc.params.uid = uid;
createStream(); // 创建本地流
}, function(err) {
console.error("加入频道失败", err)
})
}, (err) => {
console.error(err);
});
};
const getDevices = function (next) { // 获取音视频设备信息
AgoraRTC.getDevices(function (items) {
items.filter(function (item) {
return ['audioinput', 'videoinput'].indexOf(item.kind) !== -1
}).map(function (item) {
return {
name: item.label,
value: item.deviceId,
kind: item.kind,
}
});
var videos = [];
var audios = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if ('videoinput' == item.kind) {
var name = item.label;
var value = item.deviceId;
if (!name) {
name = "camera-" + videos.length;
}
videos.push({
name: name,
value: value,
kind: item.kind
});
}
if ('audioinput' == item.kind) {
var name = item.label;
var value = item.deviceId;
if (!name) {
name = "microphone-" + audios.length;
}
audios.push({
name: name,
value: value,
kind: item.kind
});
}
}
console.log({videos: videos, audios: audios});
// next({videos: videos, audios: audios});
});
}
export default {
rtc, // 参数
option, // 参数
agoraFunction, // 声网开始的方法
publish, // 发布本地流
unpublish, // 停止发布本地流
leave, // 离开频道
getDevices, // 获取可用的 摄像头 麦克风
};
到此结束