Fix browser recording playback and web management consistency
This commit is contained in:
@@ -26,6 +26,7 @@ import urllib.parse as url
|
||||
import urllib.request
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
import onvif
|
||||
import playback
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
os.umask(0o077)
|
||||
@@ -79,7 +80,8 @@ def set_setting(key, value):
|
||||
|
||||
def objects(table):
|
||||
with LOCK:
|
||||
return [dict(json.loads(r['body']), id=r['id']) for r in DB.execute('SELECT * FROM ' + table)]
|
||||
rows = [dict(json.loads(r['body']), id=r['id']) for r in DB.execute('SELECT * FROM ' + table)]
|
||||
return sorted(rows, key=lambda row: (row.get('name', ''), row['id']))
|
||||
|
||||
|
||||
def get_object(table, key):
|
||||
@@ -594,7 +596,7 @@ class Handler(BaseHTTPRequestHandler):
|
||||
except Exception:
|
||||
self.answer({'error': '操作未完成,请检查输入或服务状态'}, 500)
|
||||
|
||||
def proxy(self, port, path):
|
||||
def proxy(self, port, path, download=False):
|
||||
conn = http.client.HTTPConnection('127.0.0.1', port, timeout=55)
|
||||
headers = {'Authorization': MEDIA_AUTH}
|
||||
if self.headers.get('Range'):
|
||||
@@ -615,6 +617,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||
raise Problem('视频服务返回了无效的播放跳转', 502)
|
||||
location = '/media/live' + target.path + ('?' + target.query if target.query else '')
|
||||
self.send_response(r.status)
|
||||
if download:
|
||||
self.send_header('Content-Disposition', 'attachment; filename="recording.mp4"')
|
||||
if location:
|
||||
self.send_header('Location', location)
|
||||
for k in ('Content-Type', 'Content-Length', 'Content-Range', 'Accept-Ranges'):
|
||||
@@ -635,6 +639,36 @@ class Handler(BaseHTTPRequestHandler):
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def compatible_playback(self, path, duration):
|
||||
started = False
|
||||
old_timeout = self.connection.gettimeout()
|
||||
try:
|
||||
with playback.stream('http://127.0.0.1:' + str(PLAYBACK_PORT) + path, MEDIA_AUTH, duration) as output:
|
||||
first = output.read1(65536)
|
||||
if not first:
|
||||
raise Problem('录像转换失败,请检查录像是否完整及服务器视频驱动', 503)
|
||||
self.connection.settimeout(15)
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'video/mp4')
|
||||
self.send_header('Cache-Control', 'no-store')
|
||||
self.send_header('Accept-Ranges', 'none')
|
||||
self.send_header('X-Content-Type-Options', 'nosniff')
|
||||
self.send_header('Connection', 'close')
|
||||
self.end_headers()
|
||||
started = True
|
||||
self.close_connection = True
|
||||
self.wfile.write(first)
|
||||
while chunk := output.read1(65536):
|
||||
self.wfile.write(chunk)
|
||||
except playback.PlaybackError as exc:
|
||||
if not started:
|
||||
raise Problem(str(exc), 503)
|
||||
except OSError:
|
||||
if not started:
|
||||
raise Problem('录像转换连接失败', 503)
|
||||
finally:
|
||||
self.connection.settimeout(old_timeout)
|
||||
|
||||
def do_GET(self):
|
||||
try:
|
||||
parsed = url.urlsplit(self.path)
|
||||
@@ -681,9 +715,13 @@ class Handler(BaseHTTPRequestHandler):
|
||||
raise ValueError()
|
||||
except ValueError:
|
||||
raise Problem('单次回放最多一小时')
|
||||
download = query.get('download') == '1'
|
||||
q = url.urlencode({'path': stream_name(c), 'start': start.isoformat(), 'duration': duration,
|
||||
'format': 'mp4' if query.get('download') == '1' else 'fmp4'})
|
||||
self.proxy(PLAYBACK_PORT, '/get?' + q)
|
||||
'format': 'mp4' if download else 'fmp4'})
|
||||
if download:
|
||||
self.proxy(PLAYBACK_PORT, '/get?' + q, download=True)
|
||||
else:
|
||||
self.compatible_playback('/get?' + q, duration)
|
||||
else:
|
||||
raise Problem('接口不存在', 404)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user