yjz-web-sdk 1.0.8-beta.11 → 1.0.8-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/core/WebRTCSdk.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from 'eventemitter3';
|
|
2
2
|
import { SignalingClient } from './signal/SignalingClient';
|
|
3
3
|
import { WebRTCClient } from './rtc/WebRTCClient';
|
|
4
|
-
import { WebRTCConfig } from './rtc/WebRTCConfig';
|
|
5
4
|
import type { WebRTCConfigOptions } from './rtc/WebRTCConfig';
|
|
5
|
+
import { WebRTCConfig } from './rtc/WebRTCConfig';
|
|
6
6
|
import { ConnectorType } from './data/MessageType';
|
|
7
7
|
import { ChannelDataType } from './data/WebrtcDataType';
|
|
8
8
|
export declare class WebRTCSdk extends EventEmitter {
|
|
@@ -25,13 +25,13 @@ export declare class WebRTCClient extends EventEmitter {
|
|
|
25
25
|
private fileImage?;
|
|
26
26
|
private ua;
|
|
27
27
|
constructor(config: WebRTCConfig);
|
|
28
|
-
startPush(): Promise<void>;
|
|
28
|
+
startPush(useBackCamera?: boolean): Promise<void>;
|
|
29
29
|
handleOffer(offerSdp: string): void;
|
|
30
30
|
handleAnswer(answerSdp: string): void;
|
|
31
31
|
handleIceCandidate(candidate: RTCIceCandidateInit): void;
|
|
32
32
|
sendChannelData(type: ChannelDataType, data: any): void;
|
|
33
33
|
closeConnection(): void;
|
|
34
|
-
readyCapture(): Promise<void>;
|
|
34
|
+
readyCapture(useBackCamera: boolean): Promise<void>;
|
|
35
35
|
private getRotatedStream;
|
|
36
36
|
private setVideoParams;
|
|
37
37
|
stopPush(): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConnectorType } from '../data/MessageType';
|
|
2
|
+
import { LogLevel } from "../util/Logger.ts";
|
|
2
3
|
export interface WebRTCConfigOptions {
|
|
3
4
|
signalServerUrl: string;
|
|
4
5
|
myId?: string;
|
|
@@ -30,6 +31,8 @@ export interface WebRTCConfigOptions {
|
|
|
30
31
|
connectorAndRoomId?: Map<string, string>;
|
|
31
32
|
groupId?: string;
|
|
32
33
|
cacheTimeout?: number;
|
|
34
|
+
enableLogger?: boolean;
|
|
35
|
+
loggerLevel?: LogLevel;
|
|
33
36
|
}
|
|
34
37
|
export declare class WebRTCConfig {
|
|
35
38
|
signalServerUrl: string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare enum LogLevel {
|
|
2
|
+
DEBUG = 10,
|
|
3
|
+
INFO = 20,
|
|
4
|
+
WARN = 30,
|
|
5
|
+
ERROR = 40,
|
|
6
|
+
OFF = 100
|
|
7
|
+
}
|
|
8
|
+
export declare function setLogLevel(level: LogLevel): void;
|
|
9
|
+
export declare function enableLog(enable: boolean): void;
|
|
10
|
+
export declare function setNamespace(ns: string): void;
|
|
11
|
+
declare class LoggerCore {
|
|
12
|
+
private canLog;
|
|
13
|
+
private log;
|
|
14
|
+
debug(...args: any[]): void;
|
|
15
|
+
info(...args: any[]): void;
|
|
16
|
+
warn(...args: any[]): void;
|
|
17
|
+
error(...args: any[]): void;
|
|
18
|
+
}
|
|
19
|
+
export declare const Logger: LoggerCore;
|
|
20
|
+
export {};
|
package/lib/yjz-web-sdk.js
CHANGED
|
@@ -359,6 +359,83 @@ var EmitType = /* @__PURE__ */ ((EmitType2) => {
|
|
|
359
359
|
EmitType2["groupError"] = "groupError";
|
|
360
360
|
return EmitType2;
|
|
361
361
|
})(EmitType || {});
|
|
362
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
363
|
+
LogLevel2[LogLevel2["DEBUG"] = 10] = "DEBUG";
|
|
364
|
+
LogLevel2[LogLevel2["INFO"] = 20] = "INFO";
|
|
365
|
+
LogLevel2[LogLevel2["WARN"] = 30] = "WARN";
|
|
366
|
+
LogLevel2[LogLevel2["ERROR"] = 40] = "ERROR";
|
|
367
|
+
LogLevel2[LogLevel2["OFF"] = 100] = "OFF";
|
|
368
|
+
return LogLevel2;
|
|
369
|
+
})(LogLevel || {});
|
|
370
|
+
let globalLogLevel = 10;
|
|
371
|
+
let globalEnable = true;
|
|
372
|
+
let globalNamespace = "SDK";
|
|
373
|
+
function setLogLevel(level) {
|
|
374
|
+
globalLogLevel = level;
|
|
375
|
+
}
|
|
376
|
+
function enableLog(enable) {
|
|
377
|
+
globalEnable = enable;
|
|
378
|
+
}
|
|
379
|
+
const levelStyle = {
|
|
380
|
+
[
|
|
381
|
+
10
|
|
382
|
+
/* DEBUG */
|
|
383
|
+
]: "color: #999",
|
|
384
|
+
[
|
|
385
|
+
20
|
|
386
|
+
/* INFO */
|
|
387
|
+
]: "color: #2b90d9",
|
|
388
|
+
[
|
|
389
|
+
30
|
|
390
|
+
/* WARN */
|
|
391
|
+
]: "color: #e6a23c",
|
|
392
|
+
[
|
|
393
|
+
40
|
|
394
|
+
/* ERROR */
|
|
395
|
+
]: "color: #f56c6c",
|
|
396
|
+
[
|
|
397
|
+
100
|
|
398
|
+
/* OFF */
|
|
399
|
+
]: "color: inherit"
|
|
400
|
+
};
|
|
401
|
+
class LoggerCore {
|
|
402
|
+
canLog(level) {
|
|
403
|
+
return globalEnable && level >= globalLogLevel;
|
|
404
|
+
}
|
|
405
|
+
log(level, ...args) {
|
|
406
|
+
if (!this.canLog(level)) return;
|
|
407
|
+
const levelName = LogLevel[level];
|
|
408
|
+
const prefix = `%c[${globalNamespace}] [${levelName}]`;
|
|
409
|
+
const style = levelStyle[level];
|
|
410
|
+
switch (level) {
|
|
411
|
+
case 10:
|
|
412
|
+
console.log(prefix, style, ...args);
|
|
413
|
+
break;
|
|
414
|
+
case 20:
|
|
415
|
+
console.info(prefix, style, ...args);
|
|
416
|
+
break;
|
|
417
|
+
case 30:
|
|
418
|
+
console.warn(prefix, style, ...args);
|
|
419
|
+
break;
|
|
420
|
+
case 40:
|
|
421
|
+
console.error(prefix, style, ...args);
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
debug(...args) {
|
|
426
|
+
this.log(10, ...args);
|
|
427
|
+
}
|
|
428
|
+
info(...args) {
|
|
429
|
+
this.log(20, ...args);
|
|
430
|
+
}
|
|
431
|
+
warn(...args) {
|
|
432
|
+
this.log(30, ...args);
|
|
433
|
+
}
|
|
434
|
+
error(...args) {
|
|
435
|
+
this.log(40, ...args);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const Logger = new LoggerCore();
|
|
362
439
|
class SignalingClient extends EventEmitter {
|
|
363
440
|
constructor(config) {
|
|
364
441
|
super();
|
|
@@ -388,6 +465,7 @@ class SignalingClient extends EventEmitter {
|
|
|
388
465
|
this.webSocket = null;
|
|
389
466
|
};
|
|
390
467
|
this.webSocket.onerror = (event) => {
|
|
468
|
+
Logger.error("错误日志:", `信令服务器连接失败或者已断开=======>${this.config.signalServerUrl}`);
|
|
391
469
|
this.emit(EmitType.webrtcError, createWebRtcError(FailCode.SOCKET, event));
|
|
392
470
|
};
|
|
393
471
|
this.webSocket.onmessage = (event) => {
|
|
@@ -402,6 +480,7 @@ class SignalingClient extends EventEmitter {
|
|
|
402
480
|
this.clearTime();
|
|
403
481
|
if (this.timeout === null) {
|
|
404
482
|
this.timeout = setTimeout(() => {
|
|
483
|
+
Logger.error("错误日志:", `远端云机未响应=======>${this.config.roomId}`);
|
|
405
484
|
this.emit(EmitType.webrtcError, createWebRtcError(FailCode.STATE_ERR, ""));
|
|
406
485
|
this.timeout = null;
|
|
407
486
|
}, 6e3);
|
|
@@ -452,6 +531,7 @@ class SignalingClient extends EventEmitter {
|
|
|
452
531
|
connectorType: this.config.connectorType
|
|
453
532
|
};
|
|
454
533
|
const jsonMessage = JSON.stringify(message);
|
|
534
|
+
Logger.debug("调试日志:", `屏控登录信息====>${jsonMessage}`);
|
|
455
535
|
this.sendMessage(jsonMessage);
|
|
456
536
|
}
|
|
457
537
|
sendSwitchControlMessage(roomId, connectorType) {
|
|
@@ -463,7 +543,7 @@ class SignalingClient extends EventEmitter {
|
|
|
463
543
|
targetId: this.config.myId
|
|
464
544
|
};
|
|
465
545
|
const jsonMessage = JSON.stringify(message);
|
|
466
|
-
|
|
546
|
+
Logger.debug("调试日志:", `切换主控信令消息====>${jsonMessage}`);
|
|
467
547
|
this.sendMessage(jsonMessage);
|
|
468
548
|
}
|
|
469
549
|
sendSwitchControlToMainMessage(roomId) {
|
|
@@ -474,6 +554,7 @@ class SignalingClient extends EventEmitter {
|
|
|
474
554
|
roomId
|
|
475
555
|
};
|
|
476
556
|
const jsonMessage = JSON.stringify(message);
|
|
557
|
+
Logger.debug("调试日志:", `切换主控信令消息====>${jsonMessage}`);
|
|
477
558
|
this.sendMessage(jsonMessage);
|
|
478
559
|
}
|
|
479
560
|
sendGroupAcceptControl(roomIds, acceptControl) {
|
|
@@ -485,6 +566,7 @@ class SignalingClient extends EventEmitter {
|
|
|
485
566
|
isAccept: acceptControl
|
|
486
567
|
};
|
|
487
568
|
const jsonMessage = JSON.stringify(message);
|
|
569
|
+
Logger.debug("调试日志:", `修改控制状态====>${jsonMessage}`);
|
|
488
570
|
this.sendMessage(jsonMessage);
|
|
489
571
|
}
|
|
490
572
|
sendGroupAction(action) {
|
|
@@ -499,6 +581,7 @@ class SignalingClient extends EventEmitter {
|
|
|
499
581
|
traceId: tid
|
|
500
582
|
};
|
|
501
583
|
const jsonMessage = JSON.stringify(message);
|
|
584
|
+
Logger.debug("调试日志:", `发送群控事件====>${jsonMessage}`);
|
|
502
585
|
this.sendMessage(jsonMessage);
|
|
503
586
|
}
|
|
504
587
|
sendGroupSignInMessage() {
|
|
@@ -513,8 +596,8 @@ class SignalingClient extends EventEmitter {
|
|
|
513
596
|
groupId: "group_0001",
|
|
514
597
|
token: this.config.token
|
|
515
598
|
};
|
|
516
|
-
console.log("sendGroupSignInMessage==>", message);
|
|
517
599
|
const jsonMessage = JSON.stringify(message);
|
|
600
|
+
Logger.debug("调试日志:", `群控登录信息====>${jsonMessage}`);
|
|
518
601
|
this.sendMessage(jsonMessage);
|
|
519
602
|
}
|
|
520
603
|
}
|
|
@@ -3165,20 +3248,29 @@ class WebRTCConfig {
|
|
|
3165
3248
|
}
|
|
3166
3249
|
}
|
|
3167
3250
|
const setRemoteDescriptionWithHandleOffer = (peerConnection, sdp2, sendAnswer, onError) => {
|
|
3251
|
+
Logger.info("信息日志:", "设置远程offer Description=======>");
|
|
3168
3252
|
const description = new RTCSessionDescription({ type: "offer", sdp: sdp2 });
|
|
3169
3253
|
peerConnection.setRemoteDescription(description).then(() => createAnswer(peerConnection, sendAnswer, onError)).catch((error) => onError == null ? void 0 : onError(createWebRtcError(FailCode.HANDLE_OFFER, error)));
|
|
3170
3254
|
};
|
|
3171
3255
|
const createAnswer = (peerConnection, sendAnswer, onError) => {
|
|
3256
|
+
Logger.info("信息日志:", "创建webrtcAnswer=======>");
|
|
3172
3257
|
peerConnection.createAnswer().then((answer) => setLocalDescriptionWithCreateAnswer(peerConnection, answer, sendAnswer, onError)).catch((error) => onError == null ? void 0 : onError(createWebRtcError(FailCode.CREATE_ANSWER, error)));
|
|
3173
3258
|
};
|
|
3174
3259
|
const setLocalDescriptionWithCreateAnswer = (peerConnection, answer, sendAnswer, onError) => {
|
|
3175
|
-
|
|
3176
|
-
|
|
3260
|
+
var _a;
|
|
3261
|
+
Logger.info("信息日志:", "设置本地answer Description=======>");
|
|
3262
|
+
let sdp2 = (_a = answer.sdp) == null ? void 0 : _a.replace(
|
|
3263
|
+
/a=rtpmap:\d+ opus\/48000\/2\r\n/g,
|
|
3264
|
+
"$&a=ptime:0\r\na=maxptime:10\r\n"
|
|
3265
|
+
);
|
|
3266
|
+
peerConnection.setLocalDescription({ type: answer.type, sdp: sdp2 }).then(() => {
|
|
3267
|
+
sendAnswer == null ? void 0 : sendAnswer(sdp2 ?? "");
|
|
3177
3268
|
}).catch((error) => {
|
|
3178
3269
|
onError == null ? void 0 : onError(createWebRtcError(FailCode.LOCAL_DES, error));
|
|
3179
3270
|
});
|
|
3180
3271
|
};
|
|
3181
3272
|
const createPeerConnection = (config) => {
|
|
3273
|
+
Logger.info("信息日志:", "初始化 Webrtc PeerConnection=======>");
|
|
3182
3274
|
const iceServers = [
|
|
3183
3275
|
{ urls: config.stunServerUri },
|
|
3184
3276
|
{
|
|
@@ -3189,7 +3281,7 @@ const createPeerConnection = (config) => {
|
|
|
3189
3281
|
];
|
|
3190
3282
|
const peerConnectionConfig = {
|
|
3191
3283
|
iceServers,
|
|
3192
|
-
iceTransportPolicy: "
|
|
3284
|
+
iceTransportPolicy: "all",
|
|
3193
3285
|
bundlePolicy: "max-bundle"
|
|
3194
3286
|
};
|
|
3195
3287
|
return new RTCPeerConnection(peerConnectionConfig);
|
|
@@ -3204,6 +3296,7 @@ const configPeerConnection = (peerConnection, onICEMessage, onTrack, onConnectSt
|
|
|
3204
3296
|
sdpMid: event.candidate.sdpMid,
|
|
3205
3297
|
sdpMLineIndex: event.candidate.sdpMLineIndex
|
|
3206
3298
|
};
|
|
3299
|
+
Logger.debug("信息日志:", `webrtc 生成的icecandidate===>${JSON.stringify(candidateObj)}`);
|
|
3207
3300
|
onICEMessage(JSON.stringify(candidateObj));
|
|
3208
3301
|
};
|
|
3209
3302
|
peerConnection.onconnectionstatechange = () => {
|
|
@@ -3211,12 +3304,14 @@ const configPeerConnection = (peerConnection, onICEMessage, onTrack, onConnectSt
|
|
|
3211
3304
|
if (!state) {
|
|
3212
3305
|
return;
|
|
3213
3306
|
}
|
|
3307
|
+
Logger.debug("信息日志:", `webrtc p2p连接状态===>`, state);
|
|
3214
3308
|
if (state === "failed" || state === "disconnected" || state === "closed") {
|
|
3215
3309
|
onError == null ? void 0 : onError(createWebRtcError(FailCode.ICE_STATE, "failed"));
|
|
3216
3310
|
}
|
|
3217
3311
|
onConnectState == null ? void 0 : onConnectState(state);
|
|
3218
3312
|
};
|
|
3219
3313
|
peerConnection.ontrack = (event) => {
|
|
3314
|
+
Logger.debug("信息日志:", "webrtc p2p连接后获取的音视频track");
|
|
3220
3315
|
const track = event.track;
|
|
3221
3316
|
track.contentHint = "motion";
|
|
3222
3317
|
onTrack == null ? void 0 : onTrack(track);
|
|
@@ -3235,14 +3330,21 @@ const createOffer = async (peerConnection, sendOfferMessage) => {
|
|
|
3235
3330
|
}
|
|
3236
3331
|
};
|
|
3237
3332
|
const setLocalDescriptionWithCreateOffer = async (peerConnection, offer, sendOfferMessage) => {
|
|
3333
|
+
var _a;
|
|
3334
|
+
Logger.info("信息日志:", "设置本地offer Description=======>");
|
|
3238
3335
|
try {
|
|
3239
|
-
|
|
3240
|
-
|
|
3336
|
+
const sdp2 = (_a = offer.sdp) == null ? void 0 : _a.replace(
|
|
3337
|
+
/a=rtpmap:\d+ opus\/48000\/2\r\n/g,
|
|
3338
|
+
"$&a=ptime:0\r\na=maxptime:10\r\n"
|
|
3339
|
+
);
|
|
3340
|
+
await peerConnection.setLocalDescription({ type: offer.type, sdp: sdp2 });
|
|
3341
|
+
sendOfferMessage(sdp2 ?? "");
|
|
3241
3342
|
} catch (err) {
|
|
3242
3343
|
throw new Error("摄像头视频流添加失败");
|
|
3243
3344
|
}
|
|
3244
3345
|
};
|
|
3245
3346
|
const addIceCandidate = (peerConnection, candidate, onError) => {
|
|
3347
|
+
Logger.info("信息日志:", "接收远程ice 并设置=======>");
|
|
3246
3348
|
peerConnection.addIceCandidate(candidate).catch((err) => onError == null ? void 0 : onError(createWebRtcError(FailCode.HANDLE_ICE, err)));
|
|
3247
3349
|
};
|
|
3248
3350
|
var ChannelDataType = /* @__PURE__ */ ((ChannelDataType2) => {
|
|
@@ -3522,14 +3624,14 @@ class WebRTCClient extends EventEmitter {
|
|
|
3522
3624
|
this.config = config;
|
|
3523
3625
|
this.ua = navigator.userAgent;
|
|
3524
3626
|
}
|
|
3525
|
-
async startPush() {
|
|
3627
|
+
async startPush(useBackCamera = true) {
|
|
3526
3628
|
if (this.isPushingStream) return;
|
|
3527
3629
|
if (this.isPushingLocalStream) {
|
|
3528
3630
|
this.stopLocal();
|
|
3529
3631
|
}
|
|
3530
3632
|
try {
|
|
3531
3633
|
this.isPushingStream = true;
|
|
3532
|
-
await this.readyCapture();
|
|
3634
|
+
await this.readyCapture(useBackCamera);
|
|
3533
3635
|
} catch (err) {
|
|
3534
3636
|
this.isPushingStream = false;
|
|
3535
3637
|
let errorMessage;
|
|
@@ -3606,6 +3708,7 @@ class WebRTCClient extends EventEmitter {
|
|
|
3606
3708
|
}
|
|
3607
3709
|
}
|
|
3608
3710
|
closeConnection() {
|
|
3711
|
+
Logger.info("信息日志:", "关闭webrtc连接=======>");
|
|
3609
3712
|
if (this.statsTimer) {
|
|
3610
3713
|
clearInterval(this.statsTimer);
|
|
3611
3714
|
this.statsTimer = void 0;
|
|
@@ -3649,11 +3752,17 @@ class WebRTCClient extends EventEmitter {
|
|
|
3649
3752
|
this.peerConnection = null;
|
|
3650
3753
|
}
|
|
3651
3754
|
}
|
|
3652
|
-
async readyCapture() {
|
|
3755
|
+
async readyCapture(useBackCamera) {
|
|
3653
3756
|
this.resetPeerConnection();
|
|
3757
|
+
Logger.info("信息日志:", "启用摄像头推流到云机=======>", useBackCamera);
|
|
3654
3758
|
try {
|
|
3655
3759
|
this.localStream = await navigator.mediaDevices.getUserMedia({
|
|
3656
|
-
video: {
|
|
3760
|
+
video: {
|
|
3761
|
+
width: { ideal: 720 },
|
|
3762
|
+
height: { ideal: 540 },
|
|
3763
|
+
facingMode: useBackCamera ? { ideal: "environment" } : { ideal: "user" },
|
|
3764
|
+
frameRate: { ideal: 20, max: 30 }
|
|
3765
|
+
},
|
|
3657
3766
|
audio: true
|
|
3658
3767
|
});
|
|
3659
3768
|
const senders = [];
|
|
@@ -3664,11 +3773,12 @@ class WebRTCClient extends EventEmitter {
|
|
|
3664
3773
|
const sender = this.peerConnection.addTrack(track, rotatedStream);
|
|
3665
3774
|
senders.push(sender);
|
|
3666
3775
|
});
|
|
3667
|
-
senders.forEach((sender) => this.setVideoParams(sender));
|
|
3668
3776
|
await createOffer(this.peerConnection, (sdp2) => {
|
|
3669
3777
|
this.emit(EmitType.sendOffer, sdp2);
|
|
3670
3778
|
});
|
|
3779
|
+
senders.forEach((sender) => this.setVideoParams(sender));
|
|
3671
3780
|
} catch (err) {
|
|
3781
|
+
console.log("err===>", err);
|
|
3672
3782
|
if (err instanceof DOMException) {
|
|
3673
3783
|
switch (err.name) {
|
|
3674
3784
|
case "NotAllowedError":
|
|
@@ -3701,11 +3811,11 @@ class WebRTCClient extends EventEmitter {
|
|
|
3701
3811
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
3702
3812
|
ctx.save();
|
|
3703
3813
|
ctx.translate(canvas.width / 2, canvas.height / 2);
|
|
3704
|
-
ctx.rotate(Math.PI / 2);
|
|
3814
|
+
ctx.rotate(-Math.PI / 2);
|
|
3705
3815
|
ctx.drawImage(video, -width / 2, -height / 2, width, height);
|
|
3706
3816
|
ctx.restore();
|
|
3707
3817
|
};
|
|
3708
|
-
const fps =
|
|
3818
|
+
const fps = 25;
|
|
3709
3819
|
const frameInterval = 1e3 / fps;
|
|
3710
3820
|
let lastTime = 0;
|
|
3711
3821
|
let rafId;
|
|
@@ -3725,21 +3835,46 @@ class WebRTCClient extends EventEmitter {
|
|
|
3725
3835
|
});
|
|
3726
3836
|
return stream;
|
|
3727
3837
|
}
|
|
3838
|
+
// private async setVideoParams(sender: RTCRtpSender) {
|
|
3839
|
+
// Logger.info('信息日志:', '设置推流视频参数=======>')
|
|
3840
|
+
// const params = sender.getParameters();
|
|
3841
|
+
// params.degradationPreference = 'balanced';
|
|
3842
|
+
// const isMobile = /Android|iPhone|iPad/i.test(navigator.userAgent);
|
|
3843
|
+
// params.encodings.forEach(encoding => {
|
|
3844
|
+
// encoding.maxBitrate = isMobile ? 800000 : 1000000;
|
|
3845
|
+
// encoding.priority = 'high';
|
|
3846
|
+
// encoding.scaleResolutionDownBy = 1.0;
|
|
3847
|
+
// });
|
|
3848
|
+
// await sender.setParameters(params);
|
|
3849
|
+
// }
|
|
3728
3850
|
async setVideoParams(sender) {
|
|
3729
3851
|
const params = sender.getParameters();
|
|
3852
|
+
const isMobile = /Android|iPhone|iPad/i.test(navigator.userAgent);
|
|
3853
|
+
const targetBitrate = isMobile ? 6e5 : 18e5;
|
|
3854
|
+
const targetFramerate = 30;
|
|
3730
3855
|
params.degradationPreference = "maintain-resolution";
|
|
3856
|
+
if (!params.encodings || params.encodings.length === 0) {
|
|
3857
|
+
params.encodings = [{}];
|
|
3858
|
+
}
|
|
3859
|
+
console.log("params.codecs===>", params.codecs);
|
|
3731
3860
|
params.encodings.forEach((encoding) => {
|
|
3732
|
-
encoding.maxBitrate =
|
|
3733
|
-
encoding.
|
|
3861
|
+
encoding.maxBitrate = targetBitrate;
|
|
3862
|
+
encoding.maxFramerate = targetFramerate;
|
|
3734
3863
|
encoding.scaleResolutionDownBy = 1;
|
|
3864
|
+
encoding.priority = "high";
|
|
3735
3865
|
});
|
|
3736
|
-
|
|
3866
|
+
try {
|
|
3867
|
+
await sender.setParameters(params);
|
|
3868
|
+
Logger.info("信息日志:", `设置推流视频参数成功:${targetBitrate / 1e3}kbps / ${targetFramerate}fps`);
|
|
3869
|
+
} catch (e) {
|
|
3870
|
+
Logger.error("设置推流参数失败:", e);
|
|
3871
|
+
}
|
|
3737
3872
|
}
|
|
3738
3873
|
stopPush() {
|
|
3739
3874
|
var _a, _b, _c;
|
|
3740
3875
|
if (!this.isPushingStream) return;
|
|
3741
3876
|
this.isPushingStream = false;
|
|
3742
|
-
|
|
3877
|
+
Logger.info("信息日志:", "停止推流到云机=======>");
|
|
3743
3878
|
(_a = this.localStream) == null ? void 0 : _a.getTracks().forEach((track) => track.stop());
|
|
3744
3879
|
this.localStream = null;
|
|
3745
3880
|
(_b = this.rotatedStream) == null ? void 0 : _b.getTracks().forEach((track) => track.stop());
|
|
@@ -3780,10 +3915,11 @@ class WebRTCClient extends EventEmitter {
|
|
|
3780
3915
|
handleDataChannelMessage(event) {
|
|
3781
3916
|
const data = JSON.parse(event.data);
|
|
3782
3917
|
if (data.type === ChannelDataType.ActionCommandEvent) {
|
|
3783
|
-
const { action, value } = JSON.parse(data.data);
|
|
3918
|
+
const { action, value, cameraId } = JSON.parse(data.data);
|
|
3784
3919
|
if (action === "ACTION_CONTROL_VIDEO") {
|
|
3920
|
+
console.log("cameraId===>", cameraId, cameraId !== 0);
|
|
3785
3921
|
if (value === "ENABLE") {
|
|
3786
|
-
this.startPush();
|
|
3922
|
+
this.startPush(Number(cameraId) === 0);
|
|
3787
3923
|
} else {
|
|
3788
3924
|
this.stopPush();
|
|
3789
3925
|
this.stopLocal();
|
|
@@ -3949,6 +4085,7 @@ class WebRTCClient extends EventEmitter {
|
|
|
3949
4085
|
}
|
|
3950
4086
|
}
|
|
3951
4087
|
startCanvasStream(fps = 30) {
|
|
4088
|
+
Logger.info("信息日志:", "初始化,使用本地文件推流到云机=======>");
|
|
3952
4089
|
const canvas = this.getCanvas();
|
|
3953
4090
|
const ctx = canvas.getContext("2d");
|
|
3954
4091
|
const media = this.currentMedia;
|
|
@@ -4015,7 +4152,7 @@ class WebRTCClient extends EventEmitter {
|
|
|
4015
4152
|
try {
|
|
4016
4153
|
(_a2 = this.peerConnection) == null ? void 0 : _a2.removeTrack(sender);
|
|
4017
4154
|
} catch (e) {
|
|
4018
|
-
|
|
4155
|
+
Logger.error("错误日志:", `移除音视频轨道失败=====>`, e);
|
|
4019
4156
|
}
|
|
4020
4157
|
});
|
|
4021
4158
|
if (this.fileVideo) {
|
|
@@ -4072,12 +4209,12 @@ const testMultipleTurnServers = async (servers, timeoutMs = 600) => {
|
|
|
4072
4209
|
}));
|
|
4073
4210
|
const testPromises = turnServers.map(
|
|
4074
4211
|
(cfg) => testTurnServer(cfg, timeoutMs).then((res) => res).catch((err) => {
|
|
4075
|
-
|
|
4212
|
+
Logger.warn("警告日志:", `中继计算超时=====>`, err);
|
|
4076
4213
|
return { ...cfg, rtt: Infinity };
|
|
4077
4214
|
})
|
|
4078
4215
|
);
|
|
4079
4216
|
const results = await Promise.all(testPromises);
|
|
4080
|
-
|
|
4217
|
+
Logger.debug("调试日志:", `信令计算结果======>`, results);
|
|
4081
4218
|
const available = results.filter((r) => r.rtt !== Infinity);
|
|
4082
4219
|
if (available.length === 0) {
|
|
4083
4220
|
throw new Error("All TURN servers are unreachable or slow (RTT = Infinity).");
|
|
@@ -4240,6 +4377,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4240
4377
|
__publicField(this, "handleSignaling", (message) => {
|
|
4241
4378
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
4242
4379
|
if (!this.config) return;
|
|
4380
|
+
Logger.debug("调试信息:", `信令消息=========>`, message);
|
|
4243
4381
|
switch (message.type) {
|
|
4244
4382
|
case MessageType.Peers:
|
|
4245
4383
|
this.config.myId = message.myId;
|
|
@@ -4267,7 +4405,6 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4267
4405
|
}
|
|
4268
4406
|
break;
|
|
4269
4407
|
case MessageType.SignOut:
|
|
4270
|
-
console.log("SignOutSignOutSignOutSignOutSignOutSignOutSignOutSignOut");
|
|
4271
4408
|
if (message.myId === this.config.myId) {
|
|
4272
4409
|
(_d = this.webRTCClient) == null ? void 0 : _d.closeConnection();
|
|
4273
4410
|
(_e = this.signalingClient) == null ? void 0 : _e.close();
|
|
@@ -4395,6 +4532,14 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4395
4532
|
} else {
|
|
4396
4533
|
this.cache = new MapCache("screenCache", 100);
|
|
4397
4534
|
}
|
|
4535
|
+
if (this.options.connectorType !== ConnectorType.LanForwarding) {
|
|
4536
|
+
enableLog(!!this.options.enableLogger);
|
|
4537
|
+
if (this.options.enableLogger !== void 0 && this.options.enableLogger) {
|
|
4538
|
+
if (this.options.loggerLevel !== void 0) {
|
|
4539
|
+
setLogLevel(this.options.loggerLevel);
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4398
4543
|
if (this.options.maxRecount) {
|
|
4399
4544
|
this.MAX_COUNT = this.options.maxRecount;
|
|
4400
4545
|
}
|
|
@@ -4451,6 +4596,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4451
4596
|
/** 开始连接 signal 服务 */
|
|
4452
4597
|
startConnection() {
|
|
4453
4598
|
this.prepareConnection().catch((err) => {
|
|
4599
|
+
Logger.error("错误信息:", `sdk调试错误日志======>`, err);
|
|
4454
4600
|
this.emit(EmitType.webrtcError, err);
|
|
4455
4601
|
});
|
|
4456
4602
|
}
|
|
@@ -4461,6 +4607,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4461
4607
|
try {
|
|
4462
4608
|
if (areTurnListsEmpty(this.options)) {
|
|
4463
4609
|
if (!this.options.turnServerUri) {
|
|
4610
|
+
Logger.error("错误信息:", `sdk调试错误日志======> 暂无可用TURN服务器`);
|
|
4464
4611
|
this.emit(EmitType.webrtcError, createWebRtcError(FailCode.OPTION_ERR, "暂无可用TURN服务器"));
|
|
4465
4612
|
return;
|
|
4466
4613
|
}
|
|
@@ -4489,6 +4636,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4489
4636
|
try {
|
|
4490
4637
|
await this.prepareConnection();
|
|
4491
4638
|
} catch (e) {
|
|
4639
|
+
Logger.error("错误信息:", `sdk调试错误日志======>`, e);
|
|
4492
4640
|
this.emit(EmitType.webrtcError, e);
|
|
4493
4641
|
}
|
|
4494
4642
|
}
|
|
@@ -4504,7 +4652,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4504
4652
|
(_b = this.webRTCClient) == null ? void 0 : _b.on(EmitType.sendAnswer, (sdp2) => this.sendAnswer(sdp2));
|
|
4505
4653
|
(_c = this.webRTCClient) == null ? void 0 : _c.on(EmitType.sendICEMessage, (candidate) => this.sendICEMessage(candidate));
|
|
4506
4654
|
(_d = this.webRTCClient) == null ? void 0 : _d.on(EmitType.streamTrack, (track) => {
|
|
4507
|
-
|
|
4655
|
+
Logger.debug("调试信息:", "=========> EmitType.streamTrack callback");
|
|
4508
4656
|
this.emit(EmitType.streamTrack, track);
|
|
4509
4657
|
});
|
|
4510
4658
|
(_e = this.webRTCClient) == null ? void 0 : _e.on(EmitType.iceConnectionState, (state) => {
|
|
@@ -4527,6 +4675,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4527
4675
|
this.emit(EmitType.reconnect);
|
|
4528
4676
|
this.reconnect();
|
|
4529
4677
|
} else {
|
|
4678
|
+
Logger.error("错误信息:", `sdk调试错误日志======>`, err);
|
|
4530
4679
|
this.emit(EmitType.webrtcError, err);
|
|
4531
4680
|
}
|
|
4532
4681
|
});
|
|
@@ -4542,6 +4691,7 @@ class WebRTCSdk extends EventEmitter {
|
|
|
4542
4691
|
this.signalingClient = new SignalingClient(this.config);
|
|
4543
4692
|
this.signalingClient.on(EmitType.signalMessage, (message) => this.handleSignaling(message));
|
|
4544
4693
|
this.signalingClient.on(EmitType.webrtcError, (err) => {
|
|
4694
|
+
Logger.error("错误信息:", `sdk 信令调试错误日志======>`, err);
|
|
4545
4695
|
this.emit(EmitType.webrtcError, err);
|
|
4546
4696
|
});
|
|
4547
4697
|
}
|
|
@@ -4960,8 +5110,8 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
4960
5110
|
const widthRadio = ref(0);
|
|
4961
5111
|
const heightRadio = ref(0);
|
|
4962
5112
|
const resizeObserver = ref(null);
|
|
4963
|
-
const frameCallbackId = ref(0);
|
|
4964
5113
|
const isRotated = computed(() => videoAngle.value % 180 !== 0);
|
|
5114
|
+
const frameCallbackId = ref(0);
|
|
4965
5115
|
const videoSize = computed(() => {
|
|
4966
5116
|
let width = 0;
|
|
4967
5117
|
let height = 0;
|
|
@@ -5000,10 +5150,15 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
5000
5150
|
};
|
|
5001
5151
|
screenStatus.value = true;
|
|
5002
5152
|
emit("loadedSuccess");
|
|
5153
|
+
const isMobile = /Android|iPhone|iPad/i.test(navigator.userAgent);
|
|
5154
|
+
if (isMobile) {
|
|
5155
|
+
startVideoFrameCallback(video);
|
|
5156
|
+
}
|
|
5003
5157
|
};
|
|
5004
5158
|
video.addEventListener("loadedmetadata", handleMetadata);
|
|
5005
5159
|
onBeforeUnmount(() => {
|
|
5006
5160
|
video.removeEventListener("loadedmetadata", handleMetadata);
|
|
5161
|
+
if (frameCallbackId.value) video.cancelVideoFrameCallback(frameCallbackId.value);
|
|
5007
5162
|
});
|
|
5008
5163
|
};
|
|
5009
5164
|
const initVideoContainer = () => {
|
|
@@ -5021,8 +5176,15 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
5021
5176
|
}
|
|
5022
5177
|
const mediaStream = videoEl.srcObject;
|
|
5023
5178
|
updateTrack(mediaStream, newTrack);
|
|
5179
|
+
videoEl.playbackRate = 1;
|
|
5024
5180
|
videoEl.playsInline = true;
|
|
5181
|
+
videoEl.disablePictureInPicture = true;
|
|
5182
|
+
videoEl.setAttribute("playsinline", "true");
|
|
5025
5183
|
videoEl.setAttribute("webkit-playsinline", "true");
|
|
5184
|
+
videoEl.setAttribute("x5-video-player-type", "h5");
|
|
5185
|
+
videoEl.setAttribute("x5-video-player-fullscreen", "false");
|
|
5186
|
+
videoEl.setAttribute("x5-video-orientation", "portraint");
|
|
5187
|
+
videoEl.preload = "auto";
|
|
5026
5188
|
};
|
|
5027
5189
|
const updateTrack = (stream, newTrack) => {
|
|
5028
5190
|
if (newTrack.kind === "video") {
|
|
@@ -5035,8 +5197,6 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
5035
5197
|
if (!stream.getAudioTracks().some((t) => t.id === newTrack.id)) {
|
|
5036
5198
|
stream.addTrack(newTrack);
|
|
5037
5199
|
}
|
|
5038
|
-
} else {
|
|
5039
|
-
console.warn("不支持的 track 类型:", newTrack.kind);
|
|
5040
5200
|
}
|
|
5041
5201
|
};
|
|
5042
5202
|
const stopPlay = () => {
|
|
@@ -5045,29 +5205,17 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
5045
5205
|
if (video && video.srcObject) {
|
|
5046
5206
|
video.srcObject.getTracks().forEach((track) => track.stop());
|
|
5047
5207
|
video.srcObject = null;
|
|
5048
|
-
video.cancelVideoFrameCallback(frameCallbackId.value);
|
|
5208
|
+
if (frameCallbackId.value) video.cancelVideoFrameCallback(frameCallbackId.value);
|
|
5049
5209
|
}
|
|
5050
5210
|
};
|
|
5051
5211
|
const handleVisibilityChange = () => {
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
track.enabled = true;
|
|
5058
|
-
}
|
|
5059
|
-
});
|
|
5060
|
-
}
|
|
5061
|
-
} else {
|
|
5062
|
-
const video = remoteVideoElement.value;
|
|
5063
|
-
if (video && video.srcObject) {
|
|
5064
|
-
video.srcObject.getTracks().forEach((track) => {
|
|
5065
|
-
if (track.kind === "audio" && track.enabled) {
|
|
5066
|
-
track.enabled = false;
|
|
5067
|
-
}
|
|
5068
|
-
});
|
|
5212
|
+
const video = remoteVideoElement.value;
|
|
5213
|
+
if (!video || !video.srcObject) return;
|
|
5214
|
+
video.srcObject.getTracks().forEach((track) => {
|
|
5215
|
+
if (track.kind === "audio") {
|
|
5216
|
+
track.enabled = document.visibilityState === "visible";
|
|
5069
5217
|
}
|
|
5070
|
-
}
|
|
5218
|
+
});
|
|
5071
5219
|
};
|
|
5072
5220
|
onMounted(() => {
|
|
5073
5221
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
@@ -5079,6 +5227,16 @@ function useRemoteVideo(videoContainer, remoteVideoElement, videoAngle, emit) {
|
|
|
5079
5227
|
}
|
|
5080
5228
|
stopPlay();
|
|
5081
5229
|
});
|
|
5230
|
+
const startVideoFrameCallback = (video) => {
|
|
5231
|
+
const handleFrame = (_now, _metadata) => {
|
|
5232
|
+
video.playbackRate = 1.1;
|
|
5233
|
+
setTimeout(() => {
|
|
5234
|
+
video.playbackRate = 1;
|
|
5235
|
+
}, 600);
|
|
5236
|
+
frameCallbackId.value = video.requestVideoFrameCallback(handleFrame);
|
|
5237
|
+
};
|
|
5238
|
+
frameCallbackId.value = video.requestVideoFrameCallback(handleFrame);
|
|
5239
|
+
};
|
|
5082
5240
|
return {
|
|
5083
5241
|
videoSize,
|
|
5084
5242
|
remoteVideo,
|
|
@@ -5358,7 +5516,6 @@ class SdkController extends EventEmitter {
|
|
|
5358
5516
|
const id = this.config.roomId;
|
|
5359
5517
|
this.sdk.removeAllListeners();
|
|
5360
5518
|
this.sdk.on(EmitType.streamTrack, (track) => {
|
|
5361
|
-
console.log("=========> ON EmitType.streamTrack SdkController");
|
|
5362
5519
|
const isVideo = track.kind === "video";
|
|
5363
5520
|
this.emit(EmitType.streamTrack, isVideo, track);
|
|
5364
5521
|
});
|
|
@@ -5425,6 +5582,12 @@ class GroupCtrlSocketManager {
|
|
|
5425
5582
|
__publicField(this, "websocketModeSdkController");
|
|
5426
5583
|
__publicField(this, "isSynchronous", true);
|
|
5427
5584
|
this.config = config;
|
|
5585
|
+
enableLog(!!this.config.enableLogger);
|
|
5586
|
+
if (this.config.enableLogger !== void 0 && this.config.enableLogger) {
|
|
5587
|
+
if (this.config.loggerLevel !== void 0) {
|
|
5588
|
+
setLogLevel(this.config.loggerLevel);
|
|
5589
|
+
}
|
|
5590
|
+
}
|
|
5428
5591
|
this.websocketModeSdkController = new SdkController(config);
|
|
5429
5592
|
}
|
|
5430
5593
|
getRTCSdk() {
|