| | |
| | | getWarnGroupCount, |
| | | getWarnGroupCountTop10, |
| | | getRealVideo, |
| | | playDetection, |
| | | closeRealVideo, |
| | | } from "./service"; |
| | | export default { |
| | | data() { |
| | | return { |
| | | flvPlayer: null, |
| | | videoTimer: null, |
| | | activeIndex: "1", |
| | | activeIndex2: "1", |
| | | timer: null, |
| | |
| | | carCountData: [], //车辆统计数据 |
| | | carStatusData: {}, //车辆状态数据 |
| | | warnList: [], //预警列表数据 |
| | | |
| | | serverIp: "",//监控ip |
| | | serverPort: "",//监控端口 |
| | | carId: "",//监控车辆 |
| | | }; |
| | | }, |
| | | watch: { |
| | |
| | | } |
| | | }, |
| | | }, |
| | | filters: { |
| | | |
| | | }, |
| | | filters: {}, |
| | | |
| | | created() { |
| | | window.toCarDetail = (record) => { |
| | |
| | | if (this.timer) { |
| | | clearInterval(this.timer); |
| | | } |
| | | this.destroyPlayer(); |
| | | if (this.markers && this.markers.length > 0) { |
| | | this.markers.forEach((marker) => { |
| | | marker.setMap(null); |
| | |
| | | autoMove: true, |
| | | anchor: "top-center", |
| | | }); |
| | | // 添加信息弹窗关闭事件监听 |
| | | this.infoWindow.on('close', () => { |
| | | console.log('关闭信息弹窗1111111111111111111') |
| | | this.destroyPlayer(); |
| | | }); |
| | | this.getMapCarData(); |
| | | }) |
| | | .catch((e) => { |
| | |
| | | new Promise((resolve) => { |
| | | geocoder.getAddress(location, (status, result) => { |
| | | if (status === "complete" && result.regeocode) { |
| | | console.log("result", result,'status',status); |
| | | resolve(result.regeocode.formattedAddress); |
| | | } else { |
| | | resolve("未知地址"); |
| | |
| | | this.infoWindow.setContent( |
| | | this.listRender({ |
| | | ...item, |
| | | drivingTime:this.formatterTime(item.drivingTime || 0) , |
| | | drivingTime: this.formatterTime(item.drivingTime || 0), |
| | | location: addressResult, |
| | | videoUrl: videoRes.url, |
| | | }) |
| | | ); |
| | | |
| | | this.initVideoPlayer(videoRes.url); |
| | | this.initVideoPlayer(); |
| | | } catch (error) { |
| | | this.infoWindow.setContent( |
| | | '<div style="padding: 20px;text-align: center;color: red;">获取车辆信息失败</div>' |
| | |
| | | try { |
| | | const res = await getRealVideo({ id: carId }); |
| | | // 将RTSP流转换为FLV流 |
| | | const flvUrl = this.convertRtspToFlv(res.url); |
| | | return { |
| | | url: flvUrl |
| | | }; |
| | | this.serverIp = res.serverIp; |
| | | this.serverPort = res.serverPort; |
| | | this.carId = carId; |
| | | } catch (error) { |
| | | console.error("获取视频地址失败", error); |
| | | return { |
| | | url: "" |
| | | }; |
| | | return {}; |
| | | } |
| | | }, |
| | | |
| | | // RTSP转FLV |
| | | convertRtspToFlv(rtspUrl) { |
| | | // 这里需要根据实际的流媒体服务器地址进行修改 |
| | | // 假设流媒体服务器地址为 http://your-media-server:8080 |
| | | const mediaServer = "http://101.206.211.65:18042"; |
| | | // 从RTSP URL中提取流标识 |
| | | const streamId = rtspUrl.split("/").pop(); |
| | | // 返回FLV流地址 |
| | | return `${mediaServer}/live/${streamId}.flv`; |
| | | }, |
| | | |
| | | // 初始化视频播放器 |
| | |
| | | // 检查flv.js是否支持 |
| | | if (flvjs.isSupported()) { |
| | | try { |
| | | this.flvPlayer = flvjs.createPlayer({ |
| | | type: "flv", |
| | | isLive: true, |
| | | cors: true, |
| | | hasAudio: true, |
| | | hasVideo: true, |
| | | url: videoUrl, |
| | | enableWorker: true, |
| | | enableStashBuffer: false, |
| | | seekType: "range", |
| | | }); |
| | | |
| | | this.flvPlayer.attachMediaElement(video); |
| | | this.flvPlayer.load(); |
| | | this.flvPlayer.play().catch(error => { |
| | | console.error("视频播放失败:", error); |
| | | playDetection(this.carId).then((res) => { |
| | | this.flvPlayer = flvjs.createPlayer({ |
| | | type: "flv", //视频类型 |
| | | isLive: true, //是否为直播 |
| | | cors: true, //是否开启跨域 |
| | | hasAudio: false, //是否开启音频 |
| | | hasVideo: true, //是否开启视频 |
| | | url: `http://${this.serverIp}:${this.serverPort}/live?port=1935&app=flv&stream=${this.carId}`, // 后端拿到的视频路径 |
| | | enableWorker: true, //启用 Web Worker 进程来加速视频的解码和处理过程 |
| | | enableStashBuffer: false, // 启用数据缓存机制,提高视频的流畅度和稳定性。 |
| | | stashInitialSize: 1024, // 初始缓存大小。单位:字节。建议针对直播:调整为1024kb |
| | | stashInitialTime: 0.2, // 缓存初始时间。单位:秒。建议针对直播:调整为200毫秒 |
| | | seekType: "range", // 建议将其设置为“range”模式,以便更快地加载视频数据,提高视频的实时性。 |
| | | lazyLoad: false, //关闭懒加载模式,从而提高视频的实时性。建议针对直播:调整为false |
| | | lazyLoadMaxDuration: 0.2, // 懒加载的最大时长。单位:秒。建议针对直播:调整为200毫秒 |
| | | deferLoadAfterSourceOpen: false, // 不预先加载视频数据,在 MSE(Media Source Extensions)打开后立即加载数据,提高视频的实时性。建议针对直播:调整为false |
| | | }); |
| | | let video = document.getElementById("monitoringCard"); |
| | | this.flvPlayer.attachMediaElement(video); // video容器 |
| | | this.flvPlayer.load(); |
| | | this.flvPlayer |
| | | .play() |
| | | .then((res) => { |
| | | this.videoTimer = setInterval(() => { |
| | | playDetection(this.carId); |
| | | }, 5000); |
| | | }) |
| | | .catch((err) => { |
| | | this.destroyPlayer(); |
| | | }); |
| | | // 错误监听 |
| | | this.flvPlayer.on("error", (err) => { |
| | | this.destroyPlayer(); |
| | | }); |
| | | }); |
| | | } catch (error) { |
| | | console.error("创建播放器失败:", error); |
| | |
| | | console.error("当前浏览器不支持flv.js"); |
| | | } |
| | | }, |
| | | |
| | | destroyPlayer() { |
| | | // 销毁播放器释放资源 |
| | | if (this.flvPlayer) { |
| | | if (this.videoTimer) clearInterval(this.videoTimer) |
| | | closeRealVideo(this.carId).then(res => { |
| | | this.flvPlayer.pause(); |
| | | this.flvPlayer.unload(); |
| | | this.flvPlayer.detachMediaElement(); |
| | | this.flvPlayer.destroy(); |
| | | this.flvPlayer = null; |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | // 处理视频错误 |
| | | handleVideoError(event) { |
| | |
| | | return `<div style="background: #ffffff; padding: 24px 20px;z-index: 999"> |
| | | <div style="position: relative; width: 460px; height: 330px"> |
| | | <video |
| | | crossorigin="anonymous" |
| | | style="width: 460px; height: 330px; border-radius: 9px" |
| | | id="monitoringCard" |
| | | autoplay |
| | | playsinline |
| | | preload="auto" |
| | | @error="handleVideoError" |
| | | width="620"> |
| | |
| | | }</div> |
| | | </div> |
| | | <div style="display: flex; justify-content: space-between"> |
| | | <div style="font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;width: 200px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title="${record.location}">位置:${ |
| | | <div style="font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;width: 200px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" title="${ |
| | | record.location |
| | | }</div> |
| | | }">位置:${record.location}</div> |
| | | <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">经纬度:${ |
| | | record.longitude + "," + record.latitude |
| | | }</div> |