在我看到远程视频之前,Janus VideoRoom 插件订阅操作花费了太多秒

问题描述


我正在使用 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 (将#修改为@)