소스 검색

修复手机视频兼容性: MJPEG改为JPEG单帧轮询

- 手机端不再直接使用multipart MJPEG
- 改用/stream/:ch单帧JPEG轮询, 每100ms一帧
- 兼容不支持multipart MJPEG的手机浏览器
- 局域网验证stream/0返回640x360 JPEG HTTP 200
dev 6 일 전
부모
커밋
b1819caaa3
1개의 변경된 파일과 29개의 추가작업 그리고 9개의 파일을 삭제
  1. 29 9
      web/mobile.html

+ 29 - 9
web/mobile.html

@@ -120,6 +120,9 @@ body{font-family:system-ui,sans-serif;background:#0b1220;color:#e8e8e8;height:10
 let channels = [];
 let curChannel = 0;
 let curType = '';
+let videoTimer = null;
+let videoBusy = false;
+let videoUrl = '';
 
 function toast(msg) {
   const t = document.getElementById('toast');
@@ -177,20 +180,37 @@ function renderChSwitcher() {
 function switchChannel(id) {
   curChannel = id;
   renderChSwitcher();
+  startVideoPolling(id);
+}
+
+// 手机浏览器对multipart MJPEG兼容性不一致, 使用单帧JPEG轮询保证兼容
+function startVideoPolling(id) {
+  if (videoTimer) { clearTimeout(videoTimer); videoTimer = null; }
   const v = document.getElementById('video');
-  v.src = '/mjpeg/' + id + '?t=' + Date.now();
+  videoUrl = '/stream/' + id;
+  videoBusy = false;
+  document.getElementById('videoLoader').textContent = '加载中...';
   document.getElementById('videoLoader').style.display = 'block';
-  v.onload = () => { document.getElementById('videoLoader').style.display = 'none'; };
-  v.onerror = () => {
-    document.getElementById('videoLoader').textContent = '视频加载失败';
-    // 3秒后自动重试
-    setTimeout(() => {
+  const next = () => {
+    if (curChannel !== id) return;
+    const img = new Image();
+    videoBusy = true;
+    img.onload = () => {
       if (curChannel === id) {
-        document.getElementById('videoLoader').textContent = '重试中...';
-        v.src = '/mjpeg/' + id + '?t=' + Date.now();
+        v.src = img.src;
+        document.getElementById('videoLoader').style.display = 'none';
       }
-    }, 3000);
+      videoBusy = false;
+      videoTimer = setTimeout(next, 100);
+    };
+    img.onerror = () => {
+      videoBusy = false;
+      document.getElementById('videoLoader').textContent = '视频加载失败,重试中...';
+      videoTimer = setTimeout(next, 1000);
+    };
+    img.src = videoUrl + '?t=' + Date.now();
   };
+  next();
 }
 
 function switchTab(tab) {