mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-02-14 00:17:05 +01:00
Initial Recordings UI
This commit is contained in:
parent
abbc608ee4
commit
5461308d30
@ -1,9 +1,11 @@
|
|||||||
import base64
|
import base64
|
||||||
import datetime
|
from collections import OrderedDict
|
||||||
|
from datetime import datetime, timedelta
|
||||||
import json
|
import json
|
||||||
import glob
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -449,6 +451,57 @@ def latest_frame(camera_name):
|
|||||||
return "Camera named {} not found".format(camera_name), 404
|
return "Camera named {} not found".format(camera_name), 404
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/<camera_name>/recordings")
|
||||||
|
def recordings(camera_name):
|
||||||
|
files = glob.glob(f"{RECORD_DIR}/*/*/*/{camera_name}")
|
||||||
|
|
||||||
|
if len(files) == 0:
|
||||||
|
return "No recordings found.", 404
|
||||||
|
|
||||||
|
files.sort()
|
||||||
|
|
||||||
|
dates = OrderedDict()
|
||||||
|
for path in files:
|
||||||
|
search = re.search(r".+/(\d{4}[-]\d{2})/(\d{2})/(\d{2}).+", path)
|
||||||
|
if not search:
|
||||||
|
continue
|
||||||
|
date = f"{search.group(1)}-{search.group(2)}"
|
||||||
|
if date not in dates:
|
||||||
|
dates[date] = OrderedDict()
|
||||||
|
dates[date][search.group(3)] = 0
|
||||||
|
|
||||||
|
events = (
|
||||||
|
Event.select(
|
||||||
|
fn.DATE(Event.start_time, "unixepoch", "localtime"),
|
||||||
|
fn.STRFTIME("%H", Event.start_time, "unixepoch", "localtime"),
|
||||||
|
fn.COUNT(Event.id),
|
||||||
|
)
|
||||||
|
.where(Event.camera == camera_name)
|
||||||
|
.group_by(
|
||||||
|
fn.DATE(Event.start_time, "unixepoch", "localtime"),
|
||||||
|
fn.STRFTIME("%H", Event.start_time, "unixepoch", "localtime"),
|
||||||
|
)
|
||||||
|
.tuples()
|
||||||
|
)
|
||||||
|
|
||||||
|
for date, hour, count in events:
|
||||||
|
key = date.strftime("%Y-%m-%d")
|
||||||
|
if key in dates and hour in dates[key]:
|
||||||
|
dates[key][hour] = count
|
||||||
|
|
||||||
|
return jsonify(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"date": date,
|
||||||
|
"recordings": [
|
||||||
|
{"hour": hour, "events": events} for hour, events in hours.items()
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for date, hours in dates.items()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/vod/<path:path>")
|
@bp.route("/vod/<path:path>")
|
||||||
def vod(path):
|
def vod(path):
|
||||||
if not os.path.isdir(f"{RECORD_DIR}/{path}"):
|
if not os.path.isdir(f"{RECORD_DIR}/{path}"):
|
||||||
@ -467,8 +520,13 @@ def vod(path):
|
|||||||
)
|
)
|
||||||
durations.append(duration)
|
durations.append(duration)
|
||||||
|
|
||||||
|
# Should we cache?
|
||||||
|
parts = path.split("/", 4)
|
||||||
|
date = datetime.strptime(f"{parts[0]}-{parts[1]} {parts[2]}", "%Y-%m-%d %H")
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
{
|
{
|
||||||
|
"cache": datetime.now() - timedelta(hours=2) > date,
|
||||||
"discontinuity": False,
|
"discontinuity": False,
|
||||||
"durations": durations,
|
"durations": durations,
|
||||||
"sequences": [{"clips": clips}],
|
"sequences": [{"clips": clips}],
|
||||||
|
@ -39,12 +39,9 @@ http {
|
|||||||
vod_mode mapped;
|
vod_mode mapped;
|
||||||
vod_max_mapping_response_size 1m;
|
vod_max_mapping_response_size 1m;
|
||||||
vod_upstream_location /api;
|
vod_upstream_location /api;
|
||||||
vod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT';
|
|
||||||
vod_last_modified_types *;
|
|
||||||
|
|
||||||
# vod caches
|
# vod caches
|
||||||
vod_metadata_cache metadata_cache 512m;
|
vod_metadata_cache metadata_cache 512m;
|
||||||
vod_response_cache response_cache 128m;
|
|
||||||
vod_mapping_cache mapping_cache 5m;
|
vod_mapping_cache mapping_cache 5m;
|
||||||
|
|
||||||
# gzip manifests
|
# gzip manifests
|
||||||
@ -65,7 +62,7 @@ http {
|
|||||||
add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
|
add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
|
||||||
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
|
add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
|
||||||
add_header Access-Control-Allow-Origin '*';
|
add_header Access-Control-Allow-Origin '*';
|
||||||
expires 100d;
|
expires -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /stream/ {
|
location /stream/ {
|
||||||
|
388
web/package-lock.json
generated
388
web/package-lock.json
generated
@ -2873,7 +2873,6 @@
|
|||||||
"version": "7.12.13",
|
"version": "7.12.13",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz",
|
||||||
"integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==",
|
"integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
}
|
}
|
||||||
@ -4118,6 +4117,74 @@
|
|||||||
"integrity": "sha512-GmVAWB+JuFKqSbzlofYK4qxk955gEv4Kd9/aj2hLOxneXMAm/J7OXcl5DlElS9tmkqwCcxGysSZGOrjzNvmjFQ==",
|
"integrity": "sha512-GmVAWB+JuFKqSbzlofYK4qxk955gEv4Kd9/aj2hLOxneXMAm/J7OXcl5DlElS9tmkqwCcxGysSZGOrjzNvmjFQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@videojs/http-streaming": {
|
||||||
|
"version": "2.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.6.4.tgz",
|
||||||
|
"integrity": "sha512-sFVE0MVXhawAkET8EgiUSMvDDv6u3uGidtO0BvNXG0/qKWlze/zEzhvLsyPU4HmLFRnffKeHK5RE2XpO5vHY8Q==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"@videojs/vhs-utils": "^3.0.0",
|
||||||
|
"aes-decrypter": "3.1.2",
|
||||||
|
"global": "^4.4.0",
|
||||||
|
"m3u8-parser": "4.5.2",
|
||||||
|
"mpd-parser": "0.15.4",
|
||||||
|
"mux.js": "5.10.0",
|
||||||
|
"video.js": "^6 || ^7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@videojs/vhs-utils": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-r8Yas1/tNGsGRNoIaDJuiWiQgM0P2yaEnobgzw5JcBiEqxnS8EXoUm4QtKH7nJtnppZ1yqBx1agBZCvBMKXA2w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"global": "^4.4.0",
|
||||||
|
"url-toolkit": "^2.2.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@videojs/xhr": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-wV9nGESHseSK+S9ePEru2+OJZ1jq/ZbbzniGQ4weAmTIepuBMSYPx5zrxxQA0E786T5ykpO8ts+LayV+3/oI2w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.5.5",
|
||||||
|
"global": "~4.4.0",
|
||||||
|
"is-function": "^1.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||||
@ -4163,6 +4230,28 @@
|
|||||||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"aes-decrypter": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-42nRwfQuPRj9R1zqZBdoxnaAmnIFyDi0MNyTVhjdFOd8fifXKKRfwIHIZ6AMn1or4x5WONzjwRTbTWcsIQ0O4A==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"@videojs/vhs-utils": "^3.0.0",
|
||||||
|
"global": "^4.4.0",
|
||||||
|
"pkcs7": "^1.0.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@ -4763,6 +4852,14 @@
|
|||||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"chainsaw": {
|
||||||
|
"version": "0.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.0.9.tgz",
|
||||||
|
"integrity": "sha1-EaBRAtHEx4W20EFdM21aOhYSkT4=",
|
||||||
|
"requires": {
|
||||||
|
"traverse": ">=0.3.0 <0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@ -5103,6 +5200,11 @@
|
|||||||
"whatwg-url": "^8.0.0"
|
"whatwg-url": "^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"date-fns": {
|
||||||
|
"version": "2.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.21.3.tgz",
|
||||||
|
"integrity": "sha512-HeYdzCaFflc1i4tGbj7JKMjM4cKGYoyxwcIIkHzNgCkX8xXDNJDZXgDDVchIWpN4eQc3lH37WarduXFZJOtxfw=="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||||
@ -5218,6 +5320,11 @@
|
|||||||
"integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==",
|
"integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"desandro-matches-selector": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-cXvu1NwT59jzdi9wem1YpndCGOE="
|
||||||
|
},
|
||||||
"detect-newline": {
|
"detect-newline": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
|
||||||
@ -5271,6 +5378,11 @@
|
|||||||
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==",
|
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dom-walk": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
||||||
|
},
|
||||||
"domconstants": {
|
"domconstants": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/domconstants/-/domconstants-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/domconstants/-/domconstants-0.1.2.tgz",
|
||||||
@ -5964,12 +6076,22 @@
|
|||||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"estree-walker": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
|
||||||
|
},
|
||||||
"esutils": {
|
"esutils": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ev-emitter": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q=="
|
||||||
|
},
|
||||||
"exec-sh": {
|
"exec-sh": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz",
|
||||||
@ -6259,6 +6381,14 @@
|
|||||||
"path-exists": "^4.0.0"
|
"path-exists": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fizzy-ui-utils": {
|
||||||
|
"version": "2.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz",
|
||||||
|
"integrity": "sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==",
|
||||||
|
"requires": {
|
||||||
|
"desandro-matches-selector": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flat-cache": {
|
"flat-cache": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||||
@ -6275,6 +6405,19 @@
|
|||||||
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
|
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"flickity": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/flickity/-/flickity-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-yiPMuP8tw/zN7ARgeSLZNvzK11GkzI2mp/zlYBsyttguSCROAqxj6wiN2sSfPfW3xMG3hcUHxWUXNQMlk/wYcg==",
|
||||||
|
"requires": {
|
||||||
|
"desandro-matches-selector": "^2.0.0",
|
||||||
|
"ev-emitter": "^1.1.1",
|
||||||
|
"fizzy-ui-utils": "^2.0.7",
|
||||||
|
"get-size": "^2.0.3",
|
||||||
|
"unidragger": "^2.3.0",
|
||||||
|
"unipointer": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"for-in": {
|
"for-in": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||||
@ -6385,6 +6528,11 @@
|
|||||||
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
|
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"get-size": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-size/-/get-size-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q=="
|
||||||
|
},
|
||||||
"get-stdin": {
|
"get-stdin": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||||
@ -6435,6 +6583,22 @@
|
|||||||
"is-glob": "^4.0.1"
|
"is-glob": "^4.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"global": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
|
||||||
|
"integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "~0.5.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"process": {
|
||||||
|
"version": "0.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
||||||
|
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
"version": "11.12.0",
|
"version": "11.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||||
@ -6537,6 +6701,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hashish": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
|
||||||
|
"integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
|
||||||
|
"requires": {
|
||||||
|
"traverse": ">=0.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"himalaya": {
|
"himalaya": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz",
|
||||||
@ -6693,6 +6865,11 @@
|
|||||||
"integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
|
"integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"individual": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c="
|
||||||
|
},
|
||||||
"inflight": {
|
"inflight": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
@ -6876,6 +7053,11 @@
|
|||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-function": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
||||||
|
},
|
||||||
"is-generator-fn": {
|
"is-generator-fn": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
|
||||||
@ -8596,6 +8778,11 @@
|
|||||||
"object.assign": "^4.1.2"
|
"object.assign": "^4.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keycode": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
|
||||||
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||||
@ -8757,11 +8944,31 @@
|
|||||||
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
|
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"m3u8-parser": {
|
||||||
|
"version": "4.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.5.2.tgz",
|
||||||
|
"integrity": "sha512-sN/lu3TiRxmG2RFjZxo5c0/7Dr4RrEztl43jXrWwj5gFZ7vfa2iIxGfiPx485dm5QCazaIcKk+vNkUso8Aq0Ag==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"@videojs/vhs-utils": "^3.0.0",
|
||||||
|
"global": "^4.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.25.7",
|
"version": "0.25.7",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
||||||
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
|
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"sourcemap-codec": "^1.4.4"
|
"sourcemap-codec": "^1.4.4"
|
||||||
}
|
}
|
||||||
@ -8856,6 +9063,14 @@
|
|||||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"min-document": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||||
|
"integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
|
||||||
|
"requires": {
|
||||||
|
"dom-walk": "^0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"min-indent": {
|
"min-indent": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||||
@ -8916,6 +9131,28 @@
|
|||||||
"integrity": "sha512-Xm9jdWvqFrlV0k965eY5AlCpWIIUBY2ExzGbEG+byMs+mZI4J7zvaUOLpQ8MTFgkpgyEnu4qUhuZT/Or3QeRiA==",
|
"integrity": "sha512-Xm9jdWvqFrlV0k965eY5AlCpWIIUBY2ExzGbEG+byMs+mZI4J7zvaUOLpQ8MTFgkpgyEnu4qUhuZT/Or3QeRiA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mpd-parser": {
|
||||||
|
"version": "0.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.15.4.tgz",
|
||||||
|
"integrity": "sha512-YcOclxKc5gnT87UQYwRoPJpWOFvQORwN+bXYmTWCJ4U2pCSS7jjtPrIhoOLHFAyekj48CHTX4hjGBV/VSNsUsg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"@videojs/vhs-utils": "^3.0.0",
|
||||||
|
"global": "^4.4.0",
|
||||||
|
"xmldom": "^0.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"global": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||||
|
"requires": {
|
||||||
|
"min-document": "^2.19.0",
|
||||||
|
"process": "^0.11.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
@ -8935,6 +9172,14 @@
|
|||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mux.js": {
|
||||||
|
"version": "5.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.10.0.tgz",
|
||||||
|
"integrity": "sha512-kLzvYsHYBwNa+ckkmpxWV3eImwntJbrwd1KbN4WR0hLe+dK/KB82aCuC0fQzAI2hkjYszdlSGsAWFgYdiFBUuA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.11.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.1.20",
|
"version": "3.1.20",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
||||||
@ -9381,6 +9626,14 @@
|
|||||||
"node-modules-regexp": "^1.0.0"
|
"node-modules-regexp": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pkcs7": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.5.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pkg-dir": {
|
"pkg-dir": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
|
||||||
@ -9743,6 +9996,11 @@
|
|||||||
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
|
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"process": {
|
||||||
|
"version": "0.11.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
|
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
|
||||||
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||||
@ -9971,8 +10229,7 @@
|
|||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.13.7",
|
"version": "0.13.7",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"regenerator-transform": {
|
"regenerator-transform": {
|
||||||
"version": "0.14.5",
|
"version": "0.14.5",
|
||||||
@ -10046,6 +10303,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"remove": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/remove/-/remove-0.1.5.tgz",
|
||||||
|
"integrity": "sha1-CV/9gn1lyfQa2X0z5BanWBEHmVU=",
|
||||||
|
"requires": {
|
||||||
|
"seq": ">= 0.3.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"remove-trailing-separator": {
|
"remove-trailing-separator": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||||
@ -10230,6 +10495,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rollup-plugin-replace": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-/5bxtUPkDHyBJAKketb4NfaeZjL5yLZdeUihSfbF2PQMz+rSTEb8ARKoOl3UBT4m7/X+QOXJo3sLTcq+yMMYTA==",
|
||||||
|
"requires": {
|
||||||
|
"magic-string": "^0.25.2",
|
||||||
|
"rollup-pluginutils": "^2.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-pluginutils": {
|
||||||
|
"version": "2.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
|
||||||
|
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
|
||||||
|
"requires": {
|
||||||
|
"estree-walker": "^0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"rsvp": {
|
"rsvp": {
|
||||||
"version": "4.8.5",
|
"version": "4.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||||
@ -10242,12 +10524,28 @@
|
|||||||
"integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==",
|
"integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"rust-result": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=",
|
||||||
|
"requires": {
|
||||||
|
"individual": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"safe-json-parse": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=",
|
||||||
|
"requires": {
|
||||||
|
"rust-result": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-regex": {
|
"safe-regex": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||||
@ -10490,6 +10788,15 @@
|
|||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"seq": {
|
||||||
|
"version": "0.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq/-/seq-0.3.5.tgz",
|
||||||
|
"integrity": "sha1-rgKvOkJHk9jMvyEtaRdODFTf/jg=",
|
||||||
|
"requires": {
|
||||||
|
"chainsaw": ">=0.0.7 <0.1",
|
||||||
|
"hashish": ">=0.0.2 <0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"set-blocking": {
|
"set-blocking": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||||
@ -10809,8 +11116,7 @@
|
|||||||
"sourcemap-codec": {
|
"sourcemap-codec": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"spdx-correct": {
|
"spdx-correct": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
@ -11291,6 +11597,11 @@
|
|||||||
"punycode": "^2.1.1"
|
"punycode": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"traverse": {
|
||||||
|
"version": "0.3.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
||||||
|
"integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk="
|
||||||
|
},
|
||||||
"ts-morph": {
|
"ts-morph": {
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-9.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-9.1.0.tgz",
|
||||||
@ -11478,6 +11789,14 @@
|
|||||||
"integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==",
|
"integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"unidragger": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unidragger/-/unidragger-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-u+IgG7AG0MXJTKcdzAIYxCm+W5FcnA9M28203Awl6jIcE3/+9OtEyUX4Wv64y7XNKEVRKPot52IV4V6x7FlF5Q==",
|
||||||
|
"requires": {
|
||||||
|
"unipointer": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"union-value": {
|
"union-value": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||||
@ -11490,6 +11809,14 @@
|
|||||||
"set-value": "^2.0.1"
|
"set-value": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"unipointer": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unipointer/-/unipointer-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-m85sAoELCZhogI1owtJV3Dva7GxkHk2lI7A0otw3o0OwCuC/Q9gi7ehddigEYIAYbhkqNdri+dU1QQkrcBvirQ==",
|
||||||
|
"requires": {
|
||||||
|
"ev-emitter": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"uniq": {
|
"uniq": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
|
||||||
@ -11557,6 +11884,11 @@
|
|||||||
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
|
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"url-toolkit": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-l25w6Sy+Iy3/IbogunxhWwljPaDnqpiKvrQRoLBm6DfISco7NyRIS7Zf6+Oxhy1T8kHxWdwLND7ZZba6NjXMug=="
|
||||||
|
},
|
||||||
"use": {
|
"use": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||||
@ -11631,6 +11963,45 @@
|
|||||||
"extsprintf": "^1.2.0"
|
"extsprintf": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"video.js": {
|
||||||
|
"version": "7.11.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.11.8.tgz",
|
||||||
|
"integrity": "sha512-iQmNYB+pdgu8b45Za1AKSa5J7uDyHIqfJy+picw4voKfjErXK/BEvs+A3f99Ck7SCZU4cmMmX/s17AwaaNs+1w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.9.2",
|
||||||
|
"@videojs/http-streaming": "2.6.4",
|
||||||
|
"@videojs/xhr": "2.5.1",
|
||||||
|
"global": "4.3.2",
|
||||||
|
"keycode": "^2.2.0",
|
||||||
|
"remove": "^0.1.5",
|
||||||
|
"rollup-plugin-replace": "^2.2.0",
|
||||||
|
"safe-json-parse": "4.0.0",
|
||||||
|
"videojs-font": "3.2.0",
|
||||||
|
"videojs-vtt.js": "^0.15.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"videojs-font": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA=="
|
||||||
|
},
|
||||||
|
"videojs-playlist": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-playlist/-/videojs-playlist-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-fxI3T6mWHKaXRwTQyJeq5I0b8GM9Q4S/p92Aq7O1xAT+X8jYxYSIN15xi32a1F5adEGPRqct+yMl5MkXO9x9cQ==",
|
||||||
|
"requires": {
|
||||||
|
"global": "^4.3.2",
|
||||||
|
"video.js": "^6 || ^7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"videojs-vtt.js": {
|
||||||
|
"version": "0.15.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.3.tgz",
|
||||||
|
"integrity": "sha512-5FvVsICuMRx6Hd7H/Y9s9GDeEtYcXQWzGMS+sl4UX3t/zoHp3y+isSfIPRochnTH7h+Bh1ILyC639xy9Z6kPag==",
|
||||||
|
"requires": {
|
||||||
|
"global": "^4.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"w3c-hr-time": {
|
"w3c-hr-time": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
|
||||||
@ -11784,6 +12155,11 @@
|
|||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"xmldom": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA=="
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
@ -11,11 +11,15 @@
|
|||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"date-fns": "^2.21.3",
|
||||||
|
"flickity": "^2.2.2",
|
||||||
"idb-keyval": "^5.0.2",
|
"idb-keyval": "^5.0.2",
|
||||||
"immer": "^8.0.1",
|
"immer": "^8.0.1",
|
||||||
"preact": "^10.5.9",
|
"preact": "^10.5.9",
|
||||||
"preact-async-route": "^2.2.1",
|
"preact-async-route": "^2.2.1",
|
||||||
"preact-router": "^3.2.1"
|
"preact-router": "^3.2.1",
|
||||||
|
"video.js": "^7.11.8",
|
||||||
|
"videojs-playlist": "^4.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.12.13",
|
"@babel/eslint-parser": "^7.12.13",
|
||||||
|
@ -29,6 +29,7 @@ export default function App() {
|
|||||||
<AsyncRoute path="/cameras/:camera" getComponent={Routes.getCamera} />
|
<AsyncRoute path="/cameras/:camera" getComponent={Routes.getCamera} />
|
||||||
<AsyncRoute path="/events/:eventId" getComponent={Routes.getEvent} />
|
<AsyncRoute path="/events/:eventId" getComponent={Routes.getEvent} />
|
||||||
<AsyncRoute path="/events" getComponent={Routes.getEvents} />
|
<AsyncRoute path="/events" getComponent={Routes.getEvents} />
|
||||||
|
<AsyncRoute path="/recordings/:camera/:date?/:hour?" getComponent={Routes.getRecording} />
|
||||||
<AsyncRoute path="/debug" getComponent={Routes.getDebug} />
|
<AsyncRoute path="/debug" getComponent={Routes.getDebug} />
|
||||||
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
|
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
|
||||||
<Cameras default path="/" />
|
<Cameras default path="/" />
|
||||||
|
@ -27,6 +27,19 @@ export default function Sidebar() {
|
|||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
</Match>
|
</Match>
|
||||||
|
<Match path="/recordings/:camera/:date?/:hour?">
|
||||||
|
{({ matches }) =>
|
||||||
|
matches ? (
|
||||||
|
<Fragment>
|
||||||
|
<Separator />
|
||||||
|
{cameras.map((camera) => (
|
||||||
|
<Destination href={`/recordings/${camera}`} text={camera} />
|
||||||
|
))}
|
||||||
|
<Separator />
|
||||||
|
</Fragment>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</Match>
|
||||||
<Destination href="/events" text="Events" />
|
<Destination href="/events" text="Events" />
|
||||||
<Destination href="/debug" text="Debug" />
|
<Destination href="/debug" text="Debug" />
|
||||||
<Separator />
|
<Separator />
|
||||||
|
@ -110,6 +110,11 @@ export function useEvent(eventId, fetchId) {
|
|||||||
return useFetch(url, fetchId);
|
return useFetch(url, fetchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useRecording(camera, fetchId) {
|
||||||
|
const url = `/api/${camera}/recordings`;
|
||||||
|
return useFetch(url, fetchId);
|
||||||
|
}
|
||||||
|
|
||||||
export function useConfig(searchParams, fetchId) {
|
export function useConfig(searchParams, fetchId) {
|
||||||
const url = `/api/config${searchParams ? `?${searchParams.toString()}` : ''}`;
|
const url = `/api/config${searchParams ? `?${searchParams.toString()}` : ''}`;
|
||||||
return useFetch(url, fetchId);
|
return useFetch(url, fetchId);
|
||||||
|
@ -66,7 +66,7 @@ export default function Button({
|
|||||||
|
|
||||||
let classes = `whitespace-nowrap flex items-center space-x-1 ${className} ${ButtonTypes[type]} ${
|
let classes = `whitespace-nowrap flex items-center space-x-1 ${className} ${ButtonTypes[type]} ${
|
||||||
ButtonColors[disabled ? 'disabled' : color][type]
|
ButtonColors[disabled ? 'disabled' : color][type]
|
||||||
} font-sans inline-flex font-bold uppercase text-xs px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
|
} font-sans inline-flex font-bold uppercase text-xs px-1.5 md:px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
|
||||||
disabled ? 'cursor-not-allowed' : 'focus:ring-2 cursor-pointer'
|
disabled ? 'cursor-not-allowed' : 'focus:ring-2 cursor-pointer'
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
26
web/src/components/Calendar.jsx
Normal file
26
web/src/components/Calendar.jsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
|
export default function Calendar({ date, hours = 0, events = 0, selected = false }) {
|
||||||
|
const bg = selected ? 'bg-blue-500 bg-opacity-80' : 'bg-gray-500';
|
||||||
|
return (
|
||||||
|
<div className="min-w-20 min-h-20 md:min-w-32 md:min-h-32 p-1.5 mb-1 font-medium text-xs md:text-base">
|
||||||
|
<div className="w-20 md:w-32 flex-none rounded-lg text-center shadow-md">
|
||||||
|
<div className="block rounded-lg overflow-hidden text-center text-black">
|
||||||
|
<div className={`${bg} text-white py-0.5`}>{format(date, 'MMM yyyy')}</div>
|
||||||
|
<div className="pt-0.5 bg-white">
|
||||||
|
<span className="text-2xl md:text-5xl font-bold leading-tight">{format(date, 'd')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-center bg-white pt-0.5">
|
||||||
|
<span className="md:text-sm">{format(date, 'EEEE')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="pb-0.5 border-l border-r border-b border-white text-center bg-white hidden md:block">
|
||||||
|
<span className="md:text-xs leading-normal">
|
||||||
|
{hours} hrs, {events} events
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
65
web/src/components/Carousel.jsx
Normal file
65
web/src/components/Carousel.jsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
import Flickity from 'flickity';
|
||||||
|
import 'flickity/css/flickity.css';
|
||||||
|
|
||||||
|
export default class Carousel extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.carousel = null;
|
||||||
|
this.flkty = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
if (this.carousel) {
|
||||||
|
this.flkty = new Flickity(this.carousel, this.props.options);
|
||||||
|
|
||||||
|
if (this.props.flickityRef) {
|
||||||
|
this.props.flickityRef(this.flkty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
if (this.flkty) {
|
||||||
|
this.flkty.destroy();
|
||||||
|
this.flkty = null;
|
||||||
|
this.carousel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUpdate() {
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(props) {
|
||||||
|
return h(
|
||||||
|
this.props.elementType,
|
||||||
|
{
|
||||||
|
className: this.props.className,
|
||||||
|
ref: (c) => {
|
||||||
|
this.carousel = c;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
this.props.children
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Carousel.defaultProps = {
|
||||||
|
options: {},
|
||||||
|
className: '',
|
||||||
|
elementType: 'div',
|
||||||
|
};
|
51
web/src/components/VideoPlayer.jsx
Normal file
51
web/src/components/VideoPlayer.jsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
import videojs from 'video.js';
|
||||||
|
import 'videojs-playlist';
|
||||||
|
import 'video.js/dist/video-js.css';
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
controls: true,
|
||||||
|
fluid: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class VideoPlayer extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
const { options, onReady = () => {} } = this.props;
|
||||||
|
const videoJsOptions = {
|
||||||
|
...defaultOptions,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
const self = this;
|
||||||
|
this.player = videojs(this.videoNode, videoJsOptions, function onPlayerReady() {
|
||||||
|
onReady(this);
|
||||||
|
this.on('error', () => {
|
||||||
|
console.error('VIDEOJS: ERROR: currentSources:', this.currentSources());
|
||||||
|
});
|
||||||
|
this.on('play', () => {
|
||||||
|
console.log('VIDEOJS: currentSources:', this.currentSources());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.player) {
|
||||||
|
this.player.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { style } = this.props;
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<div data-vjs-player>
|
||||||
|
<video playsinline ref={(node) => (this.videoNode = node)} className="video-js" />
|
||||||
|
<div className="vjs-playlist" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -28,7 +28,10 @@ function Camera({ name }) {
|
|||||||
const { payload: clipValue, send: sendClips } = useClipsState(name);
|
const { payload: clipValue, send: sendClips } = useClipsState(name);
|
||||||
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
||||||
const href = `/cameras/${name}`;
|
const href = `/cameras/${name}`;
|
||||||
const buttons = useMemo(() => [{ name: 'Events', href: `/events?camera=${name}` }], [name]);
|
const buttons = useMemo(() => [
|
||||||
|
{ name: 'Events', href: `/events?camera=${name}` },
|
||||||
|
{ name: 'Recordings', href: `/recordings/${name}` }
|
||||||
|
], [name]);
|
||||||
const icons = useMemo(
|
const icons = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
|
114
web/src/routes/Recording.jsx
Normal file
114
web/src/routes/Recording.jsx
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import { Link } from 'preact-router/match';
|
||||||
|
import { closestTo, format, isEqual, parseISO } from 'date-fns';
|
||||||
|
import ActivityIndicator from '../components/ActivityIndicator';
|
||||||
|
import Button from '../components/Button';
|
||||||
|
import Calendar from '../components/Calendar';
|
||||||
|
import Carousel from '../components/Carousel';
|
||||||
|
import Heading from '../components/Heading';
|
||||||
|
import VideoPlayer from '../components/VideoPlayer';
|
||||||
|
import { FetchStatus, useApiHost, useRecording } from '../api';
|
||||||
|
|
||||||
|
export default function Recording({ camera, date, hour }) {
|
||||||
|
const apiHost = useApiHost();
|
||||||
|
const { data, status } = useRecording(camera);
|
||||||
|
|
||||||
|
if (status !== FetchStatus.LOADED) {
|
||||||
|
return <ActivityIndicator />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const recordingDates = data.map((item) => item.date);
|
||||||
|
const selectedDate = closestTo(
|
||||||
|
date ? parseISO(date) : new Date(),
|
||||||
|
recordingDates.map((i) => parseISO(i))
|
||||||
|
);
|
||||||
|
const selectedKey = format(selectedDate, 'yyyy-MM-dd');
|
||||||
|
const [year, month, day] = selectedKey.split('-');
|
||||||
|
const calendar = [];
|
||||||
|
const buttons = [];
|
||||||
|
const playlist = [];
|
||||||
|
const hours = [];
|
||||||
|
|
||||||
|
for (const item of data) {
|
||||||
|
const date = parseISO(item.date);
|
||||||
|
const events = item.recordings.map((i) => i.events);
|
||||||
|
calendar.push(
|
||||||
|
<Link href={`/recordings/${camera}/${item.date}`}>
|
||||||
|
<Calendar
|
||||||
|
date={date}
|
||||||
|
hours={events.length}
|
||||||
|
events={events.reduce((a, b) => a + b)}
|
||||||
|
selected={isEqual(selectedDate, date)}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (item.date == selectedKey) {
|
||||||
|
for (const recording of item.recordings) {
|
||||||
|
buttons.push(
|
||||||
|
<Button href={`/recordings/${camera}/${item.date}/${recording.hour}`} type="text">
|
||||||
|
{recording.hour}:00
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
playlist.push({
|
||||||
|
name: `${selectedKey} ${recording.hour}:00`,
|
||||||
|
description: `${camera} recording @ ${recording.hour}:00.`,
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: `${apiHost}/vod/${year}-${month}/${day}/${recording.hour}/${camera}/index.m3u8`,
|
||||||
|
type: 'application/vnd.apple.mpegurl',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
hours.push(recording.hour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedHour = hours.indexOf(hour);
|
||||||
|
|
||||||
|
if (this.player !== undefined) {
|
||||||
|
this.player.playlist([]);
|
||||||
|
this.player.playlist(playlist);
|
||||||
|
this.player.playlist.autoadvance(0);
|
||||||
|
if (selectedHour !== -1) {
|
||||||
|
this.player.playlist.currentItem(selectedHour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectDate = (flkty) => {
|
||||||
|
flkty.select(recordingDates.indexOf(selectedKey), false, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectHour = (flkty) => {
|
||||||
|
flkty.select(selectedHour, false, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<Heading>{camera} Recordings</Heading>
|
||||||
|
|
||||||
|
<Carousel flickityRef={selectDate} options={{ pageDots: false }}>
|
||||||
|
{calendar}
|
||||||
|
</Carousel>
|
||||||
|
|
||||||
|
<VideoPlayer
|
||||||
|
date={selectedKey}
|
||||||
|
onReady={(player) => {
|
||||||
|
if (player.playlist) {
|
||||||
|
player.playlist(playlist);
|
||||||
|
player.playlist.autoadvance(0);
|
||||||
|
if (selectedHour !== -1) {
|
||||||
|
player.playlist.currentItem(selectedHour);
|
||||||
|
}
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Carousel flickityRef={selectHour} options={{ pageDots: false }}>
|
||||||
|
{buttons}
|
||||||
|
</Carousel>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -18,6 +18,11 @@ export async function getEvents(url, cb, props) {
|
|||||||
return module.default;
|
return module.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getRecording(url, cb, props) {
|
||||||
|
const module = await import('./Recording.jsx');
|
||||||
|
return module.default;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getDebug(url, cb, props) {
|
export async function getDebug(url, cb, props) {
|
||||||
const module = await import('./Debug.jsx');
|
const module = await import('./Debug.jsx');
|
||||||
return module.default;
|
return module.default;
|
||||||
|
Loading…
Reference in New Issue
Block a user