import PlayerItem from './PlayerItem.js' import {Spinner} from './spin.js' import CONSTANT from './CONSTANT.js' const PlayerControl = window.PlayerControl; /* ---------------- RecordPlayerItem ---------------- */ class RecordPlayerItem extends PlayerItem { /** * @param {*} opt.wrapperDomId 父级id * @param {*} opt.index 索引 */ constructor(opt) { super(opt) this.canvasId = `${this.domId}-recordcanvas` this.videoId = `${this.domId}-recordVideo` this.curTimestamp = 0 this.initDom() this.defaultStatus = $('.default-status', this.$el) this.error = $('.error', this.$el) this.controller = $('.player-control', this.$el) this.progressBar = $('.record-control-bar', this.$el) this.timeInfo = $('.time-info', this.$el) this.initMouseEvent() /** * this.state 当前Player状态 * created, ready, playing, pause, stop, closed, error */ this.setStatus('created') } /** * 播放器模板 */ getTemplate() { let template = `
/
` return template } /** * 事件监听 */ initMouseEvent() { super.initMouseEvent() this.hideTimer = null this.$el.on('mouseenter mousemove', (evt) => { if (this.status === 'playing') { this.hideTimer && clearTimeout(this.hideTimer) this.setDomVisible($('.player-control', $(`#${this.domId}`)), true) } else if (this.status === 'ready') { this.setDomVisible(this.progressBar, true) } }) this.$el.on('mouseleave', (evt) => { if (this.status === 'pause') { return } this.hideTimer = setTimeout(() => { this.setDomVisible($('.player-control', $(`#${this.domId}`)), false) }, 300) }) $('.wsplayer-progress-bar', this.$el).on('mousemove', (evt) => { $('.progress-bar_hover_light', this.$el).css({ width: evt.offsetX + 'px' }) }) $('.wsplayer-progress-bar', this.$el).on('mouseleave', (evt) => { $('.progress-bar_hover_light', this.$el).css({ width: 0 }) }) $('.play-ctrl-btn', this.$el).click((evt) => { if (this.status === 'playing') { // 正在播放,暂停播放 this.pause() $('.play-icon', this.$el).removeClass('play').addClass('pause') } else { // 暂停播放状态,打开 this.play() $('.play-icon', this.$el).removeClass('pause').addClass('play') } }) } /** * 设置状态,同时控制组件显示 * created, ready, playing, pause, stop, closed, error */ setStatus(status, msg) { this.status = status switch (this.status) { case 'created': case 'closed': this.setDomVisible(this.defaultStatus, true) this.setDomVisible(this.error, false) this.setDomVisible(this.controller, false) $('.audio-icon', this.$el).removeClass('on').addClass('off') break; case 'ready': this.setDomVisible(this.defaultStatus, false) this.setDomVisible(this.error, false) break; case 'playing': this.setDomVisible(this.defaultStatus, false) this.setDomVisible(this.error, false) this.setDomVisible($('.play-pause-wrapper', this.$el), false) break; case 'pause': this.setDomVisible(this.defaultStatus, false) this.setDomVisible(this.error, false) this.setDomVisible(this.controller, false) this.setDomVisible($('.play-pause-wrapper', this.$el), true) break; case 'error': this.setDomVisible(this.defaultStatus, false) $('.error-message', this.$el).text(CONSTANT.errorInfo[msg.errorCode] ? CONSTANT.errorInfo[msg.errorCode] : CONSTANT.errorInfo['defaultErrorMsg']) this.setDomVisible(this.error, true) break; default: break; } } /** * 播放录像 * @param {String} options.decodeMode 可选参数 video | canvas * @param {String} options.wsURL 可选参数 * @param {Function} options.recordSource 2=设备,3=中心 * recordSource == 2 设备录像,按照时间方式播放 * @param {String} options.rtspURL String * @param {Number | String} options.startTime 开始时间 时间戳或者'2021-09-18 15:40:00'格式的时间字符串 * @param {Number | String} options.endTime 结束时间 时间戳或者'2021-09-18 15:40:00'格式的时间字符串 * @param {Function} options.reload 重新拉流的回调函数,用于时间回放,返回promise * reload(newStarTime, endTime).then(newRtspUrl => { play continue}) * recordSource == 3 中心录像,按照文件方式播放 * @param {Function} options.RecordFiles 文件列表 * @param {Function} options.getRtsp 文件列表 * getRtsp(file).then(newRtspUrl => { play continue}) */ init(options) { if (this.player) { this.player.close() } if (this.spinner) { this.spinner.stop() } this.spinner = new Spinner({ color: '#ffffff' }).spin(this.$el[0]) let self = this this.player = new PlayerControl(Object.assign({ wsURL: this.wsPlayer.wsURL }, options)) this.options = options this.timeLong = options.endTime - options.startTime let seconds = this.timeLong % 60 let minutes = (parseInt(this.timeLong / 60)) % 60 let hours = (parseInt(this.timeLong / 3600)) % 60 this.timeLongStr = `${hours > 0 ? hours + ':' : ''}${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}` $('.time-long', this.$el).text(this.timeLongStr) this.setStatus('ready') this.player.on('ResolutionChanged', function (e) { console.log(e) }); this.player.on('PlayStart', function (e) { console.log(e) self.setStatus('playing') }); this.player.on('DecodeStart', function (e) { console.log('DecodeStart', e) self.spinner.stop() if (e.decodeMode === 'video') { self.videoElem.style.display = ''; self.canvasElem.style.display = 'none'; } else { self.videoElem.style.display = 'none'; self.canvasElem.style.display = ''; } $('.stream-info', $(`#${self.domId}`)).text(`${e.encodeMode}, ${e.width}*${e.height}`) }); this.player.on('UpdateCanvas', function (e) { if (self.firstTime === 0) { // 使用请求时间段的时间作为 self.firstTime = self.options.startTime // self.firstTime = e.timestamp;//获取录像文件的第一帧的时间戳 } // 一秒数据帧timestamp相同,此判断可以减少计算 if (e.timestamp > self.curTimestamp) { self.curTimestamp = e.timestamp let playtime = e.timestamp - self.firstTime playtime = playtime < 0 ? 0 : playtime; let seconds = playtime % 60 let minutes = (parseInt(playtime / 60)) % 60 let hours = (parseInt(playtime / 3600)) % 60 let timeString = `${hours > 0 ? hours + ':' : ''}${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + seconds : seconds}` self.timeInfo.text(timeString) $('.progress-bar_light', self.$el).css({ width: `${playtime * 100 / self.timeLong}%` }) // ctrlBar.updateCanvas(e) // console.log('UpdateCanvas: ' + JSON.stringify(e)) } }); this.player.on('GetFrameRate', function (e) { console.log('GetFrameRate: ', e) }); this.player.on('FrameTypeChange', function (e) { console.log('编码模式改变 FrameTypeChange: ', e) }); this.player.on('Error', function (e) { self.spinner.stop() console.log('Error: ' + JSON.stringify(e)) self.setStatus('error', e) }); this.player.on('MSEResolutionChanged', function (e) { console.log('分辨率改变 MSEResolutionChanged: ', e) }); this.player.on('audioChange', function (e) { console.log('音频编码改变 audioChange: ', e) }); this.player.on('IvsDraw', function (e) { console.log('IvsDraw: ', e) }); this.player.on('WorkerReady', function () { console.log('WorkerReady') self.player.connect(); }) this.player.on('FileOver', function (e) { console.log('回放播放完成 FileOver: ', e) }); this.player.on('Waiting', function (e) { console.log('Waiting: ', e) }); this.player.on('UpdateTime', function (e) { console.log('UpdateTime: ', e) }); this.player.on('GetFirstFrame', function(){ console.log('收到第一帧'); }); this.player.init(this.canvasElem, this.videoElem); } /** * 倍速播放 * @param {Number} speed 倍速 */ playSpeed(speed) { this.player.playSpeed(speed) } /** * 时间跳转 * @param {*} time */ playByTime(time) { this.player.playByTime(time) } } export default RecordPlayerItem