Explorar el Código

feat: add speed control for PTZ and zoom functionalities in streaming interfaces

- Introduce speed control slider for PTZ movements in both Cloudflare Stream and WebRTC components
- Update PTZ command logging to include speed information
- Enhance zoom control with a slider for more precise adjustments
- Refactor zoom control UI for improved layout and user experience
yb hace 2 semanas
padre
commit
000bd34fc2
Se han modificado 2 ficheros con 112 adiciones y 54 borrados
  1. 34 8
      src/views/demo/cloudflare-stream.vue
  2. 78 46
      src/views/demo/webrtc-stream.vue

+ 34 - 8
src/views/demo/cloudflare-stream.vue

@@ -100,6 +100,20 @@
           </div>
         </div>
 
+        <!-- 速度控制 -->
+        <div class="speed-control">
+          <div class="control-label">
+            <span>速度: {{ ptzSpeed }}</span>
+          </div>
+          <el-slider
+            v-model="ptzSpeed"
+            :min="10"
+            :max="100"
+            :step="10"
+            :show-tooltip="true"
+          />
+        </div>
+
         <!-- 缩放控制 -->
         <div class="zoom-controls">
           <div class="zoom-header">
@@ -333,11 +347,12 @@ async function handlePTZ(direction: keyof typeof PTZ_DIRECTIONS) {
       username: ptzConfig.username,
       password: ptzConfig.password
     },
-    direction
+    direction,
+    ptzSpeed.value
   )
 
   if (result.success) {
-    addLog(`PTZ 移动: ${direction}`, 'info')
+    addLog(`PTZ 移动: ${direction} (速度: ${ptzSpeed.value})`, 'info')
   } else {
     addLog(`PTZ 控制失败: ${result.error}`, 'error')
   }
@@ -516,23 +531,34 @@ async function handleZoomRelease() {
     }
   }
 
