网页中播放RTSP(5) WebSocket播放视频

时间:2025-04-08 08:39:37

WebSocket播放视频是结合MediaSource的

总结:通过WebSocket获取视频流,提供给MediaSource,MediaSource结合video标签,播放视频。

这一套完全就是基于浏览器支持MediaSourceExtension(MSE)的,而我最终的目的是在unity3d里面播放视频,加入uinty3d不支持MediaSource和video标签,怎么折腾都没用。可能最后还会变成在uinty里面调要能够网页上的video来播放视频,调整一下窗口的大小。

在AppStore里面找了一下,没找到合适的资料,有个Embedded Browser说是完全支持HTML5包括视频,但是它的平台是windows,ios,linux,其实就是一个浏览器嵌入到unity程序中,没有webgl,而webgl其实就在浏览器里面了。这个在淘宝上有,3.0还买到35或者80。

接下来三个方向 调用浏览器 3.解码播放

 

参考:MediaSource

1.理解并修改

将文件和github上面的以及比较,将混淆后的变量名和方法名还原回去

function H5sPlayerWS(conf) {
    var s;
    ,  = [], this._mediaSource, , , , ,  = 0,  = 0,
         = 0,  = false,  = false,  = false, , this._conf = conf, ("Websocket Conf:",
            conf), this._videoId = , this._pbconf = , this._token = , void 0 === this._videoId ? (this._videoElemet = ,
                (, "use dom directly")) : (this._videoElemet = (this._videoId), (,
                    "use videoid")),  = this._videoElemet, null != this._pbconf && "false" == this._pbconf.showposter || (s = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session,
                        (, "connect src"), this._videoElemet.setAttribute("poster", s))
}
function H5sPlayerRTC(conf) {
    var s;
    , , ,  = 0,  = 0,  = 0,  = false,  = false, this._conf = conf,
        this._videoId = , this._pbconf = , this._token = , void 0 === this._videoId ? (this._videoElemet = ,
            (, "use dom directly")) : (this._videoElemet = (this._videoId), (,
                "use videoid")),  = this._videoElemet,  = null,  = {
                    optional: [{
                        DtlsSrtpKeyAgreement: true
                    }]
                },
         = {
            mandatory: {
                offerToReceiveAudio: true, offerToReceiveVideo: true
            }
        },
         = {
            M: []
        },
         = [], null != this._pbconf && "false" == this._pbconf.showposter || (s = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session,
            ("connect src", ), this._videoElemet.setAttribute("poster", s))
}
function createRTCSessionDescription(t) {
    return ("createRTCSessionDescription "), new RTCSessionDescription(t)
}
function H5sPlayerHls(t) {
    , , this._conf = t, this._videoId = , this._token = , ,  = , void 0 === this._videoId ? (this._videoElemet = ,
        (, "use dom directly")) : (this._videoElemet = (this._videoId), (,
            "use videoid")),  = this._videoElemet,  = "application/x-mpegURL",  = 0,  = 0;
    var s = this._conf.protocol + "//" +  + "/api/v1/GetImage?token=" + this._token + "&session=" + this._conf.session;
    this._videoElemet.setAttribute("poster", s)
}
function H5sPlayerAudio(t) {
     = [], ,  = false,  = false, this._conf = t, ("Aduio Player Conf:",
        t), this._token = , this._ = new AudioContext
}
function H5sPlayerAudBack(t) {
     = [], ,  = false,  = false, this._conf = t,  = 0,  = 48e3,  = false,
        ("Aduio Back Conf:", t), this._token = , this._ = new AudioContext, ("sampleRate",
            this._.sampleRate), ()
}
function float32ToInt16(t) {
    for (var s = , e = new Int16Array(s); s--;) {
        e[s] = 32767 * (1, t[s]);
    }
    return e
}
 = function () {
    ('reconnectFunction'+new Date());
    true ===  && (("Reconnect..."), (this._token),  = false)
},
     = function (url) {
        ('>> ');
        var ws;
        try {
            "http:" == this._conf.protocol && (ws = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + url) : new WebSocket("ws://" + this._conf.host + url)),
                "https:" == this._conf.protocol && ((this._conf.host), ws = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + url) : new WebSocket("wss://" + this._conf.host + url)),
                (this._conf.host)
        }
        catch (err) {
            return void alert("error")
        }
        return ws;
    },
     = function () {
        //('F');
        //();
        if (null !==  && void 0 !== ) {
            if (0 !==  && !) {
                try {
                    var first = (), buff = new Uint8Array(first);
                    (buff)
                }
                catch (err) {
                    (err)
                }
            }
        }
        else {
            (, "is null or undefined");
        }
        //();
    },
     = function () {
        //('X keepaliveTimer');
        //(this);
        //();
        try {
            var t = {
                cmd: "H5_KEEPALIVE"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },

    //获取websocket数据
     = function (msg) {
        //('>> ');
        //();
        //var ttt=(null, new Uint8Array());
        //(ttt);
        return , ArrayBuffer, "string" == typeof  ? (("string"), void (null != this._pbconf && null != this._pbconf.callback && this._pbconf.callback(,
            this._pbconf.userdata))) : true !==  ? false ===  ? ( = (null, new Uint8Array()),
                (this), void ( = true)) : ((), void ()) : void 0;
    },
    
     = function (player) {
        ('initMediaSource');
        try {
             =  || ,  || ("MediaSource API is not available");
            var codec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
            "MediaSource" in window && (codec) ? ("MIME type or codec: ",
                codec) : ("Unsupported MIME type or codec: ", codec), player._mediaSource = new ,  = true,
                (player._videoId);
             = (player._mediaSource), (), player._mediaSource.addEventListener("sourceopen",
                (player), false)
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        ("Add SourceBuffer"),  = this._mediaSource.addSourceBuffer(), this._mediaSource.duration = 1 / 0,
            this._mediaSource.removeEventListener("sourceopen", , false), ("updateend",
                (this), false);
    },
     = function (token) {
        ('>> ');
         = true;
        var url = "api/v1/h5swsapi", prof = "main";
        if (void 0 === this._conf.streamprofile || (prof = this._conf.streamprofile), void 0 === this._pbconf) {
            url = this._conf.rootpath + url + "?token=" + token + "&profile=" + prof + "&session=" + this._conf.session;
        }
        else {
            var i = "false", o = "fake";
            void 0 === this._pbconf.serverpb || (i = this._pbconf.serverpb), void 0 === this._pbconf.filename || (o = this._pbconf.filename),
                url = this._conf.rootpath + url + "?token=" + token + "&playback=true&profile=" + prof + "&serverpb=" + i + "&begintime=" + encodeURIComponent(this._pbconf.begintime) + "&endtime=" + encodeURIComponent(this._pbconf.endtime) + "&filename=" + o + "&session=" + this._conf.session
        }
        this._conf.session, (url),  = (url), ("setupWebSocket", ),  = "arraybuffer",
            (._player = this). = (this),  = function () {
                ("", this._player), this._player.checkSourceBufferTimerId = setInterval(this._player.(this._player), 1e4),
                    this._player.keepAliveTimerId = setInterval(this._player.(this._player), 1e3), null != this._player._pbconf && "true" === this._player._pbconf.autoplay && this._player.start();
            },
             = function () {
                ("", this._player), true === this._player.v ? (" disconnect") : this._player.S = true,
                    this._player.cleanupSourceBuffer(this._player), this._player.cleanupWebSocket(this._player), this._player.strCodec = "", this._player.p = false;
            }
    },
     = function (player) {
        ("Cleanup Source Buffer", player);
        try {
            ("updateend", , false), (),  || /Edge/.test() ? ("IE or EDGE!") : player._mediaSource.removeSourceBuffer(),
                 = null, player._mediaSource = null,  = []
        }
        catch (err) {
            (err)
        }
    },
     = function (player) {
        
        ("CleanupWebSocket", player);
        //(player);
        clearInterval(), clearInterval(),  = 0,  = 0,  = 0;
    },
     = function () {
        if (void 0 === this._pbconf) {
            true ===  && (("CheckSourceBuffer has been disconnect", this), clearInterval(),
                clearInterval(), clearInterval());
            try {
                if (("CheckSourceBuffer", this),  <= 0) {
                    if (++ , 8 < ) {
                        return ("CheckSourceBuffer Close 1"), void ();
                    }
                }
                else {
                     = 0;
                    (0);
                    var t = (0), s = t - ;
                    if (5 < s || s < 0) {
                        return ("CheckSourceBuffer Close 2", s), void ();
                    }
                    if (t == ) {
                        if (++ , 3 < ) {
                            return ("CheckSourceBuffer Close 3"), void ();
                        }
                    }
                    else {
                         = 0;
                    }
                     = t;
                }
            }
            catch (err) {
                (err)
            }
        }
    },
     = function () {
        (this._token);
         = setInterval((this), 3e3);//没3s重连一次。
    },
     = function () {
        ("disconnect", this),  = true, clearInterval(), null !=  && ((),
             = null), ("disconnect", this);
    },
     = function () {
        try {
            var t = {
                cmd: "H5_START"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        try {
            var t = {
                cmd: "H5_PAUSE"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        try {
            var t = {
                cmd: "H5_RESUME"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        try {
            var s = {
                cmd: "H5_SEEK"
            };
             = t, ((s))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        try {
            var s = {
                cmd: "H5_SPEED"
            };
             = t, ((s))
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        true ===  && (("Reconnect..."), (this._token),  = false)
    },
     = function (t) {
        var s;
        ("H5SWebSocketClient");
        try {
            "http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
                "https:" == this._conf.protocol && ((this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
                (this._conf.host)
        }
        catch (err) {
            return void alert("error")
        }
        return s;
    },
     = function () {
        try {
            var t = {
                type: "keepalive"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        if () {
            var s;
            ("onIceCandidate currentice", ), s = , ("onIceCandidate currentice",
                s, (s));
            var e = ((s));
             = "remoteice", ("onIceCandidate currentice new", e, (e)), ((e))
        }
        else {
            ("End of candidates.");
        }
    },
     = function (t) {
        var s;
        ("Remote track added:" + (t)), s =  ? [0] : ;
        var e = this._videoElemet;
         = (s), ();
    },
     = function () {
        ("createPeerConnection  config: " + () + " option:" + ());
        var s = new RTCPeerConnection(, ), e = this;
        return  = function (t) {
            (e, t)
        },
            void 0 !==  ?  = function (t) {
                (e, t)
            }
                :  = function (t) {
                    (e, t)
                },
             = function (t) {
                ("oniceconnectionstatechange  state: " + )
            },
            ("Created RTCPeerConnnection with config: " + () + "option:" + ()),
            s
    },
     = function (t) {
        ("ProcessRTCOffer", t);
        try {
             = (),  = 0;
            var s = this;
            (createRTCSessionDescription(t)), ().then(function (t) {
                ("Create answer:" + (t)), (t, function () {
                    ("ProcessRTCOffer createAnswer", t), ((t))
                },
                    function () { })
            },
                function (t) {
                    alert("Create awnser error:" + (t))
                })
        }
        catch (err) {
            (), alert("connect error: " + err)
        }
    },
     = function (t) {
        ("ProcessRemoteIce", t);
        try {
            var s = new RTCIceCandidate({
                sdpMLineIndex: , candidate: 
            });
            ("ProcessRemoteIce", s), ("Adding ICE candidate :" + (s)),
                (s, function () {
                    ("addIceCandidate OK")
                },
                    function (t) {
                        ("addIceCandidate error:" + (t))
                    })
        }
        catch (err) {
            alert("connect ProcessRemoteIce error: " + err)
        }
    },
     = function (msg) {
        , ArrayBuffer, , ("RTC received ", );
        var s = ();
        return ("Get Message type ", ), "offer" ===  ? (("Process Message type ",
            ), void (s)) : "remoteice" ===  ? (("Process Message type ", ),
                void (s)) : void (null != this._pbconf && null != this._pbconf.callback && this._pbconf.callback(, this._pbconf.userdata))
    },
     = function (t) {
         = true;
        var s = "api/v1/h5srtcapi", e = "main";
        if (void 0 === this._conf.streamprofile || (e = this._conf.streamprofile), void 0 === this._pbconf) {
            s = this._conf.rootpath + s + "?token=" + t + "&profile=" + e + "&session=" + this._conf.session;
        }
        else {
            var i = "false", o = "fake";
            void 0 === this._pbconf.serverpb || (i = this._pbconf.serverpb), void 0 === this._pbconf.filename || (o = this._pbconf.filename),
                s = this._conf.rootpath + s + "?token=" + t + "&playback=true&profile=" + e + "&serverpb=" + i + "&begintime=" + encodeURIComponent(this._pbconf.begintime) + "&endtime=" + encodeURIComponent(this._pbconf.endtime) + "&filename=" + o + "&session=" + this._conf.session
        }
        (s),  = (s), ("setupWebSocket", ),  = "arraybuffer",
            (._player = this). = (this),  = function () {
                ("", this._player);
                var t = {
                    type: "open"
                };
                this._player.((t)), this._player.keepAliveTimerId = setInterval(this._player.(this._player), 1e3), null != this._player._pbconf && "true" === this._player._pbconf.autoplay && this._player.start();
            },
             = function () {
                ("", this._player), true === this._player.v ? (" disconnect") : this._player.S = true,
                    this._player.cleanupWebSocket(this._player)
            }
    },
     = function (t) {
        ("CleanupWebSocket", t), clearInterval(),  = 0,  = 0,  = 0;
    },
     = function () {
        (this._token),  = setInterval((this), 3e3);
    },
     = function () {
        ("disconnect", this),  = true, clearInterval(), null !=  && ((),
             = null), ("disconnect", this);
    },
     = function () {
        try {
            var t = {
                cmd: "H5_START"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        try {
            var t = {
                cmd: "H5_PAUSE"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function () {
        try {
            var t = {
                cmd: "H5_RESUME"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        try {
            var s = {
                cmd: "H5_SEEK"
            };
             = t, ((s))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        try {
            var s = {
                cmd: "H5_SPEED"
            };
             = t, ((s))
        }
        catch (err) {
            (err)
        }
    },
     = function (t) {
        var s;
        ("H5SWebSocketClient");
        try {
            "http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
                "https:" == this._conf.protocol && ((this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
                (this._conf.host)
        }
        catch (err) {
            return void alert("error")
        }
        return s;
    },
     = function () {
        try {
            var t = {
                type: "keepalive"
            };
            ((t))
        }
        catch (err) {
            (err)
        }
    },
     = function (msg) {
        ("HLS received ", )
    },
     = function (t) {
        var s = "api/v1/h5swscmnapi";
        s = this._conf.rootpath + s + "?token=" + t + "&session=" + this._conf.session, (s),  = (s),
            ("setupWebSocket", ),  = "arraybuffer", (._player = this). = (this),
             = function () {
                ("", this._player), this._player.keepAliveTimerId = setInterval(this._player.(this._player), 1e3);
            },
             = function () {
                ("", this._player), this._player.cleanupWebSocket(this._player)
            }
    },
     = function (t) {
        ("H5sPlayerHls CleanupWebSocket", t), clearInterval()
    },
     = function () {
        ("HLS ", ), ("HLS ", );
        var t = , s = t - ;
        ("HLS diff", s), 0 === s && ++ ,  = t, 3 <  && (null !=  && ((),
             = null), (this._token), ("HLS reconnect"),  = "",  = 0,  = 0,
             = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "hls/" +  + "/" + this._token + "/hls.m3u8",
            ());
    },
     = function () {
        (this._token),  = 0,  = 0,  = function (t) {
            ("The End")
        },
             = function (t) {
                ("Pause")
            },
             = function (t) {
                ("Playing")
            },
             = function (t) {
                ("seeking")
            },
             = function (t) {
                ("volumechange")
            },
             = this._conf.protocol + "//" + this._conf.host + this._conf.rootpath + "hls/" +  + "/" + this._token + "/hls.m3u8",
            (),  = setInterval((this), 3e3);
    },
     = function () {
        clearInterval(),  = 0,  = 0, null !=  && ((),  = null),
            ("disconnect", this);
    },
     = function (t) {
        var s;
        ("H5SWebSocketClient");
        try {
            "http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
                "https:" == this._conf.protocol && ((this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
                (this._conf.host)
        }
        catch (err) {
            return void alert("error")
        }
        return s;
    },
     = function () {
        try {
            ("keepalive")
        }
        catch (err) {
            (err)
        }
    },
     = function (msg) {
        for (var s = new Int16Array(), e = , i = this._.createBuffer(1, e, 8e3), o = 0; o < 1; o++) {
            for (var n = (o), h = 0; h < e; h++) {
                n[h] = s[h] / 16383.5;
            }
        }
        var c = this._.createBufferSource();
         = i, (this._.destination), ();
    },
     = function (t) {
        ("CleanupWebSocket", t), clearInterval()
    },
     = function (t) {
        var s = "api/v1/h5saudapi";
        s = this._conf.rootpath + s + "?token=" + t + "&session=" + this._conf.session, (s),  = (s),
            ("setupWebSocket for audio", ),  = "arraybuffer", (._player = this). = (this),
             = function () {
                ("", this._player), this._player.keepAliveTimerId = setInterval(this._player.(this._player), 1e3);
            },
             = function () {
                ("", this._player), this._player.cleanupWebSocket(this._player)
            }
    },
     = function () {
        (this._token)
    },
     = function () {
        ("disconnect", this), null !=  && ((),  = null), ("disconnect",
            this);
    },
     = function (t) {
        var s;
        ("H5SWebSocketClient");
        try {
            "http:" == this._conf.protocol && (s = "undefined" != typeof MozWebSocket ? new MozWebSocket("ws://" + this._conf.host + t) : new WebSocket("ws://" + this._conf.host + t)),
                "https:" == this._conf.protocol && ((this._conf.host), s = "undefined" != typeof MozWebSocket ? new MozWebSocket("wss://" + this._conf.host + t) : new WebSocket("wss://" + this._conf.host + t)),
                (this._conf.host)
        }
        catch (err) {
            return void alert("error")
        }
        return s;
    },
     = function () {
        try {
            ("keepalive")
        }
        catch (err) {
            (err)
        }
    },
     = function (msg) { }, 
     = function (t) {
        ("CleanupWebSocket", t), clearInterval()
    },
     = function () {
        ("sampleRate", this._.sampleRate),  =  ||  ||  || ;
        try {
            ({
                video: false, audio: true
            },
                (this))
        }
        catch (err) {
            return void alert("Audio back false getUserMedia", err);
        }
    },
     = function () {
         = true
    },
     = function (t) {
        var s = "api/v1/h5saudbackapi";
        s = this._conf.rootpath + s + "?token=" + t + "&samplerate=" +  + "&session=" + this._conf.session,
            (s),  = (s), ("setupWebSocket for audio back", ),  = "arraybuffer",
            (._player = this). = (this),  = (this),  = function () {
                ("", this._player), this._player.cleanupWebSocket(this._player)
            }
    },
     = function (t) {
        var s = float32ToInt16((0));
        true ===  &&  && (s)
    },
     = function (t) {
        try {
            var s = this._.createMediaStreamSource(t), e = this._.createScriptProcessor(1024, 1, 1);
            (e), (this._.destination),  = (this)
        }
        catch (err) {
            return void alert("Audio intecomm error", err);
        }
    },
     = function () {
        (this._token)
    },
     = function () {
        ("disconnect", this), null !=  && ((),  = null), ("disconnect",
            this);
    };

2.创建简单播放视频原型代码

结合前面H5Stream里面的,实验并成功播放了一个H5Stream的ws视频。

还有一些细节问题。

<html>
    <head>
        <title>WebsocketVideo</title>
        <script src=""></script>
        <script src=""></script>
    </head>
    <body>
        <input style="width:100px;">
        <button >Play</button>
        <div>
            <video  autoplay webkit-playsinline playsinline></video>
        </div>
    </body>
    <script>
        $(document).ready(function(){
            var conf={};
            ="ws://localhost:8080/api/v1/h5swsapi?token=token2&profile=main&session=c1782caf-b670-42d8-ba90-2244d0b0ee83";
            ='video1';
            var player=new WebSocketPlayer(conf);
            ();
        });

        function WebSocketPlayer(conf){
            =conf;
            ='';
            =false;
            =[];
            =function(){
                ('openWebSocket');

                var player=this;
                var url=;
                var wsImp= || ;
                var ws=new wsImp(url);
                ='arraybuffer';
                =function(){
                    ('onopen');
                };
                =function(){
                    ('onclose');
                }
                =;
                =player;
            };
            =function(msg){
                ('onmessage',);
                var ws=this;
                var player=;

                if(===false){
                    =true;
                    =(null,new Uint8Array());
                    (player);
                    ();

                }else{
                    //();
                    //();
                    ();

                }
            };

            =function(player){
                try {
                    ('initMediaSource',player);
                    var msImp= || ;
                    var ms=new msImp();
                    =player;
                    =ms;

                    var video=();
                    =(ms);
                    ();
                    ('sourceopen',)
                    =video;
                }catch(ex){
                    (ex);
                }

            };

            =function(){
                ('msSourceOpen');
                var ms=this;
                var player=;
                var buffer=();
                =Infinity;
                ('updateend',)
                =buffer;
            };

            =function(){
                ('readFromBuffer1',this);
                //var player=this;
                //var buffer=;
                //('readFromBuffer2',buffer);
                //var first=();
                //var sourceBuffer=;
                //(first);
            };
        }

    </script>
</html>