Add camera presets snapshots and continuous recording playback

This commit is contained in:
Codex
2026-10-04 08:33:00 +08:00
parent 14f722fa69
commit 68be32e269
15 changed files with 513 additions and 43 deletions
+24 -2
View File
@@ -597,7 +597,7 @@ class Handler(BaseHTTPRequestHandler):
return
self.require_auth()
if path not in ('/api/logout', '/api/account/password', '/api/family/restore',
'/api/family/person', '/api/family/link', '/api/family/event', '/api/ptz'):
'/api/family/person', '/api/family/link', '/api/family/event', '/api/ptz', '/api/ptz/presets'):
self.require_admin()
if path == '/api/logout':
with LOCK:
@@ -619,6 +619,18 @@ class Handler(BaseHTTPRequestHandler):
raise Problem('设备保存请求未确认,可能已经生效;请重新读取参数后核对,勿反复提交', 502)
audit('修改摄像机参数 · ' + data['section'], c['name'] + ' / ' + self.user['username'])
self.answer(result)
elif path == '/api/ptz/presets':
c = ACCOUNTS.control(self.user, get_object('cameras', data.get('camera')))
if data.get('action') != 'goto':
self.require_admin()
try:
result = ptz.CONTROLLER.preset_command(c, data)
except ValueError as e:
raise Problem(str(e), 400)
except Exception:
raise Problem('设备操作未确认,请核对画面并重新读取预置位,勿重复提交;转动异常可点击停止', 502)
audit('云台预置位 ' + data['action'], c['name'] + ' / ' + self.user['username'])
self.answer(result)
elif path == '/api/ptz':
c = ACCOUNTS.control(self.user, get_object('cameras', data.get('camera')))
try:
@@ -778,6 +790,15 @@ class Handler(BaseHTTPRequestHandler):
elif path == '/api/users':
self.require_admin()
self.answer({'users': [ACCOUNTS.public(u) for u in objects('users')]})
elif path == '/api/ptz/presets':
c = ACCOUNTS.control(self.user, get_object('cameras', query.get('camera')))
try:
result, _ = ptz.CONTROLLER.read_presets(c)
except ValueError as e:
raise Problem(str(e), 400)
except Exception:
raise Problem('未能读取预置位,设备可能未开放该接口;方向微调仍可单独使用', 502)
self.answer(dict(result, canManage=self.user['role'] == 'admin'))
elif path == '/api/ptz':
c = ACCOUNTS.control(self.user, get_object('cameras', query.get('camera')))
try:
@@ -858,6 +879,7 @@ class Handler(BaseHTTPRequestHandler):
'/family-events.js': 'family-events.js',
'/family-history.js': 'family-history.js',
'/camera-settings.js': 'camera-settings.js',
'/recording-ranges.js': 'recording-ranges.js', '/recording-ui.js': 'recording-ui.js', '/snapshot.js': 'snapshot.js',
'/monitor.js': 'monitor.js', '/calendar.js': 'calendar.js', '/date-fields.js': 'date-fields.js',
'/zhao-icon.png': 'zhao-icon.png',
'/vendor/hls.min.js': 'vendor/hls.min.js'}
@@ -873,7 +895,7 @@ class Handler(BaseHTTPRequestHandler):
self.send_header('X-Content-Type-Options', 'nosniff')
self.send_header('X-Frame-Options', 'DENY')
self.send_header('Referrer-Policy', 'same-origin')
self.send_header('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; media-src 'self' blob:; worker-src 'self' blob:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'")
self.send_header('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: blob:; media-src 'self' blob:; worker-src 'self' blob:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'")
self.send_header('Cache-Control', 'no-store' if path == '/' else 'no-cache')
self.end_headers()
self.wfile.write(raw)