123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- <!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>
- <div id="container" style="width: 600px; margin: 0 auto;">
- <video width="100%" autoplay poster="images/loader-thumb.jpg" id="player"></video>
- <audio width="50%" controls autoplay poster="images/loader-thumb.jpg" id="audioPlayer"></audio>
- </div>
- <body oncontextmenu="Back()">
- </body>
- <script src="helper.js">
- </script>
- <script>
- //隐藏控件 controls
- var fpsCount = 0;
- var timeCount = 0;
- var isFeed = true;
- var isDrag = false;
- var curTime = new Date().getTime();
- var requestTime = new Date().getTime(); //记录离开时间
- var myVideo = document.getElementById("player");
- var myAudio = document.getElementById("audioPlayer");
- document.addEventListener("visibilitychange", () => {
- if (document.visibilityState == "visible") {
- console.log("页面可见,继续喂视频");
- requestTime = new Date().getTime();
- myVideo.play();
- } else {
- isFeed = false;
- //myVideo.pause();
- }
- });
- window.MediaSource = window.MediaSource || window.WebKitMediaSource;
- this.isMSESupported = !!window.MediaSource;
- if (!this.isMSESupported) {
- alert("不支持MSE");
- } else {
- alert("支持MSE");
- }
- myVideo.addEventListener('pause', function() {
- console.log("视频播放暂停");
- isFeed = false;
- });
- myAudio.addEventListener('onerror', function() {
- console.log("音频播放暂停");
- //myAudio.play();
- });
- function parse(data) {
- var input = new Uint8Array(data),
- dv = new DataView(input.buffer),
- duration,
- audioLength,
- audio,
- video;
- duration = dv.getUint16(0, true); //获取duration
- audioLength = dv.getUint16(2, true);
- if (audioLength == 0) {
- video = input.subarray(4);
- console.log("只有视频");
- } else {
- audio = input.subarray(4, (audioLength + 4));
- video = input.subarray(audioLength + 4);
- console.log("视频 + 音频");
- }
- return {
- audio: audio,
- video: video,
- duration: duration
- };
- }
- //解协议
- 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; //
- if (nalType == 0x07 || nalType == 0x08 || nalType == 0x05) //策略, 找到sps、sps、或I帧,才继续渲染
- {
- if (!isFeed) {
- console.log("%d, 检测到I帧,重新渲染, 耗时 %d ms", nalType, new Date().getTime() - requestTime);
- }
- isFeed = true;
- } else {
- }
- } else if (input[0] == 0xff) {
- audio = input;
- duration = 22;
- } 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("安卓卡此时横屏");
- //横屏处理
- }
- }
- //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://localhost:8080"
- // socketURL = "ws://192.168.11.238:8080";//C# websocket服务器中转
- // socketURL="wss://test.androidscloud.com/videoWebSocket?clientType=1&cardIp=14.215.128.96&port=2005&sn=RK3930C2301900005"
- //socketURL = "ws://127.0.0.1:8022/videoWebSocket?clientType=0&sn=RK3923C1201900139&cardIp=192.168.11.66&port=9100";
- /*socketURL = "ws://192.168.31.242:8022/videoWebSocket?clientType=0&sn=RK3923C1201900139&cardIp=192.168.11.66&port=9100";*/
- //flushingTime, 缓存刷新时间
- // socketURL = "ws://14.215.128.98:14112";
- socketURL = "ws://192.168.11.66:9101";
- 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: 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('message', function(event) {
- //console.log("喂数据");
- //jmuxer.feed(data);
- var data = ParseProto(event.data); //JAVA服务器转发
- //var data = parse(event.data);//分离音视频数据,C#转发
- // console.log("推流详情============",event.data);
- var audioData = {
- audio: data.audio,
- video: null,
- duration: data.duration
- };
- var videoData = {
- audio: null,
- video: data.video,
- duration: data.duration
- };
- var streamTemp = myAudio.captureStream();
- if (myAudio.readyState == 2) {
- console.log("出现声音停止");
- //alert("出现声音停止");
- //console.log("出现声音停止,当今进度 %s, %s", myAudio.played.end(0), myAudio.buffered.end(0));
- myAudio.play();
- }
- if (data.audio != null) //喂音频
- {
- //console.log("feed audio");
- audioMuxer.feed(audioData);
- }
- if (data.video != null) //喂视频
- {
- if (isFeed) {
- jmuxer.feed(data);
- }
- //jmuxer.feed(videoData);
- }
- if (data.video) {
- if (new Date().getTime() - curTime >= 1000) {
- //console.log("fps %d", fpsCount);
- fpsCount = 0;
- curTime = new Date().getTime();
- } else {
- fpsCount++;
- }
- }
- });
- myVideo.onmousedown = function(event) {
- //放在此处只是为了方便演示,实际使用中查找横竖屏只要刚连接上时调用一次就好。
- //var checkBuffer = GetScreenState();
- //ws.send(checkBuffer);
- /*if(!isFeed)
- {
- console.log("重新申请I帧");
- requestTime = new Date().getTime();
- var buffer = RequestIFrame();
- 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>
|