,其中的视频文件路径 可以使用湖南卫视在线播放地址,如果能正常播放时可自行换成自己的播放地址 海康视频时时在线预览
npm i videojs videojs-contrib-hls在main.js文件中引入并挂载原型上
import VideoJs from 'video.js' import 'video.js/dist/video-js.min.css' import 'videojs-contrib-hls' // 如果播放 rtmp文件不用引入 Vue.prototype.$video = VideoJs湖南卫视接口可用于测试
rtmp://58.200.131.2:1935/livetv/hunantv
<template> <j-modal :title="title" :width="width" :visible="visible" :fullscreen="false" switchFullscreen :maskClosable="false" :confirmLoading="confirmLoading" @cancel="handleCancel" :footer="null" > <a-spin :spinning="confirmLoading"> <a-alert message="设备有 11 个警告尚未处理" type="warning" show-icon closable /> <div class="monitorin-info"> <div class="monitorin"> <!-- x-vlc-plugin application/x-mpegURL rtmp/flv--> <video id="myVideoInfo" class="video-js vjs-default-skin" autoplay="autoplay" controls preload="auto" > <source :src="videoSrc" type="application/x-mpegURL" /> </video> <div class="control"> <div class="fl cap-voice-btns"> <a-button type="primary" @click="captureReport">抓拍上传</a-button> <a-button type="primary" @mouseup="voiceIntercom('up')" @mousedown="voiceIntercom('down')" >语音对讲</a-button> </div> <div class="direction"> <div class="top"> <a-icon type="caret-up" @mouseup="controlDirection(1,'UP')" @mousedown="controlDirection(0,'UP')" title="上移" /> </div> <div class="center"> <a-icon type="caret-left" @mouseup="controlDirection(1,'LEFT')" @mousedown="controlDirection(0,'LEFT')" title="左移" /> <span @click="controlDirection(0,'GOTO_PRESET')" title="复位"> <a-icon type="poweroff" /> </span> <a-icon type="caret-right" @mouseup="controlDirection(1,'RIGHT')" @mousedown="controlDirection(0,'RIGHT')" title="右移" /> </div> <div class="bottom"> <a-icon type="caret-down" @mouseup="controlDirection(1,'DOWN')" @mousedown="controlDirection(0,'DOWN')" title="下移" /> </div> </div> <!-- 焦距调节 --> <div class="fl"> <a-button shape="circle" icon="minus" @mouseup="controlDirection(1,'ZOOM_OUT')" @mousedown="controlDirection(0,'ZOOM_OUT')" /> <a-button shape="circle" icon="plus" @mouseup="controlDirection(1,'OOM_IN')" @mousedown="controlDirection(0,'OOM_IN')" /> </div> </div> </div> </div> <VoiceIntercom :urls="voiceIntercomUrl" /> </a-spin> </j-modal> </template> <script> import { postAction, getAction, httpAction } from '@/api/manage.js' import { validateDuplicateValue } from '@/utils/util' import Monitoring from './model/Monitoring' import CaptureReport from './CaptureReport' import VoiceIntercom from './VoiceIntercom' export default { name: 'WorksiteMonitoringInfo', components: { Monitoring, CaptureReport, VoiceIntercom }, inject: ['reload'], props: { passData: { type: String, default: '' } }, data() { return { voiceIntercomUrl: '', // 语音对讲流连接地址 flag: true, // 節流开关 title: '', width: 800, visible: false, confirmLoading: false, videoSrc: '', // 视频地址 player: null, // videoJs 实例对象 cameraIndexCode: '', dataSource: [], ws: null, ipagination: { current: 1, pageSize: 10, pageSizeOptions: ['10', '20', '30'], showTotal: (total, range) => { return range[0] + '-' + range[1] + ' 共' + total + '条' }, showQuickJumper: true, showSizeChanger: true, total: 0 }, loading: false, url: { previewurls: '/safety/admin/cameramanager/previewurls', // 流连接 manualcapture: '/safety/admin/cameramanager/manualcapture', // 摄像头-抓图 talkurls: '/safety/admin/cameramanager/talkurls', // 摄像头-获取对话流连接 controlling: '/safety/admin/cameramanager/controlling' // 摄像头-云台控制 } } }, watch: { visible(newVal, oldVal) { // 销毁video实例,阻止关闭标签之后继续请求 if (!newVal) { this.player && this.player.pause() this.player = null this.reload() this.player && this.player.dispose() this.player && this.player.tech_.dispose() } else { this.getVideo(this.cameraIndexCode) } } }, methods: { // 开启弹窗 openModal(title, id) { this.visible = true this.title = title this.cameraIndexCode = 'c56495c3f368494a8eff6052028e61ea' // id'e8695d5733064450a2c0e3704e5bcdd0' // 'c56495c3f368494a8eff6052028e61ea' // id }, // 获取视频流、 getVideo() { let parmas = {} let data = this.$qs.stringify({ cameraIndexCode: this.cameraIndexCode, protocol: 'hls', // hls expand: 'transcode=0', streamTyp: 1, // 0 transmode: 1 // streamform: 'ps' }) postAction(this.url.previewurls, data) .then(({ message }) => { console.log('-----文件详情res----', message) this.videoSrc = message // this.videoSrc = 'rtmp://58.200.131.2:1935/livetv/hunantv' }) .then(() => { let that = this this.$nextTick(() => { that.getPlayVideo() }) }) }, getPlayVideo() { let _this = this _this.player = _this.$video(document.getElementById('myVideoInfo'), { controls: true, autoplay: true, preload: 'auto', controlBar: { playToggle: true } }) }, // 方向控制 () async controlDirection(action, command = '') { let parmas = { action, // 0 操作动作(1 开始 0 停止) cameraIndexCode: this.cameraIndexCode, // command, // 操作动作(LEFT 左转 RIGHT 右转 UP 上转 DOWN 下转 FOCUS_NEAR 焦点前移 FOCUS_FAR 焦点后移 ) presetIndex: 20, speed: 1 } let timer = null if (true) { this.flag = false timer = setTimeout(() => { this.flag = true clearTimeout(timer) }, 2000) let { success } = await postAction(this.url.controlling, parmas) if (!success) this.$message.error('该设备不支持') else { if (!action) { this.$message.success('操作成功,请稍候') } } } }, // 打开抓拍上传弹窗 async captureReport() { let data = this.$qs.stringify({ cameraIndexCode: this.cameraIndexCode }) let { success, message } = await postAction(this.url.manualcapture, data) if (success) { let data = { passData: this.passData, cameraIndexCode: this.cameraIndexCode, url: message // cameraName:this.cameraName, // 摄像机名称 // project:this.projectTree // 工程树 警告位置 } await this.$refs.CaptureReport.showModal(data) } }, // 语音对讲 async voiceIntercom(eventType) { let parmas = { cameraIndexCode: this.cameraIndexCode, expand: 'streamform=ps', transmode: 1, eurlExpand: '' } let { success, message } = await postAction(this.url.talkurls, parmas) if (!success) { this.$message.error('操作失败,请稍后重试') return false } this.voiceIntercomUrl = message console.log(message) console.log('戍邊不能', eventType) // down up return false this.ws = new WebSocket(message) console.log(this.ws) this.ws.onopen = function(evt) { console.log('Connection open ...', evt) this.ws.send('Hello WebSockets!') } }, handleCancel() { this.visible = false }, // 查看 infoView(name, id) {} } } </script> <style lang="less" scoped> @import '~@assets/less/common.less'; .fl { display: flex; justify-content: space-between; margin-top: 15px; } .info { display: flex; flex-wrap: wrap; margin: 15px 0; p { width: 45%; } } .monitorin-info { margin-bottom: 30px; .monitorin { width: 100%; position: relative; #myVideoInfo { width: 100%; min-height: 550px; margin-top: 25px; } .control { position: absolute; z-index: 2; bottom: 85px; right: 20px; width: 300px; text-align: center; padding: 15px 30px 0 30px; /* 抓拍上传,语音对讲按钮 */ .cap-voice-btns { display: flex; justify-content: space-between; margin-bottom: 200px; } /* 方向按钮 */ .direction { text-align: center; i { font-size: 35px; cursor: pointer; color: #fff; } .top { font-weight: bold; cursor: pointer; } .center { span { display: inline-block; width: 100px; height: 80px; border-radius: 50%; text-align: center; line-height: 80px; font-size: 25px; cursor: pointer; } } .bottom { cursor: pointer; } } } } } .near { margin-top: 30px; font-weight: bold; } </style>