let $ip, $port, $user, $password, $loginState, $stream, $volume, $canvas, //canvas播放视频DOM $video, //video播放视频DOM $canvas_ivs, //canvas绘图DOM $video_wrap, //视频外层Wrap $videoLoading, //“加载中...”提示 WndIndex = 0, //宫格窗口Id WebCaps = null; //webCapsConfig文件转存变量 let isLogin = false; //是否登录 let channel = 0; //当前通道 let curPage = 1; //视频下载列表的当前页 let totalPage = 1; //视频下载列表的总页数 let recordArr = []; //视频文件数组 let canvasSon = null; //canvas绘图实例 let playerInstance = []; //播放|回放实例数组 let recordInstance = []; //录像下载实例数组 let talkInstance = []; //对讲实例数组 let ivsInstance = []; //canvas绘图实例数组 let cutInstance = []; //视频裁剪实例数组 let onlineChannel = []; //当前成功拉流的视频通道数组 let isCuting = false; //是否正在进行视频裁剪 let downList = []; //勾选的视频下载列表 let downItemIndex = 0; //视频下载索引 let canvasParam = { //canvas绘图默认传参 strokeColor: "#FF0000", title: "", resizeEnable: false, moveEnable: false, closeEnable: true, array: true, showSize: false, selectType: "inSide", disappear: true, selected: false, }; const lINENUMBER = 16; //回放列表每页显示录像条数 let curEnlargeWnd = 0; /** * @description 初始化 */ const init = () => { let videoStr = ""; for (var i = 0; i < 16; i++) { videoStr += '
'; } document.querySelector(".h5-play-wrap").innerHTML = videoStr; document.querySelectorAll(".h5-play-wrap div").forEach((item, index) => { item.addEventListener("click", function (event) { let _wndIndex = event.target.parentNode.getAttribute("wnd-index") - 0; if ( !(playerInstance[_wndIndex] && playerInstance[_wndIndex].isPlayback) ) { channel = event.target.parentNode.getAttribute("channel") - 0; document.querySelectorAll("#h5_channel_list li").forEach((item) => { item.classList.remove("fn-fontRed"); }); } document .querySelectorAll(".h5-play-wrap div") .forEach(function (item, index) { if (index === _wndIndex) { item.style.borderColor = "rgb(255, 204, 0)"; if ( !( playerInstance[_wndIndex] && playerInstance[_wndIndex].isPlayback ) ) { if (onlineChannel.indexOf(channel) > -1) { document .querySelector( '#h5_channel_list li[channel="' + channel + '"]' ) .classList.add("fn-fontRed"); } } WndIndex = _wndIndex; setVideoDom(); } else { item.style.borderColor = "rgb(125, 125, 125)"; } }); }); }); $ip = $("#h5_ip"); $port = $("#h5_port"); $user = $("#h5_user"); $password = $("#h5_password"); $loginState = $("#h5_loginState"); $stream = $("#h5_stream"); $volume = $("#h5_volume"); $video_wrap = document.querySelector(".h5-play-wrap"); setVideoDom(); let inputArr = document.querySelectorAll("input[btn-for]"); for (let node of inputArr) { node.addEventListener("click", bindClickEvent); } let selArr = document.querySelectorAll("select[sel-for]"); for (let node of selArr) { node.addEventListener("change", bindChangeEvent); } [ "fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "msfullscreenchange", ].forEach((item, index) => { document.addEventListener(item, fullscreenchange, false); }); onPreview(false); }; /** * @description 切换宫格时重新设置当前视频dom */ const setVideoDom = () => { $canvas = $("#h5_canvas_" + WndIndex); $video = $("#h5_video_" + WndIndex); $canvas_ivs = $("#h5_ivs_" + WndIndex); $videoLoading = $("#h5_loading_" + WndIndex); }; /** /** * @description 预览 * @param {boolean} isPlayback 是否是回放 * @param {string} url 回放视频的url * @param {number} playbackIndex 回放视频的索引 * @param {boolean} isChangeStream 是否是切换码流导致的重新拉流 */ const onPreview = (isPlayback, url, playbackIndex, isChangeStream) => { if ( playerInstance[WndIndex] && onlineChannel.indexOf(channel) > -1 && !isChangeStream ) { alert("通道" + (channel + 1) + "已存在!"); return; } onStopPreview(); var player = null; // if(!isLogin) { // alert('请先登录再预览!'); // return; // } // let curChannel = channel + 1; //无插件通道号从1开始 // let stream = $stream.value - 0 || 0; // let firstTime = 0; // let ip = $ip.value; // let port = $port.value - 0; // let username = $user.value; // let password = $password.value; let options = { wsURL: "ws://" + "221.214.127.18" + ":" + "8200" + "/rtspoverwebsocket", rtspURL: "rtsp://" + "221.214.127.18" + ":" + "8200" + "/cam/realmonitor?channel=1" + "&subtype=0" + "&proto=Private3", username: "admin", password: "pyss2017", lessRateCanvas: true, playback: isPlayback, isPrivateProtocol: false, realm: RPC.realm, //设备登录返回的realm playbackIndex: playbackIndex, }; player = new PlayerControl(options); player.on("MSEResolutionChanged", function (e) { console.log(e); }); player.on("PlayStart", function (e) { console.log(e); $videoLoading.style.display = "none"; let curWndType = document.querySelector("[sel-for=onChangeWdnNum]").value - 0; if (!player.isPlayback) { onlineChannel.push(channel); updateChannelList(); // if(curWndType !== 1) { // clickNextWnd(); // } } }); player.on("GetFrameRate", function (e) { console.log("GetFrameRate: " + e); }); player.on("FrameTypeChange", function (e) { console.log("FrameTypeChange: " + e); }); player.on("Error", function (e) { //console.log('Error: ' + JSON.stringify(e)) }); player.on("IvsDraw", function (e) { //console.log('IvsDraw: ' + JSON.stringify(e)) }); player.on("WorkerReady", function () { player.connect(); }); player.init($canvas, $video); $canvas.parentNode.setAttribute("channel", channel); $videoLoading.style.display = ""; }; /** * @description 更新通道列表 */ const updateChannelList = () => { document.querySelectorAll("#h5_channel_list li").forEach((item) => { item.classList.remove("fn-fontBlue"); item.classList.remove("fn-fontRed"); if (onlineChannel.indexOf(item.getAttribute("channel") - 0) > -1) { item.classList.add("fn-fontBlue"); } }); }; /** * @description 停止预览 */ const onStopPreview = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].stop(); playerInstance[WndIndex].close(); playerInstance[WndIndex] = null; let _index = onlineChannel.indexOf(channel); onlineChannel.splice(_index, 1); updateChannelList(); let dom = $canvas; if (dom.style.display === "none") { dom = $video; } dom.style.display = "none"; if (talkInstance[WndIndex]) { talkInstance[WndIndex].talk("off"); talkInstance[WndIndex] = null; } if (recordInstance[WndIndex]) { recordInstance[WndIndex].startRecord(false); recordInstance[WndIndex] = null; } } }; /** * @description 切换码流 */ const onChangeStream = () => { onPreview(false, null, null, true); }; /** * @description 开启音频 */ const onTurnOnSound = () => { let vol = $volume.value - 0; if (playerInstance[WndIndex]) { playerInstance[WndIndex].setAudioVolume(vol); } }; /** * @description 关闭音频 */ const onTurnSoundOff = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].setAudioVolume(0); } }; /** * @description 开启对讲 */ const onStartTalk = () => { let talkPlayer = null; let ip = $ip.value; let port = $port.value - 0; let username = $user.value; let password = $password.value; let curChannel = channel + 1; //无插件通道号从1开始 let rtspURL = "rtsp://" + "221.214.127.18" + ":" + "8200" + "/cam/realmonitor?channel=" + curChannel + "&subtype=0&proto=Private3"; let optionsAudio = { wsURL: "ws://" + "221.214.127.18" + ":" + "8200" + "/rtspoverwebsocket", rtspURL: rtspURL, username: "admin", password: "pyss2017", isTalkService: true, isPrivateProtocol: false, realm: RPC.realm, }; talkPlayer = new PlayerControl(optionsAudio); talkPlayer.talk("on"); talkInstance[WndIndex] = talkPlayer; }; /** * @description 关闭对讲 */ const onStopTalk = () => { if (talkInstance[WndIndex]) { talkInstance[WndIndex].talk("off"); talkInstance[WndIndex] = null; } }; /** * @description 抓图 */ const onSnap = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].capture("test"); } }; /** * @description 针对直播的,开始本地下载 */ const onStartRecord = () => { let recordPlayer = null; let ip = $ip.value; let port = $port.value - 0; let username = $user.value; let password = $password.value; let stream = $stream.value - 0 || 0; let rtspURL = "rtsp://" + "221.214.127.18" + ":" + "8200" + "/cam/realmonitor?channel=" + curChannel + "&subtype=0&proto=Private3"; let optionsAudio = { wsURL: "ws://" + "221.214.127.18" + ":" + "8200" + "/rtspoverwebsocket", rtspURL: rtspURL, username: "admin", password: "pyss2017", isTalkService: true, isPrivateProtocol: false, realm: RPC.realm, }; recordPlayer = new PlayerControl(optionsAudio); recordPlayer.startRecord(true); recordInstance[WndIndex] = recordPlayer; }; /** * @description 针对直播的,停止本地下载 */ const onStopRecord = () => { if (recordInstance[WndIndex]) { recordInstance[WndIndex].startRecord(false); recordInstance[WndIndex] = null; } }; /** * @description 针对回放视频的,视频裁剪 */ const onStartCut = () => { let _cutIndex = document.querySelector("[btn-for=onStartCut]").getAttribute("cutIndex") - 0; _cutIndex = _cutIndex + (curPage - 1) * lINENUMBER; let cutPlayer = null; let ip = $ip.value; let port = $port.value - 0; let username = $user.value; let password = $password.value; let url = recordArr[_cutIndex].FilePath; let _rtspURL = "rtsp://" + ip + ":" + port + "/" + url; let cutStartTime = $("#h5_cutStartTime").value; let s = new Date(cutStartTime.replace("T", " ")).getTime(); let startTime = new Date(recordArr[_cutIndex].StartTime).getTime(); let range1 = (s - startTime) / 1000; let firstTime = 0; let optionsRecord = { wsURL: "ws://" + ip + ":" + port + "/rtspoverwebsocket", rtspURL: _rtspURL, username: username, password: password, isPrivateProtocol: false, //是否私有协议,默认false realm: RPC.realm, //登录返回的设备Realm值 speed: 16, //倍速拉流,16倍速 playback: true, //是都回放 isDownLoad: true, range: range1, //视频裁剪时间与视频的StartTime时间差值 }; cutPlayer = new PlayerControl(optionsRecord); cutPlayer.on("FileOver", function () { console.log("File Over"); cutPlayer.startCut(false); isCuting = false; $("#h5_cut_process").innerText = "100%"; }); cutPlayer.on("UpdateTimeStamp", function (e) { let cutStartTime1 = $("#h5_cutStartTime").value; let cutEndTime1 = $("#h5_cutEndTime").value; if (firstTime === 0) { firstTime = e.timestamp; } let s1 = new Date(cutStartTime1.replace("T", " ")).getTime() / 1000; let e1 = new Date(cutEndTime1.replace("T", " ")).getTime() / 1000; let process = parseInt(((e.timestamp - firstTime) / (e1 - s1)) * 100); // console.log(new Date(e.timestamp * 1000)); $("#h5_cut_process").innerText = (process > 100 ? 100 : process) + "%"; if (e.timestamp >= s1 && !isCuting) { cutPlayer.startCut(true); isCuting = true; } if (e.timestamp >= e1 && isCuting) { cutPlayer.startCut(false); isCuting = false; $("#h5_cut_process").innerText = "100%"; } }); cutPlayer.init($canvas, $video); cutPlayer.connect(true); cutInstance[WndIndex] = cutPlayer; }; /** * @description 开始下载录像 * @param {object} item 录像信息 */ const onStartNVRDownload = (item) => { let _cutIndex; if (item) { _cutIndex = item.selfCheckIndex; } let firstTime = 0; let cutPlayer = null; let ip = $ip.value; let port = $port.value - 0; let username = $user.value; let password = $password.value; let url = recordArr[_cutIndex].FilePath; let _rtspURL = "rtsp://" + ip + ":" + port + "/" + url; let optionsRecord = { wsURL: "ws://" + ip + ":" + port + "/rtspoverwebsocket", rtspURL: _rtspURL, username: username, password: password, isPrivateProtocol: false, realm: RPC.realm, speed: 16, playback: true, isDownLoad: true, }; cutPlayer = new PlayerControl(optionsRecord); cutPlayer.on("FileOver", function () { console.log("File Over"); cutPlayer.startCut(false); isCuting = false; $("#h5_down_process").innerText = "100%"; downItemIndex++; if (downList[downItemIndex]) { onStartNVRDownload(downList[downItemIndex]); } }); cutPlayer.on("UpdateTimeStamp", function (e) { let s1 = new Date(item.StartTime).getTime() / 1000; let e1 = new Date(item.EndTime).getTime() / 1000; if (firstTime === 0) { firstTime = e.timestamp; } let process = parseInt(((e.timestamp - firstTime) / (e1 - s1)) * 100); $("#h5_down_process").innerText = (process > 100 ? 100 : process) + "%"; if (e.timestamp >= firstTime && !isCuting) { cutPlayer.startCut(true); isCuting = true; } if ((e.timestamp >= e1 || process >= 100) && isCuting) { cutPlayer.startCut(false); isCuting = false; $("#h5_down_process").innerText = "100%"; downItemIndex++; if (downList[downItemIndex]) { onStartNVRDownload(downList[downItemIndex]); } } }); cutPlayer.init($canvas, $video); cutPlayer.connect(true); cutInstance[WndIndex] = cutPlayer; }; const stopDownLoad = () => { cutInstance.forEach((item) => { if (item) { isCuting = false; item.stop(); item.close(); item.startCut(false, true); } }); }; /** * @description 开启电子放大 */ const onStartEnlarge = () => { if (ivsInstance[WndIndex]) { ivsInstance[WndIndex].setRegionNum("rect", 1); let param = { ...canvasParam }; ivsInstance[WndIndex].drawStart("rect", param); curEnlargeWnd = WndIndex; } }; /** * @description 关闭电子放大 */ const onStopEnlarge = () => { if (curEnlargeWnd != WndIndex) return; let dom = $canvas; if (dom.style.display === "none") { dom = $video; } dom.style.width = "100%"; dom.style.height = "100%"; dom.style.left = 0; dom.style.top = 0; dom.style.position = "static"; }; /** * @description 暂停回放 */ const onPausePlayback = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].pause(); } }; /** * @description 继续回放 */ const onContinuePlayback = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].play(); } }; /** * @description 停止回放 */ const onClosePlayback = () => { if (playerInstance[WndIndex]) { playerInstance[WndIndex].stop(); playerInstance[WndIndex].close(); playerInstance[WndIndex] = null; let dom = $canvas; if (dom.style.display === "none") { dom = $video; } dom.style.display = "none"; } }; /** * @description 录像跳到指定时间 * @param 要跳转时间的录像的id */ const onGoTime = (id) => { let curTime = $("#h5_goTime_" + id).value - 0; if (playerInstance[WndIndex]) { playerInstance[WndIndex].playByTime(curTime); } }; /** * @description 切换窗口分割 */ const onChangeWdnNum = () => { let val = document.querySelector("[sel-for=onChangeWdnNum]").value; let ivsDom = document.querySelectorAll("[id^=h5_ivs_]"); let divDom = document.querySelectorAll(".h5-play-wrap div"); if (val === "1") { divDom.forEach((item) => { item.style.width = "100%"; item.style.height = "100%"; item.style.borderColor = "#000"; }); } else if (val === "2") { divDom.forEach((item, index) => { item.style.width = "calc(50% - 2px)"; item.style.height = "calc(50% - 2px)"; if (index === 0) { item.style.borderColor = " rgb(255, 204, 0)"; } else { item.style.borderColor = " rgb(125, 125, 125)"; } }); } else if (val === "3") { divDom.forEach((item, index) => { item.style.height = "calc(33.333% - 2px)"; item.style.width = "calc(33.333% - 2px)"; if (index === 0) { item.style.borderColor = " rgb(255, 204, 0)"; } else { item.style.borderColor = " rgb(125, 125, 125)"; } }); } else if (val === "4") { divDom.forEach((item, index) => { item.style.width = "calc(25% - 2px)"; item.style.height = "calc(25% - 2px)"; if (index === 0) { item.style.borderColor = "rgb(255, 204, 0)"; } else { item.style.borderColor = "rgb(125, 125, 125)"; } }); } ivsDom.forEach((item) => { item.setAttribute("width", `${item.parentNode.clientWidth}`); item.setAttribute("height", `${item.parentNode.clientHeight}`); }); ivsInstance.forEach((item) => { item && item.resize(); }); document.querySelector("#h5_ivs_0").click(); }; /** * @description 自定义选择器 * @param {string} str dom元素 */ function $(str) { if (str.charAt(0) == "#") { return document.getElementById(str.substring(1)); } else if (str.charAt(0) == ".") { return document.getElementsByClassName(str.substring(1)); } else { return document.getElementsByTagName(str); } } /** * @description 设置样式 * @param {object} obj dom元素 * @param {*} json css样式 */ function setStyle(obj, json) { for (let i in json) { obj.style[i] = json[i]; } } /** * @description 绑定click事件 * @param {object} event event对象 */ function bindClickEvent(event) { let $el = event.target, method = $el.getAttribute("btn-for"), disabled = $el.getAttribute("disabled"); if (!disabled) { eval(method + "()"); } } /** * @description 绑定change事件 * @param {object} event event对象 */ function bindChangeEvent(event) { let $el = event.target, method = $el.getAttribute("sel-for"), disabled = $el.getAttribute("disabled"); if (!disabled) { eval(method + "()"); } } //进入页面自动初始化 init();