<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0" /> <title>CMS Player</title> <link rel="shortcut icon" href="#" /> <script src="./public/player/cmsplayer.js"></script> <script src="./public/player/common.js"></script> <script src="./public/player/pcm-player.js"></script> <script src="./public/player/webgl.js"></script> <script src="./public/player/cmstalk.js"></script> <script src="./public/player/alawmulaw.js"></script> <script src="./public/player/recorder-core.js"></script> <script src="./public/js/moment.js"></script> <script src="./public/js/axios.min.js"></script> <script src="./public/js/jquery-2.2.3.min.js"></script> <style> html, body { width: 100%; height: 100%; margin: 0; /* padding: 30px; */ box-sizing: border-box; } div { user-select: none; -ms-user-select: none; -moz-user-select: none; -html-user-select: none; -webkit-user-select: none; } ul { list-style: none; } ul li { height: 100%; float: left; box-sizing: border-box; } #videoTimeTrack li { border-right: 1px solid #ccc; } #videoTimeTrack li:first-child { border-left: 1px solid #ccc; } #playerBox { height: 96%; width: 100%; } </style> </head> <body ontouchstart> <div id="playerBox"></div> <div style="display: flex;"> <button class="layui-btn" id="talk-real-server">实时视频对讲</button> <button style="margin-left: 20px;" class="layui-btn" id="talk-real-server-close">关闭实时视频对讲</button> </div> <script type="text/javascript"> let stream, audioContext, source, processor; var PLAYURL window.onload = function () { self.player = new Player($("#playerBox")); function getParams(key) { var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) { return decodeURIComponent(r[2]); // 使用 decodeURIComponent 代替 unescape } return null; } var locationUrl = window.location.href; var id = getParams("id"); var title = getParams("title"); let requestBody = { pointId: id, useTLS: 0 } // console.log(window.location, locationUrl, id, title); try { if (window.location.host === 'www.hndyjqrh.cn') { requestBody.useTLS = 1 } // requestBody.useTLS = 1 let url = 'https://www.hndyjqrh.cn/api/multialarm/video/preview' axios({ method: 'post', url, data: { ...requestBody } }).then(res => { // console.log(res); PLAYURL = res.data.data.videoUrl self.player.play(PLAYURL, true, ""); }).catch(function (error) { console.log(error) }) } catch (error) { console.log(error); } $("html>head>title").html(title); var socket var wsUrl = '' document.getElementById("talk-real-server").onclick = function () { wsUrl = 'ws://222.245.132.168:19555/talk/pcma/stream/COWN-ZK9-Z2-C3E/QsTzeGZPrpiCxmlok44NMsdE' self.player.talkUrl = wsUrl; self.player.play(PLAYURL, true, ""); console.log(1111); axios({ method: 'post', url: 'https://www.hndyjqrh.cn/api/multialarm/talk/channel', data: { ...requestBody } }).then(res => { console.log('talk/channel', res); // wsUrl = res.data.data.videoUrl // 创建 WebSocket 连接 // socket = new WebSocket(wsUrl); // // 监听 WebSocket 连接的打开事件 // socket.onopen = function (event) { // console.log('WebSocket 连接已打开'); // console.log('socket_______________', socket); // // 获取麦克风的音频流 // if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { // console.log("支持 getUserMedia"); // } else { // console.error("当前浏览器不支持 getUserMedia"); // } // // 转换格式 // function encodeALaw(sample) { // const ALAW_MAX = 0xFFF; // 12-bit max value // const ALAW_BIAS = 0x84; // 132 // let sign = (sample & 0x8000) >> 8; // 提取符号位 // if (sign !== 0) sample = -sample; // 如果是负数,取反 // if (sample > ALAW_MAX) sample = ALAW_MAX; // 限制最大值 // // A-Law 编码公式 // let magnitude; // if (sample >= 256) { // magnitude = (sample >> 8) & 0x7F; // magnitude += 8; // } else { // magnitude = (sample >> 4) & 0x0F; // } // let aLawByte = sign | magnitude; // return aLawByte ^ 0xD5; // 反转特定位以匹配 A-Law 规范 // } // // 示例代码:将 PCM 数据转换为 A-Law 数据 // navigator.mediaDevices.getUserMedia({ audio: true }) // .then(audioStream => { // stream = audioStream // audioContext = new AudioContext({ sampleRate: 8000 }); // source = audioContext.createMediaStreamSource(stream); // processor = audioContext.createScriptProcessor(4096, 1, 1); // processor.onaudioprocess = function (event) { // const audioData = event.inputBuffer.getChannelData(0); // const int16Array = new Int16Array(audioData.length); // // 转换为 16 位 PCM 数据 // for (let i = 0; i < audioData.length; i++) { // int16Array[i] = Math.max(-1, Math.min(1, audioData[i])) * 0x7FFF; // } // // 将 16 位 PCM 转换为 A-Law 编码 // const aLawData = new Uint8Array(int16Array.length); // for (let i = 0; i < int16Array.length; i++) { // aLawData[i] = encodeALaw(int16Array[i]); // } // // 分块发送 A-Law 数据,块大小可以为 320, 480, 640 或 960 字节 // const blockSize = 320; // for (let j = 0; j < aLawData.length; j += blockSize) { // const chunk = aLawData.slice(j, j + blockSize); // socket.send(chunk.buffer); // console.log('发送音频数据块:', chunk); // } // }; // source.connect(processor); // processor.connect(audioContext.destination); // }) // .catch(error => { // console.error('获取音频流失败:', error); // }); // }; // // 监听 WebSocket 收到消息事件 // socket.onmessage = function (event) { // console.log('收到消息:', event.data); // }; // // 监听 WebSocket 连接关闭事件 // socket.onclose = function (event) { // console.log('WebSocket 连接已关闭'); // }; // // 监听 WebSocket 连接出错事件 // socket.onerror = function (event) { // console.error('WebSocket 错误:', event); // }; }).catch(function (error) { console.log(error) }) } document.getElementById("talk-real-server-close").onclick = function () { // socket.close(); // 关闭 WebSocket 连接 console.log(socket); console.log(socket.readyState); console.log(WebSocket.OPEN); if (socket && socket.readyState === WebSocket.OPEN) { socket.close(); // 关闭 WebSocket 连接 // 停止麦克风录音 if (stream) { const tracks = stream.getTracks(); tracks.forEach(track => track.stop()); } // 关闭 AudioContext 和处理器 if (audioContext) { audioContext.close(); } if (processor) { processor.disconnect(); } if (source) { source.disconnect(); } console.log('WebSocket 连接已关闭'); } else { console.log('WebSocket 连接未打开或已关闭'); } }; } </script> </body> </html>