diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2024-02-18 02:19:27 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2024-02-18 02:19:27 +0300 |
commit | f14bdc6752fc4a0ab36567d0f1e51e472a2200b6 (patch) | |
tree | 22c6b3af78fc079ab6424751289971aa65051f97 /bin | |
parent | 42155370475b1f6619498ec2c43c1c7f328ce1a1 (diff) |
web_kbn: basic support of cams hls streaming
Diffstat (limited to 'bin')
-rw-r--r-- | bin/web_kbn.py | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/bin/web_kbn.py b/bin/web_kbn.py index 5b36d53..9a99ab3 100644 --- a/bin/web_kbn.py +++ b/bin/web_kbn.py @@ -10,7 +10,7 @@ import time import __py_include from io import StringIO -from aiohttp.web import HTTPFound +from aiohttp.web import HTTPFound, HTTPBadRequest from typing import Optional, Union from homekit.config import config, AppConfigUnit, is_development_mode, Translation from homekit.camera import IpcamConfig @@ -30,6 +30,7 @@ class WebKbnConfig(AppConfigUnit): 'listen_addr': cls._addr_schema(required=True), 'assets_public_path': {'type': 'string'}, 'pump_addr': cls._addr_schema(required=True), + 'cam_hls_host': cls._addr_schema(required=True, only_ip=True), 'inverter_grafana_url': {'type': 'string'}, 'sensors_grafana_url': {'type': 'string'}, } @@ -60,9 +61,11 @@ def get_css_link(file, version) -> str: return f'<link rel="stylesheet" type="text/css" href="{config.app_config["assets_public_path"]}/{file}">' -def get_head_static() -> str: +def get_head_static(files=None) -> str: buf = StringIO() - for file in STATIC_FILES: + if files is None: + files = [] + for file in STATIC_FILES+files: v = 2 try: q_ind = file.index('?') @@ -214,12 +217,13 @@ class WebSite(http.HTTPServer): req: http.Request, template_name: str, title: Optional[str] = None, - context: Optional[dict] = None): + context: Optional[dict] = None, + assets: Optional[list] = None): if context is None: context = {} context = { **context, - 'head_static': get_head_static() + 'head_static': get_head_static(assets) } if title is not None: context['title'] = title @@ -363,7 +367,53 @@ class WebSite(http.HTTPServer): context=dict(status=status)) async def cams(self, req: http.Request): - pass + cc = IpcamConfig() + + cam = req.query.get('id', None) + zone = req.query.get('zone', None) + debug_hls = bool(req.query.get('debug_hls', False)) + debug_video_events = bool(req.query.get('debug_video_events', False)) + + if cam is not None: + if not cc.has_camera(int(cam)): + raise ValueError('invalid camera id') + cams = [int(cam)] + mode = {'type': 'single', 'cam': cam} + + elif zone is not None: + if not cc.has_zone(zone): + raise ValueError('invalid zone') + cams = cc['zones'][zone] + mode = {'type': 'zone', 'zone': zone} + + else: + raise HTTPBadRequest(text='no camera id or zone found') + + js_config = { + 'host': config.app_config['cam_hls_host'], + 'proto': 'http', + 'cams': cams, + 'hlsConfig': { + 'opts': { + 'startPosition': -1, + # https://github.com/video-dev/hls.js/issues/3884#issuecomment-842380784 + 'liveSyncDuration': 2, + 'liveMaxLatencyDuration': 3, + 'maxLiveSyncPlaybackRate': 2, + 'liveDurationInfinity': True + }, + 'debugVideoEvents': debug_video_events, + 'debug': debug_hls + } + } + + return await self.render_page(req, 'cams', + title='Камеры', + assets=['hls.js'], + context=dict( + mode=mode, + js_config=js_config, + )) if __name__ == '__main__': |