Compare commits

..

2 Commits

Author SHA1 Message Date
lxj
d9b096c8ed Merge branch 'master' of http://47.109.37.87:3000/by2025/admin-vben5
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
2025-08-12 15:49:31 +08:00
lxj
8cf6df683d 页面修改 2025-08-12 15:47:15 +08:00
5 changed files with 158 additions and 26 deletions

View File

@ -19,3 +19,14 @@ export function addFFmpegStreamProxy(params?: any) {
params, params,
); );
} }
export function addMediaStreamProxy(params?: any) {
return requestClient.post<AddStreamProxyResult>('sis/stream/proxy', params);
}
export function addFFmpegMediaStreamProxy(params?: any) {
return requestClient.post<AddStreamProxyResult>(
'sis/stream/ffmpeg/proxy',
params,
);
}

View File

@ -8,13 +8,42 @@ import './map.scss';
import { icons, MapDefaultData } from './constants.js'; import { icons, MapDefaultData } from './constants.js';
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import { deviceManageList } from '#/api/sis/deviceManage/index.js'; import { deviceManageList } from '#/api/sis/deviceManage/index.js';
import { deviceChannelList } from '#/api/sis/deviceChannel/index.js';
import mpegts from 'mpegts.js';
import { message } from 'ant-design-vue';
import {
addFFmpegMediaStreamProxy,
addMediaStreamProxy,
} from '#/api/sis/stream/index.js';
import { checkHEVCSupport } from '#/utils/video.js';
// //
let map = null; let map = null;
let currentPlayer;
let videoElement;
let isSupportH265 = false;
onMounted(() => { onMounted(() => {
// h265
isSupportH265 = checkHEVCSupport();
mapFn.intiMap(); mapFn.intiMap();
// //
loadCameraData();
//
setInterval(catchUp, 10000);
});
function catchUp() {
if (currentPlayer) {
const end = currentPlayer.buffered.end(player.buffered.length - 1);
const diff = end - videoElement.currentTime;
if (diff > 2) {
// 2
videoElement.currentTime = end - 0.5; //
}
}
}
function loadCameraData() {
deviceManageList({ deviceType: 1 }).then(({ rows = [], total = 0 }) => { deviceManageList({ deviceType: 1 }).then(({ rows = [], total = 0 }) => {
if (total > 0) { if (total > 0) {
// //
@ -29,39 +58,111 @@ onMounted(() => {
mapFn.renderOverLayersData(items, function (marker, data) { mapFn.renderOverLayersData(items, function (marker, data) {
// //
marker.addEventListener('click', () => { marker.addEventListener('click', () => {
console.log(data);
// //
const params = {
// deviceIp: data.deviceIp,
const html = [ pageNum: 1,
'<div class="video-wrap" style="width: 530px;height: 350px;padding-top:50px">', pageSize: 10,
`<div class="wrap-title" style="margin-top: -35px;">${data.deviceName}</div>`, };
`<div class="close" onclick="pageEvent.closeInfoWindow()">X</div>`, deviceChannelList({ deviceIp: data.deviceIp }).then(
`<div class="wrap-content">`, ({ total, rows }) => {
`<div onclick="pageEvent.playClick()" class="content-left" style="height: 270px">`, console.log(data);
'<video id="video-player" ref="player1" muted autoplay></video>', const deviceData = { ...data };
`</div>`, if (total > 0) {
`</div>`, //
`</div>`, const deviceName = deviceData.deviceName;
]; const html = [
const infoWindow = new BMap.InfoWindow(html.join(''), { '<div class="video-wrap" style="width: 530px;height: 330px;padding-top:50px">',
width: 530, `<div class="wrap-title" style="margin-top: -35px;">${deviceName}</div>`,
height: 350, `<div class="close" onclick="pageEvent.closeInfoWindow()">X</div>`,
enableCloseOnClick: false, `<div class="wrap-content">`,
}); `<div class="content-left" style="height: 260px">`,
map.openInfoWindow(infoWindow, marker.point); '<video id="video-player" ref="player1" muted autoplay></video>',
`</div>`,
`</div>`,
`</div>`,
];
const infoWindow = new BMap.InfoWindow(html.join(''), {
width: 530,
height: 350,
enableCloseOnClick: false,
});
map.openInfoWindow(infoWindow, marker.point);
const data = rows[0];
const params = {};
if (data.nvrIp) {
params.deviceIp = data.nvrIp;
params.channelNo = data.nvrChannelNo;
} else {
params.deviceIp = data.deviceIp;
params.channelNo = data.channelNo;
}
doPlayer(params);
}
},
);
}); });
}); });
} }
}); });
}); }
//
let currentPlayer = undefined;
/**
* 开始播放视频流
* @param nodeData 播放的节点数据
*/
function doPlayer(nodeData) {
if (mpegts.isSupported()) {
streamProxy(nodeData, (res) => {
const url = res.flv;
// url nodeData
nodeData.url = url;
closeVideo(currentPlayer);
const videoConfig = {
type: 'flv',
url: url,
isLive: true,
hasAudio: false,
hasVideo: true,
enableWorker: true, // 线
enableStashBuffer: false, // IO
stashInitialSize: 256, //
};
const playerConfig = {
enableErrorRecover: true, //
autoCleanupMaxBackwardDuration: 30,
autoCleanupMinBackwardDuration: 10,
};
const player = mpegts.createPlayer(videoConfig, playerConfig);
const videoElement = document.getElementById('video-player');
if (videoElement) {
player.attachMediaElement(videoElement);
player.load();
player.play();
} else {
console.log('视频播放元素获取异常');
}
});
} else {
message.error('浏览器不支持播放');
}
}
function streamProxy(params, cb) {
if (isSupportH265) {
addMediaStreamProxy(params).then((res) => cb(res));
} else {
// addMediaStreamProxy(params).then((res) => cb(res));
addFFmpegMediaStreamProxy(params).then((res) => cb(res));
}
}
//
window.pageEvent = { window.pageEvent = {
closeInfoWindow() { closeInfoWindow() {
map.closeInfoWindow(); map.closeInfoWindow();
closeVideo(currentPlayer); closeVideo(currentPlayer);
currentPlayer = null;
}, },
}; };

View File

@ -75,6 +75,11 @@
height: 111%; height: 111%;
} }
video {
width: 100%;
height: 100%;
}
.content-right { .content-right {
margin-left: 15px; margin-left: 15px;
padding-top: 10px; padding-top: 10px;

View File

@ -178,7 +178,7 @@ function doPlayer(nodeData: any, index: number = 0) {
console.log('index=', index); console.log('index=', index);
if (mpegts.isSupported()) { if (mpegts.isSupported()) {
streamProxy(nodeData, (res: AddStreamProxyResult) => { streamProxy(nodeData, (res: AddStreamProxyResult) => {
const url = res.wsFlv; const url = res.flv;
// url nodeData // url nodeData
nodeData.url = url; nodeData.url = url;
closePlayer(index); closePlayer(index);

View File

@ -305,7 +305,7 @@ function doPlayer(nodeData: any, index: number = 0) {
console.log('index=', index); console.log('index=', index);
if (mpegts.isSupported()) { if (mpegts.isSupported()) {
streamProxy(nodeData, (res: AddStreamProxyResult) => { streamProxy(nodeData, (res: AddStreamProxyResult) => {
const url = res.wsFlv; const url = res.flv;
// url nodeData // url nodeData
nodeData.url = url; nodeData.url = url;
closePlayer(index); closePlayer(index);
@ -371,10 +371,25 @@ function closePlayer(index: number) {
} }
} }
function catchUp() {
playerList.forEach((playerData) => {
if (playerData) {
const { player, el } = playerData;
const end = player.buffered.end(player.buffered.length - 1);
const diff = end - el.currentTime;
if (diff > 2) {
// 2
el.currentTime = end - 0.5; //
}
}
});
}
let isSupportH265 = false; let isSupportH265 = false;
onMounted(() => { onMounted(() => {
// h265 // h265
isSupportH265 = checkHEVCSupport(); isSupportH265 = checkHEVCSupport();
setInterval(catchUp, 10000);
}); });
onUnmounted(() => { onUnmounted(() => {