console
document.querySelectorAll('.btns button').forEach(v => {
v.setAttribute('disabled', true)
document.getElementById('domOpenConnect').removeAttribute('disabled')
})
let ws = null
const img = document.getElementById("stream");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const domNowTime = document.getElementById('nowTime')
const domMessage = document.getElementById('message')
const buffSize = 500
let buffData = []
let boxes = []
let boxesNew = []
var lastWsTime = 0
var frameBuffObj = []
var frameBuff = []
var boxBuff = []
var boxBuffObj = []
var currIndex = 0, indexNum = 0
var boxIndex = 0, boxNum = 0
var selBoxIndex = 0
var lastTime = 0
var timer02 = null
var funcId = ''
function doTest() {
ctx.strokeRect(0, 0, 100, 100);
ctx.strokeRect(0, 1080 / 2 - 50, 100, 100);
ctx.strokeRect(1920 - 100, 0, 100, 100);
ctx.strokeRect(1920 - 100, 1080 / 2 - 50, 100, 100);
ctx.strokeRect(0, 1080 - 100, 100, 100);
ctx.strokeRect(1920 - 100, 1080 - 100, 100, 100);
ctx.strokeRect(1920 / 2 - 50, 0, 100, 100);
ctx.strokeRect(1920 / 2 - 50, 1080 - 100, 100, 100);
ctx.strokeRect(1920 / 2 - 50, 1080 / 2 - 50, 100, 100);
}
function doTestLoop() {
message.innerHTML = ''
frameBuffObj.forEach(v => {
if (!v) return
var img = new Image()
img.src = v.data
var div = document.createElement('div')
div.innerHTML = new Date(v.time).toLocaleString() + ' ' + (v.time)
message.prepend(div)
})
process1.innerHTML = currIndex
process1.style.width = (((currIndex / buffSize) * 100) + '%')
message2.innerHTML = ''
boxBuffObj.forEach(v => {
var div = document.createElement('div')
div.innerHTML = new Date(v.time).toLocaleString() + ' ' + (v.time)
message2.prepend(div)
})
process2.style.width = (((boxIndex / buffSize) * 100) + '%')
}
var mdate = {}
function openConnect() {
init()
}
function closeConnect() {
if (ws) {
ws.close()
ws = null
}
console.log(JSON.stringify(mdate))
}
function sendDebug() {
let data = {
action: 'debug',
}
ws.send(JSON.stringify(data))
}
function sendFunc() {
var cameraId = document.getElementById('cameraId').value
let data = {
action: 'func',
params: cameraId + ""
}
ws.send(JSON.stringify(data))
}
function sendFuncStop() {
let data = {
action: 'func.stop',
id: funcId
}
alert(JSON.stringify(data))
ws.send(JSON.stringify(data))
}
function doRender() {
var obj = event.target
if (!isRender) {
startRender()
obj.innerHTML = 'Stop Render'
} else {
stopRender()
obj.innerHTML = 'Render'
}
}
function openStream() {
canvas.width = 0
var cameraId = document.getElementById('cameraId').value
let data = {
action: 'start',
params: cameraId + ""
}
ws.send(JSON.stringify(data))
logClean()
selBoxIndex = currIndex
}
function closeStream() {
var cameraId = document.getElementById('cameraId').value
let data = {
action: 'stop',
params: cameraId + ""
}
ws.send(JSON.stringify(data))
}
var boxNum = 0
function init() {
ws = new WebSocket("ws://localhost:12800/ws");
frameBuff = []
boxBuff = []
currIndex = 0
boxIndex = 0
for (var i = 0; i < buffSize; i++) {
frameBuff[i + ""] = ""
}
for (var i = 0; i < buffSize; i++) {
boxBuff[i + ""] = []
}
ws.onmessage = function (event) {
if (typeof event.data === "object") {
var blob = new Blob([event.data], { type: "image/jpeg" })
var url = URL.createObjectURL(blob)
frameBuff[currIndex + ""] = url
frameBuffObj[currIndex + ""] = {
data: url,
time: lastWsTime
}
selBoxIndex = currIndex
render()
currIndex++
if (currIndex >= buffSize) {
currIndex = 0
indexNum++
}
process1.innerHTML = boxes.length
process1.style.width = (((currIndex / buffSize) * 100) + '%')
} else {
var data = {}
try {
data = JSON.parse(event.data)
} catch {
data = {}
}
if (data.type) {
if (data.type === 'point') {
var res = data.boxes
if (!res) return
if (boxes.length > 50) boxes = []
boxes = boxes.concat(res)
boxBuff[boxIndex + ""] = res
boxBuffObj[boxIndex + ""] = {
data: res,
time: data.time
}
boxIndex++
if (boxIndex == buffSize) {
boxIndex = 0
boxNum++
}
let n = new Date().getTime()
if (data.time > 0) {
boxesNew.push({
data: res,
time: data.time
})
}
boxesNew = boxesNew.filter(v => {
return n - v.time < 500
})
draw_boxes(boxesNew)
} else if (data.type === 'frame') {
var time = parseInt(data.time)
lastWsTime = time
var key = parseInt(time / 1000) + ''
if (!buffData[key]) {
buffData[key] = 0
}
buffData[key]++
} else if (data.type === 'strm1') {
var index0 = parseInt(data.d1)
var index1 = parseInt(data.d2)
} else if (data.type == 'error') {
log(data.error)
log("close")
} else if (data.type === 'func') {
funcId = data.id
}
} else {
}
}
};
ws.onopen = function () {
document.querySelectorAll('.btns button').forEach(v => {
v.removeAttribute('disabled')
document.getElementById('domOpenConnect').setAttribute('disabled', true)
})
};
ws.onclose = function () {
document.querySelectorAll('.btns button').forEach(v => {
v.setAttribute('disabled', true)
document.getElementById('domOpenConnect').removeAttribute('disabled')
})
};
ws.onerror = function (error) {
console.error("WebSocket error:", error);
};
}
var timer01 = null
var nowIndex = 0
var latestBox = []
var isRender = false
function startRender() {
isRender = true
if (window) return
nowIndex = currIndex
latestBox = []
if (timer01) {
clearInterval(timer01)
timer01 = null
} else {
timer01 = setInterval(render, 1000 / 25)
}
}
function stopRender() {
if (timer01) {
clearInterval(timer01)
timer01 = null
}
isRender = false
}
function render1() {
var dt = (indexNum * buffSize + currIndex) - (boxNum * buffSize + boxIndex)
if (dt < 0) {
console.log('消费太快')
return
}
if (dt > buffSize) {
console.log('消费太慢')
boxIndex = currIndex
boxNum = indexNum
}
var frame = frameBuff[nowIndex + '']
if (!frame) {
return
}
draw_image_and_boxes(frame, [])
nowIndex++
if (nowIndex >= buffSize) {
nowIndex = 0
boxNum++
}
}
var lastBox = []
function render() {
var frame = null
frame = boxBuffObj[selBoxIndex + '']
frame = frameBuffObj[selBoxIndex + '']
if (!frame) {
selBoxIndex++
selBoxIndex = selBoxIndex % buffSize
return
}
var t = frame.time
var box = boxBuffObj.find((v, index) => {
var dt = Math.abs(t - v.time) / 1000
return dt >= 0 && dt < 2
})
if (box) {
lastBox = box.data
} else {
box = lastBox
}
draw_image_and_boxes(frame.data, [])
selBoxIndex++
selBoxIndex = selBoxIndex % buffSize
}
function draw_image_and_boxes(src, boxes) {
let img = new Image()
img.src = src
img.onload = () => {
if (!canvas.width) {
canvas.width = img.width;
canvas.height = img.height;
}
ctx.drawImage(img, 0, 0);
draw_boxes(boxesNew)
}
}
function draw_boxes(p1) {
ctx.strokeStyle = "#00FF00";
ctx.lineWidth = 3;
ctx.font = "18px serif";
let n = new Date().getTime()
let boxes1 = []
p1.map(v => {
boxes1 = boxes1.concat(v.data)
})
boxes1.forEach(([x1, y1, x2, y2, label, prob]) => {
prob = prob.toFixed(2)
if (prob < 0.1) return
ctx.strokeStyle = stringToColor(label)
const width = ctx.measureText(label + ' ' + prob).width;
let h = y2 - y1
if (h < 18) h = 20
let w = x2 - x1
if (w < width) w = width + 2
ctx.strokeRect(x1, y1 - 0, w, h);
ctx.fillStyle = ctx.strokeStyle;
ctx.fillRect(x1 + 2, y1 - 0, width + 10, 25);
ctx.fillStyle = "#000000";
ctx.fillText(label + ' ' + prob, x1, y1 + 18 - 0);
});
}
function log(message) {
domMessage.innerHTML += "[" + new Date().toLocaleTimeString() + "] " + message + "<br>"
}
function logClean() {
domMessage.innerHTML = ''
}
let colorMap = {}
function stringToColor(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
if (colorMap[hash]) {
return colorMap[hash]
}
const r = (hash & 0xFF0000) >> 16;
const g = (hash & 0x00FF00) >> 8;
const b = hash & 0x0000FF;
colorMap[hash] = `rgb(${r | 0x80}, ${g | 0x80}, ${b | 0x80})`
return colorMap[hash];
}
<h1>
StreamManager
<div style="display: inline-block" class="btns">
<button onclick="openConnect()" id="domOpenConnect">连接</button>
<button onclick="closeConnect()" id="domCloseConnect">断开</button>
<select id="cameraId" style="padding: .18rem 1rem;">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button onclick="openStream()" id="domOpenStream">打开</button>
<button onclick="closeStream()" id="domCloseStream">关闭</button>
<button onclick="sendDebug()" id="domSendDebug">调试</button>
<button onclick="sendFunc()" id="domSendFunc">Func</button>
<button onclick="sendFuncStop()" id="domSendFuncStop">FuncStop</button>
<button onclick="doRender()" id="domRenderFunc">Render</button>
<button onclick="doTest()" id="domTest">开启</button>
</div>
<span id="domTime"></span>
<div id="nowTime"></div>
</h1>
<img id="stream" width="640" height="360" style="opacity: 0.6; height: 0;"/>
<div style="display: flex; max-height: 80vh; overflow-y: auto;">
<div style="flex: 10; width1: 50%;">
<canvas style="width: 100%" width="0" height="0"></canvas>
</div>
<div style="flex: 1; ">
<div id="process1" style="height: 1rem;background: red;"></div>
<div id="message">
</div>
</div>
<div style="flex: 1; ">
<div id="process2" style="height: 1rem;background: blue;"></div>
<div id="message2">
</div>
</div>
</div>
.btns button {
}
canvas {
opacity: 1.2;
}
#message img {
display: block;
width: 100%;
}