/* * 本文件仅供demo使用 */ //webpack中引用此代码块,格式不要随意改动 //开发模式需要import,打包给3.0的变成了全局变量,不需要 var playerIndex = 0 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 = { value:atob('MTkyLjE2OC4xMC4xMDg=') }; $port = $('#h5_port'); // $user = $('#h5_user'); // $password = $('#h5_password'); $user = { value:atob('YWRtaW4=') }; $password = { value:atob('YWYxMjM0NTYh') }; $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); } $volume.addEventListener('input', function (event) { let vol = event.target.value - 0; $('#h5_volume_value').innerText = vol; }); $volume.addEventListener('change', function (event) { let vol = event.target.value - 0; if (playerInstance[WndIndex]) { playerInstance[WndIndex].setAudioVolume(vol); } }); $('#h5_first').addEventListener('click', function () { if (curPage != 1) { curPage = 1; updateTable(); } }); $('#h5_pre').addEventListener('click', function () { if (curPage > 1) { curPage = curPage - 1; updateTable(); } }); $('#h5_next').addEventListener('click', function () { if (curPage < totalPage) { curPage = curPage + 1; updateTable(); } }); $('#h5_last').addEventListener('click', function () { if (curPage != totalPage) { curPage = totalPage; updateTable(); } }); $('#h5_goPage').addEventListener('click', function () { let val = $('#h5_goNumber').value - 0; if (curPage != val) { curPage = val; updateTable(); } }); ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'msfullscreenchange'].forEach((item, index) => { document.addEventListener(item, fullscreenchange, false); }); } /** * @description 切换宫格时重新设置当前视频dom */ const setVideoDom = () => { $canvas = $('#h5_canvas_' + WndIndex); $video = $('#h5_video_' + WndIndex); $canvas_ivs = $('#h5_ivs_' + WndIndex); $videoLoading = $('#h5_loading_' + WndIndex); } /** * @description 登录 */ const onLogin = (id, playerStartTime, playerEndTime) => { playerInstance.forEach(item => { if (item) { item.close(); item = null; } }); talkInstance.forEach(item => { if (item) { item.talk('off'); item = null; } }); recordInstance.forEach(item => { if (item) { item.startRecord(false); item = null; } }); $('#h5_channel_list').innerHTML = ''; $('#h5_playback_channel').options.length = 0; onlineChannel = []; let ip = $ip.value; let port = $port.value; let target = ip + ':' + port; setIP(target); $loginState.innerHTML = '未登录'; $loginState.style.color = 'red'; /** * RPC.login 登录 * @param {string} $user.value 用户名 * @param {string} $password.value 密码 * @param {boolean} true 是否httpOnly,默认false * @returns {Promise} */ RPC.login($user.value, $password.value, false).then((res) => { console.info('登录成功'); /** * RPC.keepAlive 保活 */ RPC.keepAlive(300, 60000, _getSession(), target); const browser = BrowserType(); if (browser.includes('ie')) { window.onunload = () => { ajax({ url: 'global.logout' }); }; } else if (browser.includes('chrome')) { const params = { method: 'global.logout', params: null, id: 10000, session: _getSession() }; pubsub.subscribe('onbeforeunload', () => { navigator.sendBeacon('/RPC2', JSON.stringify(params)); }); } else { pubsub.subscribe('onbeforeunload', () => { ajax({ url: 'global.logout' }); }); } $loginState.style.color = 'green'; $loginState.innerHTML = '已登录'; // 查询对应编号的回放视频 onSearchRecord(id, playerStartTime, playerEndTime) setLoginState(true); afterLogin(); }).catch((err) => { }); } /** * @description 登录之后调用,获取设备能力,获取通道、码流 */ const afterLogin = () => { $('#h5_playback_channel').options.length = 0; $('#h5_channel_list').innerHTML = ''; /** * RPC.getUrlData 获取设备上的文件 * @param {string} 文件路径 * @returns {Promise} */ RPC.getUrlData(`/web_caps/webCapsConfig?version=2.400&${new Date().getTime()}`).then(json => { WebCaps = json; if (WebCaps.deviceType.indexOf('SD') > -1 || WebCaps.deviceType.indexOf('IPC') > -1) { /** * RPC.DevVideoInput.getCollect 获取模拟输入通道数 * @returns {Promise} */ RPC.DevVideoInput.getCollect().then(function (params) { let channelNum = params.channels; for (let i = 0; i < channelNum; i++) { let li = document.createElement('li'); li.innerHTML = 'D' + (i + 1); li.setAttribute('channel', i); li.style.width = '140px'; $('#h5_channel_list').appendChild(li); $('#h5_playback_channel').options.add(new Option(i + 1, i)); } document.querySelectorAll('#h5_channel_list li').forEach(item => { item.addEventListener('click', function (event) { event.stopPropagation(); let $el = event.target; channel = $el.getAttribute('channel') - 0; if (onlineChannel.indexOf(channel) > -1 && (channel != $canvas.parentNode.getAttribute('channel') - 0)) { return; } if ($el.className.indexOf('fn-fontBlue') > -1 || $el.className.indexOf('fn-fontRed') > -1) { onStopPreview(); } else { onPreview(false); } }); }); }); } }).catch(() => { /** * RPC.LogicDeviceManager.getCameraAll 获取所有用户可用视频源 * @returns {Promise} */ RPC.LogicDeviceManager.getCameraAll().then(function (params) { let channelList = params.camera.filter(item => item.Enable === true); //预览,在线通道列表 let channelArr = channelList.map(item => { let _name; item.DeviceInfo.VideoInputs.map(value => { if (value && value.Enable) { _name = value.Name; } }); return item.UniqueChannel + ';' + _name; }); // 回放,全部通道列表 let allArr = params.camera.map(item => { let _name; if (item.DeviceInfo && item.DeviceInfo.VideoInputs) { item.DeviceInfo.VideoInputs.map(value => { _name = value && value.Name; }); return item.UniqueChannel + ';D' + (item.UniqueChannel + 1) + ' ' + _name; } }); allArr.forEach((item) => { if (item) { let _item = item.split(';'); let _chan = _item[0] - 0; let name = _item[1]; if (name) { $('#h5_playback_channel').options.add(new Option(name, _chan)); } } }); channelArr.forEach((item) => { let _item = item.split(';'); let _chan = _item[0] - 0; let name = _item[1]; let li = document.createElement('li'); li.innerHTML = 'D' + (_chan + 1) + ' ' + name; li.setAttribute('channel', _chan); $('#h5_channel_list').appendChild(li); }); document.querySelectorAll('#h5_channel_list li').forEach(item => { item.addEventListener('click', function (event) { event.stopPropagation(); let $el = event.target; channel = $el.getAttribute('channel') - 0; if (onlineChannel.indexOf(channel) > -1 && (channel != $canvas.parentNode.getAttribute('channel') - 0)) { return; } if ($el.className.indexOf('fn-fontBlue') > -1 || $el.className.indexOf('fn-fontRed') > -1) { onStopPreview(); } else { onPreview(false); } }); }); }); }); $stream.options.length = 0; /** * RPC.MagicBox.getProductDefinition 获取产品定义 * @param {string} 'MaxExtraStream' 定义名称 * @returns {Promise} */ RPC.MagicBox.getProductDefinition('MaxExtraStream').then(function (params) { let maxExtra = params.definition; $stream.options.add(new Option('主码流', 0)); if (maxExtra > 1) { for (let i = 1; i <= maxExtra; i++) { $stream.options.add(new Option('辅码流' + i, i)); } } else { $stream.options.add(new Option('辅码流', 1)); } }); let curDate = new Date(); let dateString = curDate.toLocaleDateString(); let dateSplit = dateString.split('/'); let month = dateSplit[1] - 0; if (month < 10) { dateSplit[1] = '0' + month; } let day = dateSplit[2] - 0; if (day < 10) { dateSplit[2] = '0' + day; } let date = dateSplit.join('-'); } /** * @description 注销 */ const onLogout = () => { /** * RPC.Global.logout 注销接口 * @returns {Promise} */ RPC.Global.logout().then(function () { $loginState.style.color = 'red'; $loginState.innerHTML = '未登录'; setLoginState(false); playerInstance.forEach(item => { if (item) { item.stop(); item.close(); item = null; } }); cutInstance.forEach(item => { if (item) { item.stop(); item.close(); item = null; } }); talkInstance.forEach(item => { if (item) { item.talk('off'); item = null; } }); recordInstance.forEach(item => { if (item) { item.startRecord(false); item = null; } }); $('#h5_channel_list').innerHTML = ''; $('#h5_playback_channel').options.length = 0; document.querySelectorAll('[id^=h5_canvas_]').forEach(item => { if (item.style.display === '') { item.style.display = 'none'; } }); document.querySelectorAll('[id^=h5_video_]').forEach(item => { if (item.style.display === '') { item.style.display = 'none'; } }); }); } /** * @description 点击下一个宫格,在当前宫格成功拉流后,自动选中下一个宫格 */ const clickNextWnd = () => { let curWndType = document.querySelector('[sel-for=onChangeWdnNum]').value - 0; if (curWndType === 2 && WndIndex === 3 || curWndType === 3 && WndIndex === 8 || curWndType === 4 && WndIndex === 15) { document.querySelector('#h5_ivs_0').click(); } else { document.querySelector('#h5_ivs_' + (WndIndex + 1)).click(); } } /** * @description 预览 * @param {boolean} isPlayback 是否是回放 * @param {string} url 回放视频的url * @param {number} playbackIndex 回放视频的索引 * @param {boolean} isChangeStream 是否是切换码流导致的重新拉流 * @param playerStartTime 开始时间戳 * @param playerEndTime 结束时间戳 */ const onPreview = (isPlayback, url, playbackIndex, isChangeStream, playerStartTime,playerEndTime) => { 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://' + ip + ':' + port + '/rtspoverwebsocket', rtspURL: !isPlayback ? 'rtsp://' + ip + ':' + port + '/cam/realmonitor?channel=' + curChannel + '&subtype=' + stream + '&proto=Private3' : 'rtsp://' + ip + ':' + port + '/' + url, username: username, password: password, 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) { $videoLoading.style.display = 'none'; let curWndType = document.querySelector('[sel-for=onChangeWdnNum]').value - 0; if (!player.isPlayback) { onlineChannel.push(channel); updateChannelList(); // if(curWndType !== 1) { // clickNextWnd(); // } } if(player.isPlayback){ // 跳转指定时间播放 if(playerStartTime>15){ playerStartTime = playerStartTime - 15 }else{ playerStartTime = 0 } player.playByTime(playerStartTime) } }); player.on('DecodeStart', function (e) { console.log('DecodeStart',e) if (e.decodeMode === 'video') { $video.style.display = ''; $canvas.style.display = 'none'; } else { $video.style.display = 'none'; $canvas.style.display = ''; } canvasSon = new PluginCanvasES6(); canvasSon.init($canvas_ivs, function (data) { rebackActivateLocalEnlarging(data); }); canvasSon.addChangeShapeEvent(); playerInstance[WndIndex] = player; ivsInstance[WndIndex] = canvasSon; }); player.on('UpdateCanvas', function (e) { // console.log('UpdateCanvas',e) if (player.isPlayback) { let playbackIndex = player.playbackIndex; if (firstTime === 0) { firstTime = e.timestamp; } //const _left = e.timestamp - new Date(recordArr[playbackIndex].StartTime).getTime()/1000; $('#h5_curTime_' + playbackIndex % lINENUMBER).innerText = e.timestamp - firstTime; } }); player.on('GetTotalTime', function (e) { let playbackIndex = player.playbackIndex % lINENUMBER; $('#h5_totalTime_' + playbackIndex).innerText = e; }); player.on('GetFrameRate', function (e) { console.log('GetFrameRate: ' + e) }); player.on('FrameTypeChange', function (e) { console.log('FrameTypeChange: ' + e) }); player.on('IvsDraw', function (e) { console.log('IvsDraw: ' + JSON.stringify(e)) }); player.on('WorkerReady', function () { console.log('WorkerReady') player.connect(); }); player.on('FileOver', function () { console.log('播放完成'); // if (playerIndex < recordArr.length - 1) { // // 依次播放所有视频 // playerIndex++ // playerFun(playerIndex, 0, playerEndTime) // } }) player.on('UpdateTimeStamp', function (e) { if(window.parent.onDhTimeUpdate){ window.parent.onDhTimeUpdate(e.timestamp) } if (e.timestamp > playerEndTime) { console.log('UpdateTimeStamp-timestamp',e); console.log('UpdateTimeStamp-playerEndTime',playerEndTime); playerIndex = 0 onStopPreview() // 加载下一个视频 if(window.parent.nextPlayer){ window.parent.nextPlayer(true) } } }) 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://' + ip + ':' + port + '/cam/realmonitor?channel=' + curChannel + '&subtype=5&proto=Private3'; let optionsAudio = { wsURL: 'ws://' + ip + ':' + port + '/rtspoverwebsocket', rtspURL: rtspURL, username: username, password: password, 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://' + ip + ':' + port + '/cam/realmonitor?channel=' + (channel + 1) + '&subtype=' + stream + '&proto=Private3'; let optionsRecord = { wsURL: 'ws://' + ip + ':' + port + '/rtspoverwebsocket', rtspURL: rtspURL, username: username, password: password, isPrivateProtocol: false, realm: RPC.realm } recordPlayer = new PlayerControl(optionsRecord); 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 onStartGridEnlarge = () => { document.querySelectorAll('[wnd-index]').forEach((item, index) => { if (index === WndIndex) { document.querySelector('[wnd-index="' + WndIndex + '"]').style.width = '500px'; document.querySelector('[wnd-index="' + WndIndex + '"]').style.height = '300px'; } else { item.style.display = 'none'; } }); } /** * @description 关闭区域放大 */ const onCloseGridEnlarge = () => { document.querySelectorAll('[wnd-index]').forEach((item, index) => { item.style.display = ''; }); onChangeWdnNum(); } /** * @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 绘制电子放大后的回调函数 * @param {object} data 矩形框的坐标信息 */ const rebackActivateLocalEnlarging = data => { if (curEnlargeWnd != WndIndex) return; let pos = data.data; let newData; if (pos[0][0] === pos[1][0]) { // return false; } else { newData = { left: pos[0][0], top: pos[0][1], right: pos[1][0], bottom: pos[1][1] } } let dom = $canvas; if (dom.style.display === 'none') { dom = $video; } // 倒着画 if (newData.right < newData.left) { let tmp = newData.left; newData.left = newData.right; newData.right = tmp; } if (newData.bottom < newData.top) { let tmp = newData.top; newData.top = newData.bottom; newData.bottom = tmp; } let scaleW = $video_wrap.childNodes[0].clientWidth / 8191; let scaleH = $video_wrap.childNodes[0].clientHeight / 8191; let result = zoomArea(newData.left * scaleW, newData.top * scaleH, newData.right * scaleW, newData.bottom * scaleH, $video_wrap.childNodes[0].clientWidth, $video_wrap.childNodes[0].clientHeight); dom.style.width = result.width + 'px'; dom.style.height = result.height + 'px'; dom.style.left = result.left + 'px'; dom.style.top = result.top + 'px'; dom.style.position = 'absolute'; ivsInstance[WndIndex].removeShapeDrawEvent(); } /** * @description 设置全屏 */ const onSetFull = () => { if (getFull()) { exitfullScreen(); } else { setfullScreen(); } } /** * @description 查询录像 */ const onSearchRecord = async (id, playerStartTime, playerEndTime) => { let allRecords = []; let recordNums = 0; let playChannel = id; const getMediaFile = (params) => { return new Promise((resolve, reject) => { /** * RPC.MediaFileFind.instance 创建媒体文件查找实例 * @returns {Promise} */ RPC.MediaFileFind.instance().then(json => { let queryId = json.result; /** * RPC.MediaFileFind.findFile 设置查找条件,并判断是否存在文件 * @param {number} queryId 实例id * @param {object} params condition参数 * @returns {Promise} */ RPC.MediaFileFind.findFile(queryId, params).then(() => { findNextFile(queryId).then(() => { resolve(true); }).catch((err) => { reject(err); }); }).catch((err) => { reject(err); }); }).catch((err) => { reject(err); }); }); } const findNextFile = (queryId) => { return new Promise((resolve, reject) => { /** * RPC.MediaFileFind.findNextFile 在指定条件基础上查询文件信息 * @param {number} queryId 实例 * @param {object} 需要查找的数目 * @returns {Promise} */ RPC.MediaFileFind.findNextFile(queryId, { 'count': 100 }).then(data => { if (Number.isInteger(data.found)) { recordNums = recordNums + data.found; allRecords = allRecords.concat([...data.infos]); if (data.found === 100) { findNextFile(queryId).then(() => { resolve(true); }).catch((err) => { reject(err); }); } else { recordArr = [...allRecords]; console.log(recordArr); updateInfos(recordArr.slice(0, lINENUMBER)); updatePages(); stopFind(queryId); resolve(true); } } else { stopFind(queryId); resolve(true); } }).catch((err) => { reject(err); stopFind(queryId); }); }) } const stopFind = object => { return new Promise((resolve, reject) => { /** * PC.MediaFileFind.close 结束查询 * @param {number} object 媒体文件查找实例ID * @returns {Promise} */ RPC.MediaFileFind.close(object).then(() => { /** * PC.MediaFileFind.destroy 销毁媒体文件查找实例 * @param {number} object 媒体文件查找实例ID */ RPC.MediaFileFind.destroy(object); resolve(true); }).catch(() => { reject(); }).finally(() => { }); }) } const updateInfos = (infos) => { let table = document.querySelector('#h5_table tbody'); table.innerHTML = ''; for (let i = 0; i < infos.length; i++) { let time = infos[i].StartTime + ' - ' + infos[i].EndTime; // let size = Math.round(infos[i].Length / 1024); let newRow = table.insertRow(-1); newRow.innerHTML = `${i + 1}${time}${size}--/--`; } document.querySelectorAll('[id^=h5_button_go_]').forEach(item => { item.addEventListener('click', function (event) { let id = item.getAttribute('id').split('_')[3] - 0; onGoTime(id); }); }); document.querySelectorAll('[id^=h5_check_]').forEach(function (item) { item.addEventListener('click', function (event) { event.stopPropagation(); if (event.target.checked) { //渲染裁剪时间 let _index = event.target.getAttribute('id').split('_')[2] - 0; let startTime = recordArr[_index + lINENUMBER * (curPage - 1)].StartTime.split(' ').join('T'); let endTime = recordArr[_index + lINENUMBER * (curPage - 1)].EndTime.split(' ').join('T'); if (startTime.split(':')[2] === '00') { startTime = startTime.substr(0, startTime.length - 3); } if (endTime.split(':')[2] === '00') { endTime = endTime.substr(0, endTime.length - 3); } $('#h5_cutStartTime').value = startTime; $('#h5_cutEndTime').value = endTime; document.querySelector('[btn-for=onStartCut]').setAttribute('cutIndex', _index); } }); }); document.querySelectorAll('#h5_table tbody tr').forEach(function (item) { item.addEventListener('dblclick', function (event) { event.stopPropagation(); if (event.target.nodeName === 'TD') { event.target.style.color = 'blue'; let dom = event.target.parentNode.childNodes[1]; let value = dom.innerText - 1; let url = recordArr[value].FilePath; onStopPreview(); onPreview(true, url, value); } }); }); playerFun(playerIndex, playerStartTime, playerEndTime) } const updatePages = () => { totalPage = Math.ceil(recordNums / lINENUMBER); $('#h5_curPage').innerText = curPage; $('#h5_totalPage').innerText = totalPage; } let tmpDir = []; try { /** * RPC.getDeviceAllInfo 获取存储信息 * @param {string} 'getDeviceAllInfo' 方法名 * @return {Promise} */ tmpDir = await RPC.getDeviceAllInfo('getDeviceAllInfo'); } catch (e) { console.log(e); } let dirs = null; if (tmpDir.info && tmpDir.info.length > 1) { dirs = 'All'; } else { //dirs = tmpDir.info?[0]?.Detail?[0]?.Path ?? '/mnt/sd'; dirs = tmpDir.info && tmpDir.info[0] && tmpDir.info[0].Detail && tmpDir.info[0].Detail[0] && tmpDir.info[0].Detail[0].Path || '/mnt/sd'; } let startTime = $('#h5_startTime').value.replace('T', ' '); let endTime = $('#h5_endTime').value.replace('T', ' '); if (startTime.split(' ')[1].split(':').length < 3) { startTime = startTime + ':00'; } if (endTime.split(' ')[1].split(':').length < 3) { endTime = endTime + ':00'; } let params = { condition: { Channel: playChannel, Dirs: [dirs], StartTime: startTime, EndTime: endTime, Flags: null, Events: ['*'], Types: ['dav'] } }; getMediaFile(params).catch((err) => { if (err && err.error && err.error.code === 285409409) { alert('回放功能需要确保SD卡经过设备认证'); } else { // alert('无数据'); } }); } /** * @description 勾选当前页的全部录像 */ const onCheckAll = () => { let dom = $('#h5_checkAll'); let ele = document.querySelectorAll('[id^=h5_check_]'); let domChecked = dom.checked; ele.forEach((item, index) => { item.checked = domChecked; }) } /** * @description 下载录像 */ const onDownload = async () => { let ele = document.querySelectorAll('[id^=h5_check_]'); downList = []; ele.forEach((item, index) => { let _id = item.getAttribute('id').split('_')[2] - 0; if (item.checked) { recordArr[(curPage - 1) * lINENUMBER + _id].selfCheckIndex = _id; downList.push(recordArr[(curPage - 1) * lINENUMBER + _id]); } }); downItemIndex = 0; onStartNVRDownload(downList[0]); // if(WebCaps != null) { // // let supportDownloadEncrypt = await RPC.MagicBox.getProductDefinition('SupportDownloadEncrypt').then(json => { // // return !!json.SupportDownloadEncrypt; // // }).catch(err => { // // return false; // // }); // const downFile = (name, href) => { // let a = document.createElement('a'); // a.href = href; // a.download = ''; // document.body.appendChild(a); // a.click(); // setTimeout(() => { // document.body.removeChild(a); // }, 1000); // }; // const loop = list => { // if (list === undefined) { // return; // } // // let tmpUrl = supportDownloadEncrypt ? '/RPC_Encrypt_Loadfile' : '/RPC_Loadfile'; // let tmpUrl = '/RPC_Loadfile'; // // let hrefs = window.location.origin + tmpUrl + list.FilePath; // let hrefs = 'http://' + $ip.value + tmpUrl + list.FilePath; // setTimeout( function () { // downFile('', hrefs); // loop(downList.shift()); // }, 1000); // }; // loop(downList.shift()); // } else { // onStartNVRDownload( downList[downItemIndex] ); // } } /** * @description 更新录像列表当前页 */ const updateTable = () => { playerInstance.forEach(item => { if (item) { item.stop(); item.close(); item = null; } }); $('#h5_checkAll').checked = false; $('#h5_curPage').innerText = curPage; let table = document.querySelector('#h5_table tbody'); table.innerHTML = ''; let index = (curPage - 1) * lINENUMBER; let infos = recordArr.slice(index, index + lINENUMBER); for (let i = 0; i < infos.length; i++) { let time = infos[i].StartTime + '-' + infos[i].EndTime; let size = Math.round(infos[i].Length / 1024) + '(KB)'; let newRow = table.insertRow(-1); newRow.innerHTML = `${index + i + 1}${time}${size}--/--`; } document.querySelectorAll('[id^=h5_button_go_]').forEach(function (item) { item.addEventListener('click', function (event) { let id = item.getAttribute('id').split('_')[3] - 0; onGoTime(id); }); }); document.querySelectorAll('[id^=h5_check_]').forEach(function (item) { item.addEventListener('click', function (event) { event.stopPropagation(); if (event.target.checked) { //渲染裁剪时间 let _index = event.target.getAttribute('id').split('_')[2] - 0; let startTime = recordArr[_index + lINENUMBER * (curPage - 1)].StartTime.split(' ').join('T'); let endTime = recordArr[_index + lINENUMBER * (curPage - 1)].EndTime.split(' ').join('T'); if (startTime.split(':')[2] === '00') { startTime = startTime.substr(0, startTime.length - 3); } if (endTime.split(':')[2] === '00') { endTime = endTime.substr(0, endTime.length - 3); } /* let _index = event.target.getAttribute('id').split('_')[2] - 0; let startTime = recordArr[_index].StartTime; let endTime = recordArr[_index].EndTime; */ $('#h5_cutStartTime').value = startTime; $('#h5_cutEndTime').value = endTime; document.querySelector('[btn-for=onStartCut]').setAttribute('cutIndex', _index); } }); }); document.querySelectorAll('#h5_table tbody tr').forEach(function (item) { item.addEventListener('dblclick', function (event) { event.stopPropagation(); let dom = event.target.parentNode.childNodes[1]; if (event.target.nodeName === 'TD') { event.target.style.color = 'blue'; let value = dom.innerText - 1; let url = recordArr[value].FilePath; onPreview(true, url, value); } }); }); } /** * @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; console.log(curTime, 'xxxxx'); if (playerInstance[WndIndex]) { playerInstance[WndIndex].playByTime(curTime); } } const goTime = (time) => { console.log(time); if (playerInstance[WndIndex]) { playerInstance[WndIndex].playByTime(time); } } /** * @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 + "()"); } } /** * @description 设置登录状态 * @param {boolean} bool 设备是否已经登录 */ function setLoginState(bool) { isLogin = bool; } /** * @description 转换数据坐标 * @param {*} x1 左上角x坐标 * @param {*} y1 左上角y坐标 * @param {*} x2 右下角x坐标 * @param {*} y2 右下角y坐标 * @param {*} width 宫格宽 * @param {*} height 宫格高 */ function zoomArea(x1, y1, x2, y2, width, height) { // 小框区域的数据 let rectArea = { width: x2 - x1, height: y2 - y1, centerX: (x1 + x2) / 2, // 圆心坐标 centerY: (y1 + y2) / 2 }; // 放大比例,控件放大倍数上限是20 let scale = Math.min(width / rectArea.width, height / rectArea.height, 20); // 原始窗口信息 let sourceWin = { width: width, height: height, centerX: width / 2, centerY: height / 2 }; // 放大后的窗口区域 let bigWinArea = { width: width * scale, height: height * scale, left: sourceWin.centerX - rectArea.centerX * scale, top: sourceWin.centerY - rectArea.centerY * scale }; // 数据矫正 if (bigWinArea.left > 0) { bigWinArea.left = 0; } if (bigWinArea.left < sourceWin.width - bigWinArea.width) { bigWinArea.left = sourceWin.width - bigWinArea.width; } if (bigWinArea.top > 0) { bigWinArea.top = 0; } if (bigWinArea.top < sourceWin.height - bigWinArea.height) { bigWinArea.top = sourceWin.height - bigWinArea.height; } return bigWinArea; } /** * @description 获取全屏状态 */ function getFull() { return window.top.document.mozFullScreen || window.top.document.webkitIsFullScreen || window.top.document.msFullscreenElement; } /** * @description 全屏状态改变的回调事件 */ function fullscreenchange() { if (getFull()) { return; } else { exitfullScreen(); } } /** * @description 设置全屏 */ function setfullScreen() { let docElm = window.top.document.documentElement; if (docElm.requestFullScreen) { docElm.requestFullScreen(); } else if (docElm.mozRequestFullScreen) { docElm.mozRequestFullScreen(); } else if (docElm.webkitRequestFullScreen) { docElm.webkitRequestFullScreen(); } else if (docElm.msRequestFullscreen) { docElm.msRequestFullscreen(); } handleFullscreen(true); } /** * @description 退出全屏 */ function exitfullScreen() { let docElm = window.top.document.documentElement; if (docElm.exitFullscreen) { docElm.exitFullscreen(); } else if (docElm.mozCancelFullScreen) { docElm.mozCancelFullScreen(); } else if (docElm.webkitCancelFullScreen) { docElm.webkitCancelFullScreen(); } else if (docElm.msExitFullscreen) { docElm.msExitFullscreen(); } handleFullscreen(false); } /** * @description 处理全屏开关时的窗口大小 * @param {boolean} bool 是否要全屏 */ function handleFullscreen(bool) { if (bool) { let wrap = { position: 'absolute', left: 0, top: 0, width: window.screen.width + 'px', height: window.screen.height + 'px', overflow: 'visible' } setStyle($video_wrap, wrap); } else { let wrap = { position: 'relative', overflow: 'hidden', // width: '500px', // height: '300px', } setStyle($video_wrap, wrap); } } /** * @description ptz云台事件 * @param {string} type 云台事件类型 * @param {boolean} isStop 是否停止相应事件 */ window.onHandlePTZ = function (type, isStop) { let stepVal = $('#h5_ptz_step').value - 0; let arg2 = 0; let arg2Arr = ['LeftUp', 'RightUp', 'LeftDown', 'RightDown']; let presetArr = ['GotoPreset', 'SetPreset', 'ClearPreset']; let presetNum = $('#h5_preset').value - 0; if (arg2Arr.indexOf(type) > -1) { arg2 = stepVal; } if (!isStop) { if (presetArr.indexOf(type) > -1) { /** * RPC.PTZManager 云台相关 * @param {string} 方法 * @param {number} channel 通道 * @param {object} 参数集合 */ RPC.PTZManager('start', channel, { 'code': type, 'arg1': presetNum, 'arg2': 0, 'arg3': 0 }); } else { RPC.PTZManager('start', channel, { 'code': type, 'arg1': stepVal, 'arg2': arg2, 'arg3': 0 }); } } else { RPC.PTZManager('stop', channel, { 'code': type, 'arg1': stepVal, 'arg2': arg2, 'arg3': 0 }); } } //进入页面自动初始化 init();