问题描述
我正在使用 Janus VideoRoom 插件,我想订阅/取消订阅 2 个或更多不同的发布者。
前 4 或 5 个订阅(开始订阅 -> 视频可见)需要 2-3 秒。
我称之为正常。
但是下一次订阅需要更多时间。
我称之为非正常。
请告诉我我的错误在哪里?
这是我的 JS (TypeScript)
declare var Janus: any;
export class SubscriberClientSimple {
private login:string;
private opaqueId:string;
private videoPlayer:any;
private streamName:string;
private serverUri:string;
private serverURL:string;
private api:any;
private plugin:any;
private remoteStream:any;
public static STARTING:string = "STARTING";
public static STARTED:string = "STARTED";
public static STOPPING:string = "STOPPING";
public static STOPPED:string = "STOPPED";
private state:string;
constructor(login:string){
this.login = login;
this.opaqueId = "subscriber-" + this.login + "-" + Janus.randomString(12);
}
public destroy():void{
}
public setPlayerElement(element:any):void{
this.videoPlayer = element;
}
public hasVideoPlayerElement():boolean{
return this.videoPlayer!=null;
}
public isAudioEnabled():boolean{
return false;
}
public isVideoEnabled():boolean{
return true;
}
public getStreamName():string{
return this.streamName;
}
public subscribe(streamName: string,serverUri: string,audio:boolean,video:boolean):void{
this.log("Start requested");
this.state = SubscriberClientSimple.STARTING;
this.streamName = streamName;
this.serverUri = serverUri;
this.serverURL = MEDIA_SERVER_URL + MEDIA_SERVER_PATH + "/janus-debug";
EventBus.dispatchEvent(StreamingEvent.REMOTE_VIDEO_RECEIVE_INTENT,null);
//this.log("server url : "+this.serverURL);
Janus.init({
userId: parseInt(this.login),backendUrl: this.serverURL,environment: environment,debug: false,// fixme это вынужденно отключено,чтобы можно было использовать Janus.noop как коллбэк для логирования
callback: () => this.initCallback()
});
}
public unsubscribe():void{
this.log("unsubscribe state="+this.state);
if(this.state == SubscriberClientSimple.STARTED){
this.state = SubscriberClientSimple.STOPPING;
EventBus.dispatchEvent(StreamingEvent.SUBSCRIBER_BUSY,null);
if(this.plugin){
this.log("sending leave command...");
this.plugin.send({message: {request: "leave"}});
}
}
}
public disableAudio():void{
this.log("disable AUdio");
}
public disableVideo():void{
this.log("disable VIDEO");
}
public enableAudio():void{
}
public enableVideo():void{
}
public reset():void{
}
public setSocketService(socketService:any):void{
}
public setModalService(modalService):void{
}
public isMyCurrentPublisher(id:string):boolean{
return this.streamName == id;
}
public getSubscribeState():any{
var data:any = {userId:this.login,audio: {state:""},video:{state:"OFF"}};
data.audio.state = "OFF";
if(this.state == SubscriberClientSimple.STARTED){
data.video.state = "ON";
}
return data;
}
public isSubscribing():boolean{
return this.state == SubscriberClientSimple.STARTED;
}
private initCallback():void{
this.log("initCallback");
if (!Janus.isWebrtcSupported()) {
this.onWebRTCNotSupported();
}
this.createSession();
}
private createSession():void {
// Create session
this.log("createSession");
this.api = new Janus({
server: this.serverUri,iceServers: ICE_SERVERS,success: () => this.onStreamingServerCreateSuccess(),error: (err) => this.onStreamingServerCreateError(err),destroyed: () => this.onStreamingServerDestroyed()
});
}
private onStreamingServerCreateSuccess():void{
this.log("onStreamingServerCreateSuccess");
this.attachPlugin();
}
private attachPlugin():void{
this.log("attachPlugin");
let remoteFeed = null;
this.api.attach(
{
plugin: "janus.plugin.videoroom",opaqueId: this.opaqueId,success: (pluginHandle) => {
this.log("plugin attached");
remoteFeed = pluginHandle;
remoteFeed.simulcastStarted = false;
// We wait for the plugin to send us an offer
remoteFeed.send({
"message": {
"request": "listparticipants","room": +this.streamName
},success: (res) => {
this.log("Total participants="+res.participants.length);
var canJoin:boolean = res.participants && res.participants.length > 0;
this.log("canJoin="+canJoin);
if (canJoin) {
var publisherParticipant:any = res.participants[0];
var publisherId:string = publisherParticipant.id;
const subscriptionData:any = {
"request": "join","room": +this.streamName,"ptype": "subscriber","Feed": publisherId,"private_id": parseInt(this.login)
};
this.log("subscriptionData="+JSON.stringify(subscriptionData));
remoteFeed.send({"message": subscriptionData});
}
else {
this.log("Requested stream is not available anymore.");
}
}
});
},error: (error) => {
const message = "Error attaching subscribe plugin. " + error.toString();
this.log(message);
},onmessage: (msg,jsep) => {
this.onPluginMessage(msg,jsep,remoteFeed);
},webrtcState: (on,reason) => {
if (reason === "Close PC") {
var message:string = "Closed PeerConnection";
this.log(message);
}
},iceState: (state) => {
this.onICEState(state);
},onlocalstream: function (stream) {
// The subscriber stream is recvonly,we don't expect anything here
},onremotestream: (stream) => {
this.onSubscriberGotRemoteStream(stream);
},oncleanup: () => {
this.onCleanUp();
}
});
}
private onPluginMessage(msg,remoteFeed):void{
this.log("onPluginMessage");
this.log("msg:"+JSON.stringify(msg));
this.log("jsep:"+JSON.stringify(jsep));
this.log("remoteFeed:"+remoteFeed);
const event = msg["videoroom"];
if (msg["error"]){
if (msg["error"] !== "No such room") {
this.log("Janus ERROR:"+msg["error"]);
}
}
else if (event) {
if (event === "attached") {
// Subscriber created and attached
this.log("Subscriber created and attached");
if (this.plugin === undefined || this.plugin === null) {
this.plugin = remoteFeed;
}
remoteFeed.rfid = msg["id"];
remoteFeed.rfdisplay = msg["display"];
}
else if(event === "event"){
var leftRoomresult:any = msg["left"];
if(leftRoomresult){
if(leftRoomresult == "ok"){
var roomId:string = msg["room"].toString();
this.onLeftRoom(roomId);
}
}
}
else if (event === "slow_link") {
}
}
if (jsep) {
// Answer and attach
this.log("create answer");
remoteFeed.createAnswer(
{
jsep: jsep,media: {audioSend: false,videoSend: false},// We want recvonly audio/video
success: (_jsep) => {
this.log("Got SDP!",_jsep);
const body = {"request": "start","room": this.streamName};
remoteFeed.send({"message": body,"jsep": _jsep});
},error: (err) => {
this.log("WebRTC error:",err);
}
});
}
}
private onSubscriberGotRemoteStream(stream:any):void{
this.log("onSubscriberGotRemoteStream this.state="+this.state);
if(this.state == SubscriberClientSimple.STARTING){
const videoTracks = stream.getVideoTracks();
this.remoteStream = stream;
this.attachRemoteStream();
this.startRemoteVideo();
this.state = SubscriberClientSimple.STARTED;
}
}
private onLeftRoom(roomId:string):void{
if(roomId == this.streamName){
this.log("Left room");
this.plugin.ondetached();
this.plugin.detach();
this.plugin = null;
this.log("VIDEO stopped");
this.state = SubscriberClientSimple.STOPPED;
EventBus.dispatchEvent(StreamingEvent.REMOTE_VIDEO_disABLED,null);
}
}
private onCleanUp():void{
this.log("onCleanUp");
}
private onICEState(state:string):void{
this.log("ICE state of this WebRTC PeerConnection changed to " + state);
}
private attachRemoteStream():void {
Janus.attachMediaStream(this.videoPlayer,this.remoteStream );
this.videoPlayer.muted = "muted";
}
private startRemoteVideo():void {
this.videoPlayer.play();
this.log("VIDEO started");
EventBus.dispatchEvent(StreamingEvent.REMOTE_VIDEO_RECEIVING_STARTED,null);
}
private onStreamingServerCreateError(err:any):void{
this.log("Streaming Server Error:",err);
}
private onStreamingServerDestroyed():void{
this.log("Janus destroyed");
}
private onWebRTCNotSupported():void{
this.log("WebRTC Not Supported");
}
protected log(value:any,...rest:any[]):void{
EventBus.dispatchEvent(AppEvent.SEND_LOG,{className:this.getClassName(),value:value,rest:rest});
}
protected getClassName():string{
return "SubscriberClientSimple";
}
}
这是我在 4 或 5 个 norMAL 订阅启动后的日志
// 观看发布者的视频
//停止上一个订阅
04:01:50 取消订阅状态=STARTED
04:01:50 正在发送请假命令...
04:01:50 取消订阅状态=STOPPING
04:01:50 取消订阅状态=STOPPING
04:01:50 onPluginMessage
04:01:50 msg:{"videoroom":"event","room":681365,"left":"ok"}
04:01:50 jsep:未定义
04:01:50 remoteFeed:[object 对象]
04:01:50 离开房间
04:01:50 onCleanUp
04:01:50 视频停止
04:01:50 关闭 PeerConnection
04:01:50 onCleanUp
//新订阅正常开始
04:01:53 请求开始
04:01:53 initCallback
04:01:53 创建会话
04:01:54 onStreamingServerCreateSuccess
04:01:54 附加插件
04:01:54 附加插件
04:01:54 参与者总数=1
04:01:54 canJoin=true
04:01:54 subscriptionData={"request":"join","room":724240,"ptype":"subscriber","Feed":3606687285964170,"private_id":680291}
04:01:54 onPluginMessage
04:01:54 msg:{"videoroom":"attached","id":3606687285964170,"display":"724240"}
04:01:54 jsep:{"type":"offer","sdp":"v=0\r\no=- 1615780141548001 1 IN IP4 185.12.12.24\r\ns=VideoRoom 724240\r \nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS janus\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 185.12。 12.24\r\na=sendonly\r\na=mid:audio\r\na=rtcp-mux\r\na=ice-ufrag:NVx5\r\na=ice-pwd:Tz3hjJNIxACUULUbBBREaL\r\na=ice-选项:滴流\r\na=指纹:sha-256 53:C2:82:E2:61:73:BC:B5:0D:66:E8:2E:11:90:97:66:92:52:62 :FE:2C:6B:45:95:A1:EF:08:D6:05:C6:8E:A1\r\na=setup:actpass\r\na=rtpmap:111 opus/48000/2\r\ na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=rtcp-fb: 111 传输-cc\r\na=msid:janus janusa0\r\na=ssrc:3479227141 cname:janus\r\na=ssrc:3479227141 msid:janus janusa0\r\na=ssrc:3479227141 ms\label:janusr na=ssrc:3479227141 label:janusa0\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\r\nc=IN IP4 185.12.12.24\r\na=sendonly\r\na=mid:video\r \na=rtcp-mux\r\na=ice-ufrag:NVx5\r\na=ice-pwd:Tz3hjJNIxACUULUbBBREa L\r\na=ice-options:trickle\r\na=fingerprint:sha-256 53:C2:82:E2:61:73:BC:B5:0D:66:E8:2E:11:90:97 :66:92:52:62:FE:2C:6B:45:95:A1:EF:08:D6:05:C6:8E:A1\r\na=setup:actpass\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=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:13 urn:3gpp:video-orientation\r\ na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=ssrc-group:FID 462666388 1246572010\r\na=msid:janus janusv0\r\na=ssrc:48826name:462666386 janus\r\na=ssrc:462666388 msid:janus janusv0\r\na=ssrc:462666388 mslabel:janus\r\na=ssrc:462666388 label:janusv0\r\na=ssrc:1246572010\r\janus: =ssrc:1246572010 msid:janus janusv0\r\na=ssrc:1246572010 mslabel:janus\r\na=ssrc:1246572010 标签:janusv0\r\n"}
04:01:54 remoteFeed:[object 对象]
04:01:54 订阅者已创建并附加
04:01:54 创建答案
04:01:54 onSubscriberGotRemoteStream this.state=STARTING
04:01:54 视频开始
04:01:54 onSubscriberGotRemoteStream this.state=STARTED
04:01:54 onSubscriberGotRemoteStream this.state=STARTED
04:01:54 得到了 SDP! [RTCSession描述]
04:01:54 此 WebRTC PeerConnection 的 ICE 状态更改为检查
04:01:54 此 WebRTC PeerConnection 的 ICE 状态更改为已连接
04:01:55 onPluginMessage
04:01:55 msg:{"videoroom":"event","started":"ok"}
04:01:55 jsep:未定义
04:01:55 remoteFeed:[object 对象]
// norMAL 开始订阅用了 2 秒
// 观看发布者的视频
// 停止上一个订阅
04:09:55 取消订阅状态=STARTED
04:09:55 正在发送请假命令...
04:09:55 取消订阅状态=STOPPING
04:09:55 取消订阅状态=STOPPING
04:09:55 onPluginMessage
04:09:55 msg:{"videoroom":"event","left":"ok"}
04:09:55 jsep:未定义
04:09:55 remoteFeed:[object 对象]
04:09:55 离开房间
04:09:55 onCleanUp
04:09:55 视频停止
04:09:56 关闭 PeerConnection
04:09:56 onCleanUp
// 新订阅异常开始
04:09:58 请求开始
04:09:58 initCallback
04:09:58 创建会话
04:09:58 onStreamingServerCreateSuccess
04:09:58 附加插件
// 停顿一下!!!
04:10:17 附加插件
// 停顿一下!!!
04:10:22 参与者总数=1
04:10:22 canJoin=true
04:10:22 subscriptionData={"request":"join","private_id":680291}
04:10:28 onPluginMessage
04:10:28 msg:{"videoroom":"attached","display":"724240"}
04:10:28 jsep:{"type":"offer","sdp":"v=0\r\no=- 1615780141548001 1 IN IP4 185.12.12.24\r\ns=VideoRoom 724240\r \nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS janus\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 185.12。 12.24\r\na=sendonly\r\na=mid:audio\r\na=rtcp-mux\r\na=ice-ufrag:WETD\r\na=ice-pwd:ch2L786bEYlY6OIi+AJ4no\r\na= ice-options:trickle\r\na=fingerprint:sha-256 53:C2:82:E2:61:73:BC:B5:0D:66:E8:2E:11:90:97:66:92:52 :62:FE:2C:6B:45:95:A1:EF:08:D6:05:C6:8E:A1\r\na=setup:actpass\r\na=rtpmap:111 opus/48000/2\ r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=rtcp- fb:111 transport-cc\r\na=msid:janus janusa0\r\na=ssrc:1576733354 cname:janus\r\na=ssrc:1576733354 msid:janus janusa0\r\na=ssrc:1576733354\mslabel r\na=ssrc:1576733354 label:janusa0\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97\r\nc=IN IP4 185.12.12.24\r\na=sendonly\r\na=mid:video \r\na=rtcp-mux\r\na=ice-ufrag:WETD\r\na=ice-pwd:ch2L786bEYlY6OIi+AJ4n o\r\na=ice-options:trickle\r\na=fingerprint:sha-256 53:C2:82:E2:61:73:BC:B5:0D:66:E8:2E:11:90:97 :66:92:52:62:FE:2C:6B:45:95:A1:EF:08:D6:05:C6:8E:A1\r\na=setup:actpass\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=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:13 urn:3gpp:video-orientation\r\ na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=ssrc-group:FID 4137684267 1240900261\r\na=msid:janus janusv0\r\na=ssrc:42637name c janus\r\na=ssrc:4137684267 msid:janus janusv0\r\na=ssrc:4137684267 mslabel:janus\r\na=ssrc:4137684267 label:janusv0\r\na=ssrc:12409name:00261 =ssrc:1240900261 msid:janus janusv0\r\na=ssrc:1240900261 mslabel:janus\r\na=ssrc:1240900261 label:janusv0\r\n"}
04:10:28 remoteFeed:[object 对象]
04:10:28 订阅者已创建并附加
04:10:28 创建答案
04:10:28 onSubscriberGotRemoteStream this.state=STARTING
04:10:28 视频开始
04:10:28 onSubscriberGotRemoteStream this.state=STARTED
04:10:28 onSubscriberGotRemoteStream this.state=STARTED
04:10:28 得到了 SDP! [RTCSession描述]
04:10:28 此 WebRTC PeerConnection 的 ICE 状态更改为检查
04:10:28 此 WebRTC PeerConnection 的 ICE 状态更改为已连接
04:10:35 onSubscriberGotRemoteStream this.state=STARTED
04:10:47 onPluginMessage
04:10:47 msg:{"videoroom":"event","started":"ok"}
04:10:47 jsep:未定义
04:10:47 remoteFeed:[object 对象]
// 异常开始订阅需要 49 秒
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)