ebc

index.vue 4.5KB

    <template> <div class="replayer"> <div class="replayer-video"> <t-loading v-model="loadVideo"> <span class="text-md text-info">获取视频资源...</span> </t-loading> <video-player :sources="videoList" :autoadvance="0" :style="{opacity: loadVideo ? 0: 1}" @player-inited="handlePlayerInited" @playlistitem="handlePlayerCurrentChange" /> </div> </div> </template> <script> import VideoPlayer from '@/components/VideoPlayer' export default { components: { VideoPlayer }, props: { list: { type: Array, default: () => [] }, visibled: { type: Boolean, default: false } }, data () { return { currentTab: null, loadVideo: false, videoList: [], $player: null } }, computed: { visible: { get () { return this.visibled }, set (val) { if (!val) this.$player.pause() this.$emit('update:visibled', val) } } }, watch: { list: { handler (val) { console.warn(`list Change`) this.resetVideoList() if (val.length > 0) { this.currentTab = val[0].fileId // 手动触发第一个tab点击事件 this.handleTabChange(null, 0) } }, immediate: true } }, methods: { // 初始化 handlePlayerInited (player) { this.$player = player window.player = this let distinguishBtn = player.controlBar.addChild('button') distinguishBtn.addClass('aidicon') distinguishBtn.addClass('aidicon-image-outline') distinguishBtn.setAttribute('title', '识别记录') distinguishBtn.size = '20' distinguishBtn.on('click', () => { this.$emit('goDistinguishRecord') }) let repalyBtn = player.controlBar.addChild('button') repalyBtn.addClass('aidicon') repalyBtn.addClass('aidicon-piechart-outline') repalyBtn.setAttribute('title', '视频回放') repalyBtn.on('click', () => { this.$emit('videoReplay', this.list[0].id) }) }, async handleTabChange (name, index) { this.$player.pause() await this.preloadOriVideoUrl(index) this.play(index) }, handlePlayerCurrentChange (e, item) { const { index, fileId } = item this.currentTab = fileId this.preloadOriVideoUrl(index) }, resetVideoList () { const videoList = this.list.map((item, index) => { const { fileId, fileType } = item return { index, fileId, fileType, loaded: false } }) this.videoList = videoList }, play (index) { console.log(`播放:index=${index}`) // 调用额外的currentItem方法以避免currentItem在首次不生效 // https://github.com/brightcove/videojs-playlist/blob/master/docs/api.md this.$player.playlist.currentItem() this.$player.playlist.currentItem(index) this.$player.play() }, /** * 从index开始预载videoList的视频地址 * 此方法将在获取index对应的地址后就立即返回 */ preloadOriVideoUrl (index = 0, maxLength = 5) { return new Promise((resolve, reject) => { for (let i = index; i in this.videoList && i - index < maxLength; i++) { console.log(`预载地址:index=${i}`) const item = this.videoList[i] const task = item.loaded ? Promise.resolve() : this.getOriVideoUrl(item.fileId).then(resp => { console.log(`预载完成,更新播放源:index=${i}`) item.loaded = true item.sources = [{ src: resp.url, type: item.fileType }] }) if (i === index) { this.loadVideo = !item.loaded task.then(() => { resolve() }).finally(() => { this.loadVideo = false }) } } }) }, /* * 获取真实视频地址 */ getOriVideoUrl (fileId) { console.log(`请求地址:${fileId}`) // fake return new Promise((resolve, reject) => { setTimeout(() => { const url = fileId || 'rtmp://10.19.90.34:2935/live?token=039b6232ce6548210722a4c0de19c62e/1' resolve({ url }) }, 1000) }) } } } </script> <style lang="scss"> .replayer { display: flex; &-list { margin-right: 20px; // width: 200px; } &-video { position: relative; flex: auto; } } </style>