123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="description" content="jMuxer - a simple javascript mp4 muxer for non-standard streaming communications protocol">
- <meta name="keywords" content="h264 player, mp4 player, mse, mp4 muxing, jmuxer, aac player">
- <title>JMuxer demo</title>
- <script async defer src="https://buttons.github.io/buttons.js"></script>
- <style type="text/css">
- .github-tools {
- position: absolute;
- top: 15px;
- right: 15px;
- }
- a.h264-player {
- font-size: 20px;
- text-decoration: none;
- color: #07568e;
- margin-top: 10px;
- display: block;
- }
- .gesture {
- font-size: 15px;
- color: #ad4903;
- margin-top: 10px;
- }
- </style>
- </head>
- <body>
- <h2>jMuxer Demo</h2>
- <p>Sample demo node server is running on heroku free hosting</p>
- <br /><br />
- <div class="github-tools">
- <!-- Place this tag where you want the button to render. -->
- </div>
- <div id="container" style="width: 600px; margin: 0 auto;">
- <video width="100%" disablePictureInPicture ="true" autoplay poster="images/loader-thumb.jpg" id="player"></video>
- <audio width="50%" preload="none" autoplay controls poster="images/loader-thumb.jpg" id="audioPlayer" ></audio>
- <div class="gesture">If it does not play automatically, Click the `video play button` to initiate the video</div>
- </div>
- <body oncontextmenu="Back()">
- </body>
- <script src="helper.js" >
- </script>
- <script>
- //隐藏控件 controls
- var fpsCount = 0;
- var requestCount = 0;
- var timeCount = 0;
- var isVisuable = true;
- var isFeed = true;
- var isDrag = false;
- var isEnough = true;
-
- var delayTime = new Date().getTime();
- var feedTime = new Date().getTime();
- var requestTime = new Date().getTime() ;
- var curTime = new Date().getTime();
- var requestTime = new Date().getTime();//记录离开时间
- var myVideo = document.getElementById("player");
- var myAudio = document.getElementById("audioPlayer");
- var audioBuffer = [];
- var audioBack = [];
-
- document.addEventListener("visibilitychange", () => {
-
- if (document.visibilityState == "visible")
- {
- console.log("页面可见,继续喂视频");
- //requestTime = new Date().getTime();
- isVisuable = true;
- }
- else
- {
- isVisuable = false;
- isFeed = false;
- myVideo.pause();
- }
-
- });
-
- myVideo.addEventListener('pause',function(){
- //console.log("视频播放暂停");
- isFeed = false;
- });
-
- myAudio.addEventListener('pause',function(){
- console.log("音频播放暂停");
- myAudio.play();
- });
-
- //解协议
- function ParseProto(data)
- {
- var temp = "";
- var input = new Uint8Array(data),
- duration,
- video,
- audio;
-
- if(input[0] == 0 && input[1] == 0 && input[2] == 0 && input[3] == 1)
- {
- // debugger
- video = input;
- duration = 24;
- var nalType = input[4] &0x1f;//nalType == 0x07|| nalType == 0x08 || nalType == 0x05
-
- if(!isFeed)
- {
- if(nalType == 0x05)
- {
- console.log("发现I帧");
- }
-
- if(nalType == 0x05 && isVisuable)
- {
- console.log("检测到I帧 %d,重新渲染, 耗时 %d ms", nalType , new Date().getTime() - requestTime);
- isFeed = true;
- }
- }
-
- }
- else if(input[0] == 0xff)
- {
- if(!isEnough)
- {
- requestCount++;
- }
- audio = input;
-
- if(new Date().getTime() - curTime > 100)
- {
- delayTime = new Date().getTime();
- console.log("接收时间 %d ms", new Date().getTime() - curTime);
- }
- curTime = new Date().getTime();
- duration = 24;
- //console.log("duration %d", duration);
-
- }
- else if(input[0] == 0x68)
- {
- if(input[23] == 0x05)//横竖屏标识
- {
- var state = CheckScreenDirection(input.slice(24, 24 + 8));
-
- if(state == 1)
- {
- console.log("安卓卡此时竖屏");
- //竖屏处理
- }
- else
- {
- console.log("安卓卡此时横屏");
- //横屏处理
- }
- }
-
- if(input[23] == 0x0b)
- {
- console.log("多端登陆");
- }
- //console.log("屏幕旋转 %s", PrintArry(input));
- }
- return {
- audio: audio,
- video: video,
- duration: duration
- };
- }
-
- window.onload = function() {
- var socketURL = 'wss://jmuxer-demo-server.herokuapp.com';
- //socketURL = "ws://127.0.0.1:8080"
- //socketURL = "ws://192.168.11.238:8080"
- //socketURL = "ws://14.215.128.98:14112";
- socketURL = "ws://192.168.11.66:9101";
- //socketURL = "wss://192.168.11.242:9104";
-
- var jmuxer = new JMuxer({
- node: 'player',
- flushingTime:15 ,
- fps: 30,
- mode:'video',
- debug: false
- });
-
- var audioMuxer = new JMuxer({
- node: 'audioPlayer',
- flushingTime:1,
- clearBuffer: true,
- fps: 60,//可以不选,原先43
- mode:'audio',
- debug: false
- });
-
- /*var costTime = new Date().getTime() - curTime;
- if(costTime > 5)
- {
- console.log("websocket接收延迟 %d ms", costTime);
- }*/
-
- curTime = new Date().getTime();
- var ws = new WebSocket(socketURL);
- ws.binaryType = 'arraybuffer';
-
- //断开检测
- ws.onclose = function (e) {
- alert("websocket连接断开");
- console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean);
- console.log(e);
- }
-
- ws.addEventListener('open', function (event) {
- console.log("发送配置帧");
- ws.send(ConfigChannel("RK3923C1201900139"));
- });
-
- ws.addEventListener('error', function (event) {
- console.log("连接失败");
- });
-
- /*setInterval(function()
- {
- var audioData =
- {
- audio: null,
- video: null,
- duration: 24
- };
-
- if(myAudio != null)
- {
- if(audioBuffer.length < 1)
- {
- if(audioBack.length > 0)
- {
- audioData.audio = audioBack[0];
- audioMuxer.feed(audioData);
- audioBack.shift();
- }
-
- return;
- }
-
- if(audioBack.length > 10)
- {
- audioBack.shift();
- }
-
- if(audioBuffer.length > 50)
- {
- console.log("当前大小 %d", audioBuffer.length);
- audioBuffer = [];
- }
- else if(audioBuffer.length > 1)
- {
-
- var time = new Date().getTime();
- audioData.audio = audioBuffer[0];
- audioMuxer.feed(audioData);
-
- if(time - feedTime > 80)
- {
- console.log("喂数据间隔 %d ms, 队列长度", time - feedTime, audioBuffer.length);
- }
- feedTime = time;
-
- audioBuffer.shift();
- }
- }
- }, 1);*/
-
- ws.addEventListener('message',function(event) {
- var data = ParseProto(event.data);//JAVA服务器转发
- //console.log("收到数据");
-
- var audioData = {
- audio: data.audio,
- video: null,
- duration: data.duration
- };
-
- var videoData = {
- audio: null,
- video: data.video,
- duration: data.duration
- };
-
-
- if(myAudio.readyState == 2)
- {
- requestTime = new Date().getTime();
- isEnough = false;
- console.log("数据存储不够,出现声音停止");
- //myAudio.playbackRate = 2;
- }
- else if(myAudio.readyState == 4 && isEnough== false)
- {
- var time = new Date().getTime();
- isEnough = true;
- console.log("填满耗时 %d ms, 填充帧数 %d, 填充延迟 %d ms", time - requestTime, requestCount, requestCount * 23);
- requestCount = 0;
- console.log("----接收到启动 %d ms---", time - delayTime);
- }
-
- if(data.audio != null)//喂音频
- {
- //audioBuffer.push(data.audio);
- //audioBack.push(data.audio) ;
- audioMuxer.feed(audioData);
- }
-
- if(data.video != null)//喂视频
- {
- if(isFeed)
- {
- jmuxer.feed(data);
- }
-
- //jmuxer.feed(videoData);
- }
-
- });
-
-
- myVideo.onmousedown = function(event)
- {
- //放在此处只是为了方便演示,实际使用中查找横竖屏只要刚连接上时调用一次就好。
- //var checkBuffer = GetScreenState();
- //ws.send(checkBuffer);
- if(!isFeed)
- {
- console.log("重新申请I帧");
- requestTime = new Date().getTime();
- var buffer = RequestIFrame();
- //var buffer = new Uint8Array([0x01]);
- ws.send(buffer);
- }
-
- //console.log("报文 %s", PrintArry(buffer));
-
-
- if(event.button == 0)
- {
- var posX = event.offsetX * 1080 *1.0/myVideo.clientWidth;
- var posY = event.offsetY * 1920 *1.0/myVideo.clientHeight;
- var buffer = ExexuteMouseDown(posX.toString(), posY.toString());
- ws.send(buffer);
- isDrag = true;
- }
-
- }
-
- myVideo.onmousemove = function(event)
- {
- if(isDrag && event.button == 0)
- {
- var posX = event.offsetX * 1080 *1.0/myVideo.clientWidth;
- var posY = event.offsetY * 1920 *1.0/myVideo.clientHeight;
- var buffer = ExexuteMouseMove(posX.toString(), posY.toString());
- ws.send(buffer);
- //console.log("移动位置 %d, %d", posX, posY);
- }
-
- }
-
- myVideo.onmouseup = function(event)
- {
- isDrag = false;
- var posX = event.offsetX * 1080 *1.0/myVideo.clientWidth;
- var posY = event.offsetY * 1920 *1.0/myVideo.clientHeight;
- var buffer = ExexuteMouseUp(posX.toString(), posY.toString());
- ws.send(buffer);
-
- }
-
- myVideo.onkeydown = function(event)
- {
- ExexuteKeyDown(e.keyCode);
- }
-
- }
- function Back()
- {
- if(event.button == 2)
- {
- //ExexuteKeyDown(4);
- }
- ExexuteKeyDown(4);
- window.event.returnValue=false;
- return false;
- }
-
- </script>
- <script type="text/javascript" src="jmuxer.js"></script>
- </body>
- </html>
|