diff --git a/package-lock.json b/package-lock.json index 40b876b..ede4e8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,8 @@ "jszip": "^3.10.1", "pinia": "^2.3.0", "vue": "^3.5.38", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "whammy": "^0.0.1" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.7", @@ -796,6 +797,29 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.3.tgz", @@ -2966,6 +2990,12 @@ "dev": true, "license": "MIT" }, + "node_modules/whammy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/whammy/-/whammy-0.0.1.tgz", + "integrity": "sha512-H8J4+I5ISuOZXAZiNMZXD71+oZIM6szrgYG8wt4dCpDNEU8mogxPGvgMIFg/BhkuptOLbtW0X34E/YE6a75ujg==", + "license": "BSD-2-Clause" + }, "node_modules/zrender": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.1.0.tgz", diff --git a/package.json b/package.json index 838f525..221493b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "jszip": "^3.10.1", "pinia": "^2.3.0", "vue": "^3.5.38", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "whammy": "^0.0.1" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.7", diff --git a/src/views/home/components/VideoPlayer.vue b/src/views/home/components/VideoPlayer.vue index 588c82b..8b0211b 100644 --- a/src/views/home/components/VideoPlayer.vue +++ b/src/views/home/components/VideoPlayer.vue @@ -1,5 +1,8 @@ diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 21e9527..c763ee2 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -31,12 +31,26 @@ @upload-video="handleVideoUpload" /> - +
+ + +
videoMode.value === 'live') @@ -179,6 +194,7 @@ function connectRawStream() { case 'webrtc_stream': webrtcUrl.value = msg.webrtc_url + webrtcUrl2.value = msg.webrtc_url2 || msg.webrtc_url addLog('已获取原始 WebRTC 流,开始播放', 'success') ElMessage.success('原始视频流已连接') break @@ -270,6 +286,7 @@ function connectDetectStream() { case 'webrtc_stream': webrtcUrl.value = msg.webrtc_url + webrtcUrl2.value = msg.webrtc_url2 || msg.webrtc_url addLog('已获取检测 WebRTC 流,开始播放', 'success') ElMessage.success('检测流已连接') break @@ -403,6 +420,7 @@ async function switchStream() { stopRawStream() videoMode.value = 'live' webrtcUrl.value = '' + webrtcUrl2.value = '' algorithmRunning.value = false paused.value = false clearAllLiveData() @@ -427,13 +445,14 @@ async function toggleStream() { } else { stopDetectStream() algorithmRunning.value = false - streamRunning.value = false - videoMode.value = 'idle' - webrtcUrl.value = '' - paused.value = false - ending.value = false - ElMessage.info('视频流已关闭') - addLog('视频流已关闭', 'info') + streamRunning.value = false + videoMode.value = 'idle' + webrtcUrl.value = '' + webrtcUrl2.value = '' + paused.value = false + ending.value = false + ElMessage.info('视频流已关闭') + addLog('视频流已关闭', 'info') } } else { // 启动视频流 — 确保算法启用状态为 true @@ -458,6 +477,7 @@ async function toggleStream() { streamRunning.value = true videoMode.value = 'live' webrtcUrl.value = '' + webrtcUrl2.value = '' clearAllLiveData() connectProcessWs() // 如果原始流还在运行(由"切换"启动),先关闭 @@ -480,6 +500,7 @@ function handleVideoUpload(file) { offlineVideoUrl.value = URL.createObjectURL(file.raw) detectionFile.value = file.raw videoMode.value = 'offline' + webrtcUrl2.value = '' resetDetectionState() flowLogs.value = [] addLog('离线视频已加载','warning') @@ -925,6 +946,24 @@ onUnmounted(() => { min-height: 0; } +.video-row { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + min-height: 0; + + .video-container { + flex: 1; + min-width: 0; + min-height: 0; + } + + .secondary-video { + position: relative; + } +} + .stats-panel { display: flex; flex-wrap: wrap;