diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ea126d6..cd33c06 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -27,7 +27,7 @@ 当前 RTSP 负责实时视频,ONVIF 负责读取设备身份、媒体配置、独立视频源及主子码流地址。不同品牌使用相同对象结构,路径和能力由设备返回值或对应驱动确定;不按品牌名字保证所有型号兼容。当前品牌驱动只提供路径模板,自动摄像头配置读取支持 ONVIF Media v1。 -主码流用于清晰预览和可选本机录像。默认多画面预览由每路子码流经 FFmpeg 转为 H.264 / AAC;MediaMTX 的 runOnDemand 仅在观看时启动受限分辨率的转码进程,发布权限限定为回环地址的兼容预览路径。高清兼容预览读取原始主码流,经 Intel VAAPI 完成解码、1080p 缩放和 H.264 编码,最高 15 帧/秒;无可用硬件时明确失败,不自动启动多路软件高清转换。原始主、子码流仍可选择。系统目前不修改摄像头或录像机设置,不自动导入不存在的通道,不把服务可达当成画面接通。 +主码流用于清晰预览和可选本机录像。界面只显示主码流与子码流两个选项,默认主码流。子码流预览由每路子码流经 FFmpeg 转为 H.264 / AAC;MediaMTX 的 runOnDemand 仅在观看时启动受限分辨率的转码进程,发布权限限定为回环地址的兼容预览路径。高清兼容预览读取原始主码流,经 Intel VAAPI 完成解码、1080p 缩放和 H.264 编码,最高 15 帧/秒;无可用硬件时明确失败,不自动启动多路软件高清转换。原始编码直出不作为网页预览选项,原始主码流继续用于录像及转码输入。系统目前不修改摄像头或录像机设置,不自动导入不存在的通道,不把服务可达当成画面接通。 ## 管理 API diff --git a/README.md b/README.md index b271933..13c0c01 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ 本机录像默认关闭,用户逐通道开启。默认保留 7 天、容量 40 GB、磁盘预留 8 GB,界面可调整。保留期限到达后 MediaMTX 自动删除本机录像;配额达到后暂停录制,不删除录像机中的数据。配额每 20 秒观察一次,允许少量超出。文件路径及录像索引使用 UTC,界面按浏览器时区显示。 -HLS 会有数秒延迟。网页默认使用 FFmpeg 按需生成的 H.264 Baseline / AAC 兼容画面,最高 768×432、10 帧/秒,供小电脑上的多镜头预览。“高清 · 主码流兼容”使用实际主码流,通过 Intel VAAPI 硬件解码、缩放及 H.264 Main 编码,最高 1920×1080、15 帧/秒。高清预览需要可用的 Intel 核显、驱动及 render 设备权限,不自动退回高负载的软件高清转码。首开需要等待取流与缓冲。没有观看者后会停止转码;同一镜头的观看者共享一路转码。用户仍可选择原始主、子码流,但 H.265 的兼容性取决于浏览器。本机录像保留原始主码流编码,兼容预览不改变录像及摄像头设置。网页回放按需转换为 H.264/AAC,最多同时两个会话,每段最多一小时;使用时间轴或定位时间跳转。关闭回放或切换页面后终止转换,不生成额外缓存文件。有可用 VAAPI 时回放最高 1080p/15 帧,否则使用 768×432/10 帧软件转换。下载保留原始录像编码,需支持该编码的播放器。设备状态基于 MediaMTX 实际码流状态;“正在录像”还要求观察到近期写入的本机录像文件。离线不会生成假画面或假录像。 +HLS 会有数秒延迟。网页清晰度仅提供“主码流”和“子码流”两个选项,默认主码流。主码流预览使用实际主码流,通过 Intel VAAPI 硬件解码、缩放及 H.264 Main 编码,最高 1920×1080、15 帧/秒。子码流预览使用实际子码流,由 FFmpeg 按需生成 H.264 Baseline / AAC 兼容画面,最高 768×432、10 帧/秒。高清预览需要可用的 Intel 核显、驱动及 render 设备权限,不自动退回高负载的软件高清转码。首开需要等待取流与缓冲。没有观看者后会停止转码;同一镜头的观看者共享一路转码。网页不提供原始编码直出的预览选项。本机录像保留原始主码流编码,兼容预览不改变录像及摄像头设置。网页回放按需转换为 H.264/AAC,最多同时两个会话,每段最多一小时;使用时间轴或定位时间跳转。关闭回放或切换页面后终止转换,不生成额外缓存文件。有可用 VAAPI 时回放最高 1080p/15 帧,否则使用 768×432/10 帧软件转换。下载保留原始录像编码,需支持该编码的播放器。设备状态基于 MediaMTX 实际码流状态;“正在录像”还要求观察到近期写入的本机录像文件。离线不会生成假画面或假录像。 ## Ubuntu x86_64 部署 diff --git a/VERSION b/VERSION index 699c6c6..1a03094 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.8 +0.1.9 diff --git a/test_app.py b/test_app.py index 9061966..3e8ad2d 100644 --- a/test_app.py +++ b/test_app.py @@ -4,6 +4,7 @@ import http.client import io import json import os +import re import tempfile import threading import time @@ -63,6 +64,13 @@ class WebTests(unittest.TestCase): self.assertEqual(headers['X-Frame-Options'], 'DENY') self.assertIn("frame-ancestors 'none'", headers['Content-Security-Policy']) + def test_live_quality_has_only_main_and_sub(self): + code, _, body = self.request('/', False) + self.assertEqual(code, 200) + select = re.search(r'', body.decode()).group(1) + self.assertEqual(re.findall(r'', select), + [('hd', '主码流'), ('compat', '子码流')]) + def test_origin_rejected(self): self.assertEqual(self.request('/api/storage', data={}, origin='https://example.org')[0], 403) diff --git a/web/app.js b/web/app.js index 0be5a07..6a72a0d 100644 --- a/web/app.js +++ b/web/app.js @@ -62,12 +62,12 @@ function renderLive() { const src = `/media/live/cam_${c.id}_${quality}/index.m3u8`; const error = text => {const el=panel.querySelector('.video-error');el.textContent=text;el.hidden=false;}; video.onplaying=()=>{panel.querySelector('.video-empty').hidden=true;panel.querySelector('.video-error').hidden=true;}; - video.onerror=()=>error('浏览器无法解码此码流,请在清晰度中选择“流畅 · 兼容画面”或“高清 · 主码流兼容”。'); + video.onerror=()=>error('画面解码失败,请切换主码流或子码流,或点击刷新状态重试。'); if (window.Hls?.isSupported()) { const hls = new Hls({maxBufferLength:10,backBufferLength:5,liveSyncDurationCount:3,manifestLoadingTimeOut:60000,levelLoadingTimeOut:60000,manifestLoadingMaxRetry:2,levelLoadingMaxRetry:2}); hls.on(Hls.Events.ERROR,(_,data)=>{if(data.fatal){ const codecError = /codec|bufferAddCodec|manifestIncompatible/i.test(data.details || ''); - error(codecError ? '浏览器不支持当前视频编码,请选择“流畅 · 兼容画面”或“高清 · 主码流兼容”。' : '画面加载失败('+(data.details || data.type)+')。点击刷新状态可重试。'); + error(codecError ? '画面解码失败,请切换主码流或子码流,或点击刷新状态重试。' : '画面加载失败('+(data.details || data.type)+')。点击刷新状态可重试。'); console.warn('Video playback failed', c.id, data.type, data.details); hls.destroy(); }}); diff --git a/web/index.html b/web/index.html index f4a9298..06b7250 100644 --- a/web/index.html +++ b/web/index.html @@ -24,7 +24,7 @@
流畅画面最高 768×432;高清画面从主码流转换,最高 1920×1080、15 帧/秒。原始画面需要浏览器支持摄像头编码。
主码流画面更清晰,最高 1920×1080;子码流更流畅,最高 768×432,适合网络较慢时使用。
一台实体摄像头对应一个对象,双镜头在对象下建立两个镜头通道;每个镜头分别有主码流和子码流。
统一保存录像机地址与账号,镜头通道关联录像机。实时取流使用 RTSP;读取录像机已有历史录像,需要该型号的回放接口适配。
为家庭、公司或其他场所建立地址档案,再关联摄像头。地区、小区、楼栋和门牌都是独立属性。
开启摄像头的“持续录像”后,服务会保存主码流。预览默认使用 H.264 流畅画面(最高 768×432、10 帧/秒),也可选择从主码流转换的 1080p 高清画面。原始码流与本机录像保留设备编码。
开启摄像头的“持续录像”后,服务会保存主码流。预览默认使用主码流高清画面(最高 1920×1080、15 帧/秒),也可切换子码流流畅画面(最高 768×432、10 帧/秒)。本机录像保留设备原始编码。