-  .zoom-controls {
+  .speed-control {
     margin-top: 15px;
     padding-top: 15px;
     border-top: 1px solid var(--border-color);
 
-    .zoom-label {
+    .control-label {
       font-size: 12px;
       color: var(--text-secondary);
-      margin-bottom: 10px;
+      margin-bottom: 8px;
     }
+  }
 
-    .zoom-btns {
+  .zoom-controls {
+    margin-top: 15px;
+    padding-top: 15px;
+    border-top: 1px solid var(--border-color);
+
+    .zoom-header {
       display: flex;
-      gap: 8px;
+      align-items: center;
+      justify-content: space-between;
+      font-size: 12px;
+      color: var(--text-secondary);
+      margin-bottom: 8px;
 
-      .el-button {
+      span {
         flex: 1;
+        text-align: center;
       }
     }
   }

+ 78 - 46
src/views/demo/webrtc-stream.vue

@@ -97,29 +97,37 @@
           </div>
         </div>
 
+        <!-- 速度控制 -->
+        <div class="speed-control">
+          <div class="control-label">
+            <span>速度: {{ ptzSpeed }}</span>
+          </div>
+          <el-slider
+            v-model="ptzSpeed"
+            :min="10"
+            :max="100"
+            :step="10"
+            :show-tooltip="true"
+          />
+        </div>
+
         <!-- 缩放控制 -->
         <div class="zoom-controls">
-          <div class="zoom-label">缩放</div>
-          <div class="zoom-btns">
-            <el-button
-              type="primary"
-              :icon="ZoomIn"
-              @mousedown="handleZoom('IN')"
-              @mouseup="handleZoomStop"
-              @mouseleave="handleZoomStop"
-            >
-              放大
-            </el-button>
-            <el-button
-              type="primary"
-              :icon="ZoomOut"
-              @mousedown="handleZoom('OUT')"
-              @mouseup="handleZoomStop"
-              @mouseleave="handleZoomStop"
-            >
-              缩小
-            </el-button>
+          <div class="zoom-header">
+            <el-icon><ZoomOut /></el-icon>
+            <span>缩放</span>
+            <el-icon><ZoomIn /></el-icon>
           </div>
+          <el-slider
+            v-model="zoomValue"
+            :min="-100"
+            :max="100"
+            :step="10"
+            :show-tooltip="true"
+            :format-tooltip="formatZoomTooltip"
+            @input="handleZoomChange"
+            @change="handleZoomRelease"
+          />
         </div>
       </div>
     </div>
@@ -246,6 +254,10 @@ const ptzConfig = reactive({
   password: 'Wxc767718929'
 })
 
+// PTZ 速度和缩放
+const ptzSpeed = ref(50)
+const zoomValue = ref(0)
+
 // 播放状态
 const isPlaying = ref(false)
 
@@ -384,11 +396,12 @@ async function handlePTZ(direction: keyof typeof PTZ_DIRECTIONS) {
       username: ptzConfig.username,
       password: ptzConfig.password
     },
-    direction
+    direction,
+    ptzSpeed.value
   )
 
   if (result.success) {
-    addLog(`PTZ 移动: ${direction}`, 'info')
+    addLog(`PTZ 移动: ${direction} (速度: ${ptzSpeed.value})`, 'info')
   } else {
     addLog(`PTZ 控制失败: ${result.error}`, 'error')
   }
@@ -408,41 +421,49 @@ async function handlePTZStop() {
   }
 }
 
-// 缩放控制
-async function handleZoom(direction: keyof typeof PTZ_ZOOM_DIRECTIONS) {
-  if (!ptzConfig.host || !ptzConfig.username || !ptzConfig.password) {
-    ElMessage.warning('请先配置摄像头信息')
+// 缩放滑块控制
+function formatZoomTooltip(val: number) {
+  if (val === 0) return '停止'
+  return val > 0 ? `放大 ${val}` : `缩小 ${Math.abs(val)}`
+}
+
+async function handleZoomChange(val: number) {
+  if (!ptzConfig.host || !ptzConfig.username || !ptzConfig.password) return
+
+  if (val === 0) {
+    await stopZoom({
+      host: ptzConfig.host,
+      username: ptzConfig.username,
+      password: ptzConfig.password
+    })
     return
   }
 
-  const result = await startZoom(
+  const direction = val > 0 ? 'IN' : 'OUT'
+  const speed = Math.abs(val)
+
+  await startZoom(
     {
       host: ptzConfig.host,
       username: ptzConfig.username,
       password: ptzConfig.password
     },
-    direction
+    direction,
+    speed
   )
-
-  if (result.success) {
-    addLog(`缩放: ${direction === 'IN' ? '放大' : '缩小'}`, 'info')
-  } else {
-    addLog(`缩放失败: ${result.error}`, 'error')
-  }
 }
 
-async function handleZoomStop() {
+async function handleZoomRelease() {
+  // 松开滑块时回到中间并停止
+  zoomValue.value = 0
   if (!ptzConfig.host) return
 
-  const result = await stopZoom({
+  await stopZoom({
     host: ptzConfig.host,
     username: ptzConfig.username,
     password: ptzConfig.password
   })
-
-  if (!result.success) {
-    addLog(`缩放停止失败: ${result.error}`, 'error')
-  }
+  addLog('缩放停止', 'info')
 }
 </script>
 
@@ -563,23 +584,34 @@ async function handleZoomStop() {
     }
   }
 
-  .zoom-controls {
+  .speed-control {
     margin-top: 15px;
     padding-top: 15px;
     border-top: 1px solid var(--border-color);
 
-    .zoom-label {
+    .control-label {
       font-size: 12px;
       color: var(--text-secondary);
-      margin-bottom: 10px;
+      margin-bottom: 8px;
     }
+  }
 
-    .zoom-btns {
+  .zoom-controls {
+    margin-top: 15px;
+    padding-top: 15px;
+    border-top: 1px solid var(--border-color);
+
+    .zoom-header {
       display: flex;
-      gap: 8px;
+      align-items: center;
+      justify-content: space-between;
+      font-size: 12px;
+      color: var(--text-secondary);
+      margin-bottom: 8px;
 
-      .el-button {
+      span {
         flex: 1;
+        text-align: center;
       }
     }
   }