add recordings
This commit is contained in:
parent
b4a380aba7
commit
f369692133
@ -43,6 +43,7 @@
|
|||||||
"strftime": "0.10.1",
|
"strftime": "0.10.1",
|
||||||
"typescript": "^4.4.2",
|
"typescript": "^4.4.2",
|
||||||
"validator": "^13.9.0",
|
"validator": "^13.9.0",
|
||||||
|
"video.js": "^8.10.0",
|
||||||
"web-vitals": "^2.1.0",
|
"web-vitals": "^2.1.0",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
},
|
},
|
||||||
@ -74,6 +75,7 @@
|
|||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@types/strftime": "^0.9.8",
|
"@types/strftime": "^0.9.8",
|
||||||
"@types/uuid": "^9.0.2",
|
"@types/uuid": "^9.0.2",
|
||||||
|
"@types/video.js": "^7.3.56",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@ const MainBody = observer(() => {
|
|||||||
if (isError) return <RetryError onRetry={refetch} />
|
if (isError) return <RetryError onRetry={refetch} />
|
||||||
|
|
||||||
const cards = () => {
|
const cards = () => {
|
||||||
|
// return cameras.filter(cam => cam.frigateHost?.host.includes('5001')).slice(0,1).map(camera => (
|
||||||
return cameras.map(camera => (
|
return cameras.map(camera => (
|
||||||
<CameraCard
|
<CameraCard
|
||||||
key={camera.id}
|
key={camera.id}
|
||||||
|
|||||||
@ -1,32 +1,175 @@
|
|||||||
// // import { route } from 'preact-router';
|
import MultiSelect from '../shared/components/frigate/MultiSelect';
|
||||||
// import { Fragment, useState, useRef, useCallback, useMemo } from 'react';
|
import StarRecording from '../shared/components/frigate/icons/StarRecording';
|
||||||
// import VideoPlayer from '../shared/components/frigate/VideoPlayer';
|
import Submitted from '../shared/components/frigate/icons/Submitted';
|
||||||
// import CogwheelLoader from '../shared/components/CogwheelLoader';
|
import CalendarIcon from '../shared/components/frigate/icons/CalendarIcon';
|
||||||
// import { Grid, Text } from '@mantine/core';
|
import Menu, { MenuItem } from '../shared/components/frigate/Menu';
|
||||||
// import MultiSelect from '../shared/components/frigate/MultiSelect';
|
import Dialog from '../shared/components/frigate/Dialog';
|
||||||
// import Button from '../shared/components/frigate/Button';
|
import TimelineSummary from '../shared/components/frigate/TimelineSummary';
|
||||||
// import StarRecording from '../shared/components/frigate/icons/StarRecording';
|
import TimelineEventOverlay from '../shared/components/frigate/TimelineEventOverlay';
|
||||||
// import Submitted from '../shared/components/frigate/icons/Submitted';
|
import { Tabs, TextTab } from '../shared/components/frigate/Tabs';
|
||||||
// import CalendarIcon from '../shared/components/frigate/icons/CalendarIcon';
|
import Clock from '../shared/components/frigate/icons/Clock';
|
||||||
// import Menu, { MenuItem } from '../shared/components/frigate/Menu';
|
import TimeAgo from '../shared/components/frigate/TimeAgo';
|
||||||
// import Dialog from '../shared/components/frigate/Dialog';
|
import Camera from '../shared/components/frigate/icons/Camera';
|
||||||
// import TimelineSummary from '../shared/components/frigate/TimelineSummary';
|
import Zone from '../shared/components/frigate/icons/Zone';
|
||||||
// import TimelineEventOverlay from '../shared/components/frigate/TimelineEventOverlay';
|
import Score from '../shared/components/frigate/icons/Score';
|
||||||
// import { Tabs, TextTab } from '../shared/components/frigate/Tabs';
|
import Link from '../shared/components/frigate/Link';
|
||||||
// import Clock from '../shared/components/frigate/icons/Clock';
|
import Delete from '../shared/components/frigate/icons/Delete';
|
||||||
// import TimeAgo from '../shared/components/frigate/TimeAgo';
|
import Download from '../shared/components/frigate/icons/Download';
|
||||||
// import Camera from '../shared/components/frigate/icons/Camera';
|
import { IconDownload, IconStar, IconStarFilled } from '@tabler/icons-react';
|
||||||
// import Zone from '../shared/components/frigate/icons/Zone';
|
// ↑↑↑ from frigate ↑↑↑
|
||||||
// import Score from '../shared/components/frigate/icons/Score';
|
|
||||||
// import Link from '../shared/components/frigate/Link';
|
|
||||||
// import Delete from '../shared/components/frigate/icons/Delete';
|
|
||||||
// import Download from '../shared/components/frigate/icons/Download';
|
|
||||||
|
|
||||||
export default function EventsPage() {
|
import { Fragment, useState, useRef, useCallback, useMemo, useContext, useEffect, lazy, Suspense } from 'react';
|
||||||
|
import VideoPlayer from '../shared/components/frigate/VideoPlayer';
|
||||||
|
import CogwheelLoader from '../shared/components/CogwheelLoader';
|
||||||
|
import { Accordion, Button, Center, Flex, Grid, SelectItem, Text } from '@mantine/core';
|
||||||
|
import { frigateApi, frigateQueryKeys, mapHostToHostname, proxyApi } from '../services/frigate.proxy/frigate.api';
|
||||||
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { Context } from '..';
|
||||||
|
import OneSelectFilter, { OneSelectItem } from '../shared/components/filters.aps/OneSelectFilter';
|
||||||
|
import CenterLoader from '../shared/components/CenterLoader';
|
||||||
|
import RetryError from './RetryError';
|
||||||
|
const CameraAccordion = lazy(() => import('../shared/components/accordion/CameraAccordion'));
|
||||||
|
|
||||||
|
|
||||||
|
const RecordingsPage = observer(() => {
|
||||||
|
const { sideBarsStore } = useContext(Context)
|
||||||
|
const filterData: OneSelectItem[] = [
|
||||||
|
{ value: 'dsfgdfg', label: 'fasdfsdf' },
|
||||||
|
{ value: 'dsfgsfgnjcv', label: 'frteh' },
|
||||||
|
{ value: 'rthsdfgh', label: 'dftghdfgjn' },
|
||||||
|
]
|
||||||
|
const hostSelector = () => (
|
||||||
|
<OneSelectFilter
|
||||||
|
id='dsfgds54'
|
||||||
|
label='HostSelector'
|
||||||
|
spaceBetween='1rem'
|
||||||
|
data={filterData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
useEffect(() => {
|
||||||
|
sideBarsStore.rightVisible = true
|
||||||
|
sideBarsStore.setRightChildren(hostSelector())
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const location = useLocation()
|
||||||
|
const queryParams = new URLSearchParams(location.search)
|
||||||
|
const cameraId = queryParams.get('cameraId');
|
||||||
|
const hostId = queryParams.get('hostId')
|
||||||
|
const date = queryParams.get('date');
|
||||||
|
const time = queryParams.get('time');
|
||||||
|
|
||||||
|
const { data: camera, isPending: cameraPending, isError: cameraError, refetch: cameraRefetch } = useQuery({
|
||||||
|
queryKey: [frigateQueryKeys.getCameraWHost, cameraId],
|
||||||
|
queryFn: async () => {
|
||||||
|
if (cameraId) {
|
||||||
|
return frigateApi.getCameraWHost(cameraId)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const { data: host, isPending: hostPending, isError: hostError, refetch: hostRefetch } = useQuery({
|
||||||
|
queryKey: [frigateQueryKeys.getFrigateHost, hostId],
|
||||||
|
queryFn: async () => {
|
||||||
|
if (hostId) {
|
||||||
|
return frigateApi.getHost(hostId)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const [openCameraId, setOpenCameraId] = useState<string | null>(null)
|
||||||
|
|
||||||
|
const handleOnChange = (cameraId: string | null) => {
|
||||||
|
console.log('Camera id', cameraId)
|
||||||
|
setOpenCameraId(openCameraId === cameraId ? null : cameraId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRetry = () => {
|
||||||
|
if (cameraId) cameraRefetch()
|
||||||
|
else if (hostId) hostRefetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostPending || cameraPending) return <CenterLoader />
|
||||||
|
if (hostError || cameraError) return <RetryError onRetry={handleRetry} />
|
||||||
|
|
||||||
|
|
||||||
|
// Camera selected
|
||||||
|
if (camera && camera.frigateHost) {
|
||||||
|
return (
|
||||||
|
<Flex w='100%' h='100%' direction='column' align='center'>
|
||||||
|
<Text>{camera.frigateHost.name}</Text>
|
||||||
|
<Suspense>
|
||||||
|
<CameraAccordion camera={camera} host={camera.frigateHost} />
|
||||||
|
</Suspense>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Host selected
|
||||||
|
if (host && host.cameras.length > 0) {
|
||||||
|
|
||||||
|
const cameras = host.cameras.map(camera => {
|
||||||
|
return (
|
||||||
|
<Accordion.Item key={camera.id + 'Item'} value={camera.id}>
|
||||||
|
<Accordion.Control key={camera.id + 'Control'}>{camera.name}</Accordion.Control>
|
||||||
|
<Accordion.Panel key={camera.id + 'Panel'}>
|
||||||
|
{openCameraId === camera.id && (
|
||||||
|
<Suspense>
|
||||||
|
<CameraAccordion camera={camera} host={host} />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex w='100%' h='100%' direction='column' align='center'>
|
||||||
|
<Text>{host.name}</Text>
|
||||||
|
<Accordion
|
||||||
|
mt='1rem'
|
||||||
|
variant='separated'
|
||||||
|
radius="md" w='100%'
|
||||||
|
onChange={(value) => handleOnChange(value)}>
|
||||||
|
{cameras}
|
||||||
|
</Accordion>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex w='100%' h='100%' direction='column' justify='center' align='center'>
|
||||||
|
<Text size='xl'>Please select host</Text>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// const videoUrl = proxyApi.eventURL('localhost:5000', event)
|
||||||
|
// const recordUrl = 'http://127.0.0.1:5000/vod/2024-02/22/18/Buhgalteria/Asia,Krasnoyarsk/master.m3u8'
|
||||||
|
// const recordUrl = proxyApi.recordingURL('localhost:5000', 'Buhgalteria', 'Asia,Krasnoyarsk', '2024-02/22/18')
|
||||||
|
// console.log(recordUrl)
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <Flex w='100%' h='100%' direction='column'>
|
||||||
|
// {/* <VideoPlayer videoUrl={recordUrl} /> */}
|
||||||
|
// </Flex>
|
||||||
|
// )
|
||||||
|
|
||||||
|
// seekOptions={{ forward: 10, backward: 5 }}
|
||||||
|
// onReady={handlePlayerReady}
|
||||||
|
// onDispose={onDispose}
|
||||||
|
{/* {eventOverlay ? (
|
||||||
|
<TimelineEventOverlay eventOverlay={eventOverlay} cameraConfig={config.cameras[event.camera]} />
|
||||||
|
) : null} */}
|
||||||
return (
|
return (
|
||||||
<div />
|
<div />
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
export default RecordingsPage
|
||||||
|
|
||||||
// const API_LIMIT = 25;
|
// const API_LIMIT = 25;
|
||||||
|
|
||||||
@ -45,7 +188,7 @@ export default function EventsPage() {
|
|||||||
// export default function Events({ path, ...props }) {
|
// export default function Events({ path, ...props }) {
|
||||||
// // const apiHost = useApiHost();
|
// // const apiHost = useApiHost();
|
||||||
// // const { data: config } = useSWR('config');
|
// // const { data: config } = useSWR('config');
|
||||||
// const timezone = useMemo(() => config?.ui?.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone, [config]);
|
// const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
// const [searchParams, setSearchParams] = useState({
|
// const [searchParams, setSearchParams] = useState({
|
||||||
// before: null,
|
// before: null,
|
||||||
// after: null,
|
// after: null,
|
||||||
@ -284,12 +427,12 @@ export default function EventsPage() {
|
|||||||
// [path, searchParams, setSearchParams]
|
// [path, searchParams, setSearchParams]
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// const onClickFilterSubmitted = useCallback(() => {
|
// // const onClickFilterSubmitted = useCallback(() => {
|
||||||
// if (++searchParams.is_submitted > 1) {
|
// // if (++searchParams.is_submitted > 1) {
|
||||||
// searchParams.is_submitted = -1;
|
// // searchParams.is_submitted = -1;
|
||||||
// }
|
// // }
|
||||||
// onFilter('is_submitted', searchParams.is_submitted);
|
// // onFilter('is_submitted', searchParams.is_submitted);
|
||||||
// }, [searchParams, onFilter]);
|
// // }, [searchParams, onFilter]);
|
||||||
|
|
||||||
// const isDone = (eventPages?.[eventPages.length - 1]?.length ?? 0) < API_LIMIT;
|
// const isDone = (eventPages?.[eventPages.length - 1]?.length ?? 0) < API_LIMIT;
|
||||||
|
|
||||||
@ -405,14 +548,14 @@ export default function EventsPage() {
|
|||||||
// )}
|
// )}
|
||||||
|
|
||||||
// <div className="ml-auto flex">
|
// <div className="ml-auto flex">
|
||||||
// {config.plus.enabled && (
|
// {/* {config.plus.enabled && (
|
||||||
// <Submitted
|
// <Submitted
|
||||||
// className="h-10 w-10 text-yellow-300 cursor-pointer ml-auto"
|
// className="h-10 w-10 text-yellow-300 cursor-pointer ml-auto"
|
||||||
// onClick={() => onClickFilterSubmitted()}
|
// onClick={() => onClickFilterSubmitted()}
|
||||||
// inner_fill={searchParams.is_submitted == 1 ? 'currentColor' : 'gray'}
|
// inner_fill={searchParams.is_submitted == 1 ? 'currentColor' : 'gray'}
|
||||||
// outer_stroke={searchParams.is_submitted >= 0 ? 'currentColor' : 'gray'}
|
// outer_stroke={searchParams.is_submitted >= 0 ? 'currentColor' : 'gray'}
|
||||||
// />
|
// />
|
||||||
// )}
|
// )} */}
|
||||||
|
|
||||||
// <StarRecording
|
// <StarRecording
|
||||||
// className="h-10 w-10 text-yellow-300 cursor-pointer ml-auto"
|
// className="h-10 w-10 text-yellow-300 cursor-pointer ml-auto"
|
||||||
@ -773,14 +916,17 @@ export default function EventsPage() {
|
|||||||
// <div
|
// <div
|
||||||
// className="relative rounded-l flex-initial min-w-[125px] h-[125px] bg-contain bg-no-repeat bg-center"
|
// className="relative rounded-l flex-initial min-w-[125px] h-[125px] bg-contain bg-no-repeat bg-center"
|
||||||
// style={{
|
// style={{
|
||||||
// 'background-image': `url(${apiHost}api/events/${event.id}/thumbnail.jpg)`,
|
// 'backgroundImage': `url(${apiHost}api/events/${event.id}/thumbnail.jpg)`,
|
||||||
// }}
|
// }}
|
||||||
// >
|
// >
|
||||||
// <StarRecording
|
// <IconStar
|
||||||
|
// onClick={(e) => onSave(e, event.id, !event.retain_indefinitely)}
|
||||||
|
// fill={event.retain_indefinitely ? 'yellow' : 'none'} />
|
||||||
|
// {/* <StarRecording
|
||||||
// className="h-6 w-6 text-yellow-300 absolute top-1 right-1 cursor-pointer"
|
// className="h-6 w-6 text-yellow-300 absolute top-1 right-1 cursor-pointer"
|
||||||
// onClick={(e) => onSave(e, event.id, !event.retain_indefinitely)}
|
// onClick={(e) => onSave(e, event.id, !event.retain_indefinitely)}
|
||||||
// fill={event.retain_indefinitely ? 'currentColor' : 'none'}
|
// fill={event.retain_indefinitely ? 'currentColor' : 'none'}
|
||||||
// />
|
// /> */}
|
||||||
// {event.end_time ? null : (
|
// {event.end_time ? null : (
|
||||||
// <div className="bg-slate-300 dark:bg-slate-700 absolute bottom-0 text-center w-full uppercase text-sm rounded-bl">
|
// <div className="bg-slate-300 dark:bg-slate-700 absolute bottom-0 text-center w-full uppercase text-sm rounded-bl">
|
||||||
// In progress
|
// In progress
|
||||||
@ -825,7 +971,7 @@ export default function EventsPage() {
|
|||||||
// : `, ${event.sub_label}: ${(event?.data?.sub_label_score * 100).toFixed(0)}%`}
|
// : `, ${event.sub_label}: ${(event?.data?.sub_label_score * 100).toFixed(0)}%`}
|
||||||
// </div>
|
// </div>
|
||||||
// </div>
|
// </div>
|
||||||
// <div class="hidden sm:flex flex-col justify-end mr-2">
|
// {/* <div class="hidden sm:flex flex-col justify-end mr-2">
|
||||||
// {event.end_time && event.has_snapshot && (event?.data?.type || 'object') == 'object' && (
|
// {event.end_time && event.has_snapshot && (event?.data?.type || 'object') == 'object' && (
|
||||||
// <Fragment>
|
// <Fragment>
|
||||||
// {event.plus_id ? (
|
// {event.plus_id ? (
|
||||||
@ -849,19 +995,11 @@ export default function EventsPage() {
|
|||||||
// )}
|
// )}
|
||||||
// </Fragment>
|
// </Fragment>
|
||||||
// )}
|
// )}
|
||||||
// </div>
|
// </div> */}
|
||||||
// <div class="flex flex-col">
|
// <div className="flex flex-col">
|
||||||
// <Delete
|
// {event.has_clip || event.has_snapshot ?
|
||||||
// className="h-6 w-6 cursor-pointer"
|
// <IconDownload onClick={(e) => onDownloadClick(e, event)} />
|
||||||
// stroke="#f87171"
|
// : <></>}
|
||||||
// onClick={(e) => onDelete(e, event.id, event.retain_indefinitely)}
|
|
||||||
// />
|
|
||||||
|
|
||||||
// <Download
|
|
||||||
// className="h-6 w-6 mt-auto"
|
|
||||||
// stroke={event.has_clip || event.has_snapshot ? '#3b82f6' : '#cbd5e1'}
|
|
||||||
// onClick={(e) => onDownloadClick(e, event)}
|
|
||||||
// />
|
|
||||||
// </div>
|
// </div>
|
||||||
// </div>
|
// </div>
|
||||||
// </div>
|
// </div>
|
||||||
@ -1,7 +1,6 @@
|
|||||||
export const routesPath = {
|
export const routesPath = {
|
||||||
MAIN_PATH: '/',
|
MAIN_PATH: '/',
|
||||||
BIRDSEYE_PATH: '/birdseye',
|
BIRDSEYE_PATH: '/birdseye',
|
||||||
EVENTS_PATH: '/events',
|
|
||||||
RECORDINGS_PATH: '/recordings',
|
RECORDINGS_PATH: '/recordings',
|
||||||
SETTINGS_PATH: '/settings',
|
SETTINGS_PATH: '/settings',
|
||||||
HOSTS_PATH: '/hosts',
|
HOSTS_PATH: '/hosts',
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import HostConfigPage from "../pages/HostConfigPage";
|
|||||||
import HostSystemPage from "../pages/HostSystemPage";
|
import HostSystemPage from "../pages/HostSystemPage";
|
||||||
import HostStoragePage from "../pages/HostStoragePage";
|
import HostStoragePage from "../pages/HostStoragePage";
|
||||||
import LiveCameraPage from "../pages/LiveCameraPage";
|
import LiveCameraPage from "../pages/LiveCameraPage";
|
||||||
|
import RecordingsPage from "../pages/RecordingsPage";
|
||||||
|
|
||||||
interface IRoute {
|
interface IRoute {
|
||||||
path: string,
|
path: string,
|
||||||
@ -30,6 +31,10 @@ export const routes: IRoute[] = [
|
|||||||
path: routesPath.HOSTS_PATH,
|
path: routesPath.HOSTS_PATH,
|
||||||
component: <FrigateHostsPage />,
|
component: <FrigateHostsPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: routesPath.RECORDINGS_PATH,
|
||||||
|
component: <RecordingsPage />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: routesPath.HOST_CONFIG_PATH,
|
path: routesPath.HOST_CONFIG_PATH,
|
||||||
component: <HostConfigPage />,
|
component: <HostConfigPage />,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { z } from "zod"
|
|||||||
import { GetConfig, DeleteFrigateHost, GetFrigateHost, PutConfig, PutFrigateHost, GetFrigateHostWithCameras, GetCameraWHost, GetCameraWHostWConfig } from "./frigate.schema";
|
import { GetConfig, DeleteFrigateHost, GetFrigateHost, PutConfig, PutFrigateHost, GetFrigateHostWithCameras, GetCameraWHost, GetCameraWHostWConfig } from "./frigate.schema";
|
||||||
import { FrigateConfig } from "../../types/frigateConfig";
|
import { FrigateConfig } from "../../types/frigateConfig";
|
||||||
import { url } from "inspector";
|
import { url } from "inspector";
|
||||||
|
import { RecordSummary } from "../../types/record";
|
||||||
|
|
||||||
|
|
||||||
const instanceApi = axios.create({
|
const instanceApi = axios.create({
|
||||||
@ -17,7 +18,7 @@ export const frigateApi = {
|
|||||||
getHosts: () => instanceApi.get<GetFrigateHost[]>('apiv1/frigate-hosts').then(res => {
|
getHosts: () => instanceApi.get<GetFrigateHost[]>('apiv1/frigate-hosts').then(res => {
|
||||||
return res.data
|
return res.data
|
||||||
}),
|
}),
|
||||||
getHostWithCameras: () => instanceApi.get<GetFrigateHostWithCameras[]>('apiv1/frigate-hosts', { params: { include: 'cameras' } }).then(res => {
|
getHostsWithCameras: () => instanceApi.get<GetFrigateHostWithCameras[]>('apiv1/frigate-hosts', { params: { include: 'cameras' } }).then(res => {
|
||||||
return res.data
|
return res.data
|
||||||
}),
|
}),
|
||||||
getHost: (id: string) => instanceApi.get<GetFrigateHostWithCameras>(`apiv1/frigate-hosts/${id}`).then(res => {
|
getHost: (id: string) => instanceApi.get<GetFrigateHostWithCameras>(`apiv1/frigate-hosts/${id}`).then(res => {
|
||||||
@ -34,8 +35,8 @@ export const frigateApi = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const proxyApi = {
|
export const proxyApi = {
|
||||||
getHostConfigRaw: (hostName: string) => instanceApi.get('proxy/api/config/raw', { params: { hostName: hostName } }).then(res => res.data),
|
getHostConfigRaw: (hostName: string) => instanceApi.get(`proxy/${hostName}/api/config/raw`).then(res => res.data),
|
||||||
getHostConfig: (hostName: string) => instanceApi.get('proxy/api/config', { params: { hostName: hostName } }).then(res => res.data),
|
getHostConfig: (hostName: string) => instanceApi.get(`proxy/${hostName}/api/config`).then(res => res.data),
|
||||||
getImageFrigate: async (imageUrl: string) => {
|
getImageFrigate: async (imageUrl: string) => {
|
||||||
const response = await fetch(imageUrl);
|
const response = await fetch(imageUrl);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@ -43,11 +44,59 @@ export const proxyApi = {
|
|||||||
}
|
}
|
||||||
return response.blob();
|
return response.blob();
|
||||||
},
|
},
|
||||||
cameraWsURL: (hostName: string, cameraName: string) => {
|
getHostRestart: (hostName: string) => instanceApi.get(`proxy/${hostName}/api/restart`).then(res => res.data),
|
||||||
return `ws://${proxyURL.host}/proxy-ws/live/jsmpeg/${cameraName}?hostName=${hostName}`
|
|
||||||
},
|
getRecordings: (
|
||||||
cameraImageURL: (hostName: string, cameraName: string) => {
|
hostName: string,
|
||||||
return `http://${proxyURL.host}/proxy/api/${cameraName}/latest.jpg?hostName=${hostName}`
|
cameraName: string,
|
||||||
|
after: number,
|
||||||
|
before: number
|
||||||
|
) =>
|
||||||
|
instanceApi.get(`proxy/${hostName}/api/${cameraName}/recordings?after=${after}&before=${before}`).then(res => res.data),
|
||||||
|
|
||||||
|
getRecordingsSummary: (
|
||||||
|
hostName: string,
|
||||||
|
cameraName: string,
|
||||||
|
timezone: string,
|
||||||
|
) =>
|
||||||
|
instanceApi.get<RecordSummary[]>(`proxy/${hostName}/api/${cameraName}/recordings/summary`, {params: { timezone}}).then(res => res.data),
|
||||||
|
|
||||||
|
getEvents: (
|
||||||
|
hostName: string,
|
||||||
|
camerasName: string[],
|
||||||
|
timezone: string,
|
||||||
|
minScore?: number,
|
||||||
|
maxScore?: number,
|
||||||
|
after?: number,
|
||||||
|
before?: number,
|
||||||
|
labels?: string[],
|
||||||
|
) =>
|
||||||
|
instanceApi.get(`proxy/${hostName}/api/events`, {
|
||||||
|
params: {
|
||||||
|
cameras: camerasName,
|
||||||
|
after: after,
|
||||||
|
timezone: timezone,
|
||||||
|
before: before, // @before the last event start_time in list
|
||||||
|
labels: labels,
|
||||||
|
min_score: minScore,
|
||||||
|
max_score: maxScore,
|
||||||
|
}
|
||||||
|
}).then(res => res.data),
|
||||||
|
|
||||||
|
getEventsSummary: (hostName: string, cameraName: string) =>
|
||||||
|
instanceApi.get(`proxy/${hostName}/api/${cameraName}/events/summary`).then(res => res.data),
|
||||||
|
getEventsInProgress: (hostName: string) => instanceApi.get(`proxy/${hostName}/api/events?in_progress=1&include_thumbnails=0`),
|
||||||
|
cameraWsURL: (hostName: string, cameraName: string) =>
|
||||||
|
`ws://${proxyURL.host}/proxy-ws/${hostName}/live/jsmpeg/${cameraName}`,
|
||||||
|
cameraImageURL: (hostName: string, cameraName: string) =>
|
||||||
|
`${proxyURL.protocol}//${proxyURL.host}/proxy/${hostName}/api/${cameraName}/latest.jpg`,
|
||||||
|
eventURL: (hostName: string, event: string) =>
|
||||||
|
`${proxyURL.protocol}//${proxyURL.host}/proxy/${hostName}/vod/event/${event}/master.m3u8`,
|
||||||
|
// http://127.0.0.1:5000/vod/2024-02/23/19/CameraName/Asia,Krasnoyarsk/master.m3u8
|
||||||
|
recordingURL: (hostName: string, cameraName: string, timezone: string, day: string, hour: string) => {// day:2024-02-23 hour:19
|
||||||
|
const parts = day.split('-')
|
||||||
|
const date = `${parts[0]}-${parts[1]}/${parts[2]}/${hour}`
|
||||||
|
return `${proxyURL.protocol}//${proxyURL.host}/proxy/${hostName}/vod/${date}/${cameraName}/${timezone}/master.m3u8` // todo add Date/Time
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,4 +118,6 @@ export const frigateQueryKeys = {
|
|||||||
getCamerasWHost: 'cameras-frigate-host',
|
getCamerasWHost: 'cameras-frigate-host',
|
||||||
getCameraWHost: 'camera-frigate-host',
|
getCameraWHost: 'camera-frigate-host',
|
||||||
getHostConfig: 'host-config',
|
getHostConfig: 'host-config',
|
||||||
|
getRecordingsSummary: 'recordings-frigate-summary',
|
||||||
|
getRecordings: 'recordings-frigate',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,9 +52,6 @@ const CameraCard = ({
|
|||||||
const handleOpenRecordings = () => {
|
const handleOpenRecordings = () => {
|
||||||
throw Error('Not yet implemented')
|
throw Error('Not yet implemented')
|
||||||
}
|
}
|
||||||
const handleOpenEvents = () => {
|
|
||||||
throw Error('Not yet implemented')
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Grid.Col md={6} lg={3} p='0.2rem'>
|
<Grid.Col md={6} lg={3} p='0.2rem'>
|
||||||
<Card h='100%' radius="lg" padding='0.5rem' className={classes.mainCard}>
|
<Card h='100%' radius="lg" padding='0.5rem' className={classes.mainCard}>
|
||||||
@ -66,7 +63,6 @@ const CameraCard = ({
|
|||||||
className={classes.bottomGroup}>
|
className={classes.bottomGroup}>
|
||||||
<Flex justify='space-evenly' mt='0.5rem' w='100%'>
|
<Flex justify='space-evenly' mt='0.5rem' w='100%'>
|
||||||
<Button size='sm' onClick={handleOpenRecordings}>Recordings</Button>
|
<Button size='sm' onClick={handleOpenRecordings}>Recordings</Button>
|
||||||
<Button size='sm' onClick={handleOpenEvents}>Events</Button>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Group>
|
</Group>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
72
src/shared/components/accordion/CameraAccordion.tsx
Normal file
72
src/shared/components/accordion/CameraAccordion.tsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { Accordion, Center, Text } from '@mantine/core';
|
||||||
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
|
import { GetCameraWHostWConfig, GetFrigateHost } from '../../../services/frigate.proxy/frigate.schema';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { frigateQueryKeys, mapHostToHostname, proxyApi } from '../../../services/frigate.proxy/frigate.api';
|
||||||
|
import CogwheelLoader from '../CogwheelLoader';
|
||||||
|
import DayAccordion from './DayAccordion';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { Context } from '../../..';
|
||||||
|
|
||||||
|
interface CameraAccordionProps {
|
||||||
|
camera: GetCameraWHostWConfig,
|
||||||
|
host: GetFrigateHost
|
||||||
|
}
|
||||||
|
|
||||||
|
const CameraAccordion = observer(({
|
||||||
|
camera,
|
||||||
|
host
|
||||||
|
}: CameraAccordionProps) => {
|
||||||
|
const { recordingsStore } = useContext(Context)
|
||||||
|
|
||||||
|
const { data, isPending, isError } = useQuery({
|
||||||
|
queryKey: [frigateQueryKeys.getRecordingsSummary, camera?.id],
|
||||||
|
queryFn: () => {
|
||||||
|
if (camera && host) {
|
||||||
|
const hostName = mapHostToHostname(host)
|
||||||
|
return proxyApi.getRecordingsSummary(hostName, camera.name, 'Asia/Krasnoyarsk')
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const [openedDay, setOpenedDay] = useState<string | null>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (openedDay) {
|
||||||
|
recordingsStore.playedRecord.cameraName = camera.name
|
||||||
|
const hostName = mapHostToHostname(host)
|
||||||
|
recordingsStore.playedRecord.hostName = hostName
|
||||||
|
}
|
||||||
|
}, [openedDay])
|
||||||
|
|
||||||
|
const handleClick = (value: string | null) => {
|
||||||
|
setOpenedDay(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPending) return (
|
||||||
|
<Center>
|
||||||
|
<Text>Loading...</Text>
|
||||||
|
</Center>
|
||||||
|
)
|
||||||
|
if (isError) return <Text>Loading error</Text>
|
||||||
|
|
||||||
|
if (!data || !camera) return null
|
||||||
|
|
||||||
|
const days = data.map(rec => (
|
||||||
|
<Accordion.Item key={rec.day} value={rec.day}>
|
||||||
|
<Accordion.Control key={rec.day + 'control'}>{rec.day}</Accordion.Control>
|
||||||
|
<Accordion.Panel key={rec.day + 'panel'}>
|
||||||
|
<DayAccordion key={rec.day + 'day'} recordSummary={rec} />
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
|
||||||
|
))
|
||||||
|
return (
|
||||||
|
<Accordion variant='separated' radius="md" w='100%' onChange={handleClick}>
|
||||||
|
{days}
|
||||||
|
</Accordion>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default CameraAccordion;
|
||||||
94
src/shared/components/accordion/DayAccordion.tsx
Normal file
94
src/shared/components/accordion/DayAccordion.tsx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { Accordion, Flex, Group, Text } from '@mantine/core';
|
||||||
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
|
import { RecordHour, RecordSummary, Recording } from '../../../types/record';
|
||||||
|
import Button from '../frigate/Button';
|
||||||
|
import { IconPlayerPause, IconPlayerPlay, IconPlayerStop } from '@tabler/icons-react';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import PlayControl from './PlayControl';
|
||||||
|
import { frigateApi, proxyApi } from '../../../services/frigate.proxy/frigate.api';
|
||||||
|
import { Context } from '../../..';
|
||||||
|
import VideoPlayer from '../frigate/VideoPlayer';
|
||||||
|
|
||||||
|
interface RecordingAccordionProps {
|
||||||
|
recordSummary?: RecordSummary
|
||||||
|
}
|
||||||
|
|
||||||
|
const DayAccordion = observer(({
|
||||||
|
recordSummary
|
||||||
|
}: RecordingAccordionProps) => {
|
||||||
|
const { recordingsStore } = useContext(Context)
|
||||||
|
const [openVideoPlayer, setOpenVideoPlayer] = useState<string>()
|
||||||
|
const [openedValue, setOpenedValue] = useState<string>()
|
||||||
|
const [playerUrl, setPlayerUrl] = useState<string>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (openVideoPlayer) {
|
||||||
|
console.log('openVideoPlayer', openVideoPlayer)
|
||||||
|
if (openVideoPlayer) {
|
||||||
|
recordingsStore.playedRecord.day = recordSummary?.day
|
||||||
|
recordingsStore.playedRecord.hour = openVideoPlayer
|
||||||
|
recordingsStore.playedRecord.timezone = 'Asia,Krasnoyarsk'
|
||||||
|
const parsed = recordingsStore.getFullPlayedRecord(recordingsStore.playedRecord)
|
||||||
|
console.log('recordingsStore.playedRecord: ', recordingsStore.playedRecord)
|
||||||
|
if (parsed.success) {
|
||||||
|
const url = proxyApi.recordingURL(
|
||||||
|
parsed.data.hostName,
|
||||||
|
parsed.data.cameraName,
|
||||||
|
parsed.data.timezone,
|
||||||
|
parsed.data.day,
|
||||||
|
parsed.data.hour
|
||||||
|
)
|
||||||
|
console.log('GET URL: ', url)
|
||||||
|
setPlayerUrl(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
setPlayerUrl(undefined)
|
||||||
|
}
|
||||||
|
}, [openVideoPlayer])
|
||||||
|
|
||||||
|
if (!recordSummary || recordSummary.hours.length < 1) return (<Text>Not have record at that day</Text>)
|
||||||
|
|
||||||
|
const handleOpenPlayer = (hour: string) => {
|
||||||
|
// console.log(`openVideoPlayer day:${recordSummary.day} hour:${hour}`)
|
||||||
|
if (openVideoPlayer !== hour) {
|
||||||
|
setOpenedValue(hour)
|
||||||
|
setOpenVideoPlayer(hour)
|
||||||
|
} else if (openedValue === hour && openVideoPlayer === hour) {
|
||||||
|
setOpenVideoPlayer(undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClick = (value: string) => {
|
||||||
|
if (openedValue === value) {
|
||||||
|
setOpenedValue(undefined)
|
||||||
|
} else {
|
||||||
|
setOpenedValue(value)
|
||||||
|
}
|
||||||
|
setOpenVideoPlayer(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion
|
||||||
|
key={recordSummary.day}
|
||||||
|
variant='separated'
|
||||||
|
radius="md" w='100%'
|
||||||
|
value={openedValue}
|
||||||
|
onChange={handleClick}
|
||||||
|
>
|
||||||
|
{recordSummary.hours.map(hour => (
|
||||||
|
<Accordion.Item key={hour.hour + 'Item'} value={hour.hour}>
|
||||||
|
<Accordion.Control key={hour.hour + 'Control'}>
|
||||||
|
<PlayControl hour={hour.hour} openVideoPlayer={openVideoPlayer} onClick={handleOpenPlayer}/>
|
||||||
|
</Accordion.Control>
|
||||||
|
<Accordion.Panel key={hour.hour + 'Panel'}>
|
||||||
|
{openVideoPlayer === hour.hour ? <VideoPlayer videoUrl={playerUrl} /> : <></>}
|
||||||
|
Events
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
))}
|
||||||
|
</Accordion>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default DayAccordion;
|
||||||
46
src/shared/components/accordion/PlayControl.tsx
Normal file
46
src/shared/components/accordion/PlayControl.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Flex, Group, Text } from '@mantine/core';
|
||||||
|
import { IconPlayerPlay, IconPlayerStop } from '@tabler/icons-react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface PlayControlProps {
|
||||||
|
hour: string,
|
||||||
|
openVideoPlayer?: string,
|
||||||
|
onClick?: (value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlayControl = ({
|
||||||
|
hour,
|
||||||
|
openVideoPlayer,
|
||||||
|
onClick
|
||||||
|
}: PlayControlProps) => {
|
||||||
|
const handleClick = (value: string) => {
|
||||||
|
if (onClick) onClick(value)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Flex justify='space-between'>
|
||||||
|
Hour: {hour}
|
||||||
|
<Group>
|
||||||
|
<Text onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
handleClick(hour)
|
||||||
|
}}>
|
||||||
|
{openVideoPlayer === hour ? 'Stop Video' : 'Play Video'}
|
||||||
|
</Text>
|
||||||
|
{openVideoPlayer === hour ?
|
||||||
|
<IconPlayerStop onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
handleClick(hour)
|
||||||
|
}} />
|
||||||
|
:
|
||||||
|
<IconPlayerPlay onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
handleClick(hour)
|
||||||
|
}} />
|
||||||
|
|
||||||
|
}
|
||||||
|
</Group>
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlayControl;
|
||||||
11
src/shared/components/accordion/TestAccordion.tsx
Normal file
11
src/shared/components/accordion/TestAccordion.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const TestAccordion = ({ camera }: { camera: any }) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
TEST ACCORDION {camera.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TestAccordion;
|
||||||
@ -2,9 +2,18 @@ import { SelectItem, SystemProp, SpacingValue, SelectProps, Box, Flex, CloseButt
|
|||||||
import React, { CSSProperties } from 'react';
|
import React, { CSSProperties } from 'react';
|
||||||
import CloseWithTooltip from '../CloseWithTooltip';
|
import CloseWithTooltip from '../CloseWithTooltip';
|
||||||
import { strings } from '../../strings/strings';
|
import { strings } from '../../strings/strings';
|
||||||
|
|
||||||
|
|
||||||
|
export interface OneSelectItem {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
selected?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface OneSelectFilterProps {
|
interface OneSelectFilterProps {
|
||||||
id: string
|
id: string
|
||||||
data: SelectItem[]
|
data: OneSelectItem[]
|
||||||
spaceBetween?: SystemProp<SpacingValue>
|
spaceBetween?: SystemProp<SpacingValue>
|
||||||
label?: string
|
label?: string
|
||||||
defaultValue?: string
|
defaultValue?: string
|
||||||
|
|||||||
@ -1,100 +0,0 @@
|
|||||||
import { useRef, useEffect } from 'react';
|
|
||||||
import videojs from 'video.js';
|
|
||||||
import 'videojs-playlist';
|
|
||||||
import 'video.js/dist/video-js.css';
|
|
||||||
|
|
||||||
export default function VideoPlayer({
|
|
||||||
children,
|
|
||||||
options,
|
|
||||||
seekOptions = { forward: 30, backward: 10 }, onReady = () => { }, onDispose = () => { }
|
|
||||||
}) {
|
|
||||||
const playerRef = useRef();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const defaultOptions = {
|
|
||||||
controls: true,
|
|
||||||
controlBar: {
|
|
||||||
skipButtons: seekOptions,
|
|
||||||
},
|
|
||||||
playbackRates: [0.5, 1, 2, 4, 8],
|
|
||||||
fluid: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if (!videojs.browser.IS_FIREFOX) {
|
|
||||||
defaultOptions.playbackRates.push(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
const player = videojs(playerRef.current, { ...defaultOptions, ...options }, () => {
|
|
||||||
onReady(player);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Allows player to continue on error
|
|
||||||
player.reloadSourceOnError();
|
|
||||||
|
|
||||||
// Disable fullscreen on iOS if we have children
|
|
||||||
if (
|
|
||||||
children &&
|
|
||||||
videojs.browser.IS_IOS &&
|
|
||||||
videojs.browser.IOS_VERSION > 9 &&
|
|
||||||
!player.el_.ownerDocument.querySelector('.bc-iframe')
|
|
||||||
) {
|
|
||||||
player.tech_.el_.setAttribute('playsinline', 'playsinline');
|
|
||||||
player.tech_.supportsFullScreen = function () {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const screen = window.screen;
|
|
||||||
|
|
||||||
const angle = () => {
|
|
||||||
// iOS
|
|
||||||
if (typeof window.orientation === 'number') {
|
|
||||||
return window.orientation;
|
|
||||||
}
|
|
||||||
// Android
|
|
||||||
if (screen && screen.orientation && screen.orientation.angle) {
|
|
||||||
return window.orientation;
|
|
||||||
}
|
|
||||||
videojs.log('angle unknown');
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const rotationHandler = () => {
|
|
||||||
const currentAngle = angle();
|
|
||||||
|
|
||||||
if (currentAngle === 90 || currentAngle === 270 || currentAngle === -90) {
|
|
||||||
if (player.paused() === false) {
|
|
||||||
player.requestFullscreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((currentAngle === 0 || currentAngle === 180) && player.isFullscreen()) {
|
|
||||||
player.exitFullscreen();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (videojs.browser.IS_IOS) {
|
|
||||||
window.addEventListener('orientationchange', rotationHandler);
|
|
||||||
} else if (videojs.browser.IS_ANDROID && screen.orientation) {
|
|
||||||
// addEventListener('orientationchange') is not a user interaction on Android
|
|
||||||
screen.orientation.onchange = rotationHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (videojs.browser.IS_IOS) {
|
|
||||||
window.removeEventListener('orientationchange', rotationHandler);
|
|
||||||
}
|
|
||||||
player.dispose();
|
|
||||||
onDispose();
|
|
||||||
};
|
|
||||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div data-vjs-player>
|
|
||||||
{/* Setting an empty data-setup is required to override the default values and allow video to be fit the size of its parent */}
|
|
||||||
<video ref={playerRef} className="small-player video-js vjs-default-skin" data-setup="{}" controls playsinline />
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
72
src/shared/components/frigate/VideoPlayer.tsx
Normal file
72
src/shared/components/frigate/VideoPlayer.tsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import videojs from 'video.js';
|
||||||
|
import Player from 'video.js/dist/types/player';
|
||||||
|
import 'video.js/dist/video-js.css'
|
||||||
|
|
||||||
|
interface VideoPlayerProps {
|
||||||
|
videoUrl?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const VideoPlayer = ({ videoUrl }: VideoPlayerProps) => {
|
||||||
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
|
const playerRef = useRef<Player | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const defaultOptions = {
|
||||||
|
preload: 'auto',
|
||||||
|
autoplay: true,
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: videoUrl,
|
||||||
|
type: 'application/vnd.apple.mpegurl',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
controls: true,
|
||||||
|
controlBar: {
|
||||||
|
skipButtons: { forward: 10, backward: 5 },
|
||||||
|
},
|
||||||
|
playbackRates: [0.5, 1, 2, 4, 8],
|
||||||
|
fluid: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!videojs.browser.IS_FIREFOX) {
|
||||||
|
defaultOptions.playbackRates.push(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO add rotations on IOS and android devices
|
||||||
|
|
||||||
|
console.log('playerRef.current', playerRef.current)
|
||||||
|
|
||||||
|
if (videoRef.current) {
|
||||||
|
console.log('mount new player')
|
||||||
|
playerRef.current = videojs(videoRef.current, { ...defaultOptions }, () => {
|
||||||
|
console.log('player is ready');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log('VideoPlayer rendered')
|
||||||
|
return () => {
|
||||||
|
if (playerRef.current !== null) {
|
||||||
|
playerRef.current.dispose();
|
||||||
|
playerRef.current = null;
|
||||||
|
console.log('unmount player')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (playerRef.current) {
|
||||||
|
playerRef.current.src(videoUrl);
|
||||||
|
console.log('player change src')
|
||||||
|
}
|
||||||
|
}, [videoUrl]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div data-vjs-player>
|
||||||
|
{/* Setting an empty data-setup is required to override the default values and allow video to be fit the size of its parent */}
|
||||||
|
<video ref={videoRef} className="small-player video-js vjs-default-skin" data-setup="{}" controls playsInline />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VideoPlayer;
|
||||||
@ -1,7 +1,9 @@
|
|||||||
import { h } from 'preact';
|
import { memo } from 'react';
|
||||||
import { memo } from 'preact/compat';
|
|
||||||
|
|
||||||
export function Download({ className = 'h-6 w-6', stroke = 'currentColor', fill = 'none', onClick = () => {} }) {
|
|
||||||
|
|
||||||
|
|
||||||
|
export function Download({ className = 'h-6 w-6', stroke = 'currentColor', fill = 'none', onClick = () => void }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
33
src/shared/stores/recordings.store.ts
Normal file
33
src/shared/stores/recordings.store.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
export type RecordingPlay = {
|
||||||
|
hostName?: string
|
||||||
|
cameraName?: string
|
||||||
|
hour?: string
|
||||||
|
day?: string
|
||||||
|
timezone?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class RecordingsStore {
|
||||||
|
recordingSchema = z.object({
|
||||||
|
hostName: z.string(),
|
||||||
|
cameraName: z.string(),
|
||||||
|
hour: z.string(),
|
||||||
|
day: z.string(),
|
||||||
|
timezone: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
private _playedRecord: RecordingPlay = {}
|
||||||
|
public get playedRecord(): RecordingPlay {
|
||||||
|
return this._playedRecord
|
||||||
|
}
|
||||||
|
public set playedRecord(value: RecordingPlay) {
|
||||||
|
this._playedRecord = value
|
||||||
|
}
|
||||||
|
|
||||||
|
getFullPlayedRecord(value: RecordingPlay) {
|
||||||
|
return this.recordingSchema.safeParse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import { FiltersStore } from "./filters/filters.store";
|
|||||||
import { ModalStore } from "./modal.store";
|
import { ModalStore } from "./modal.store";
|
||||||
import { OrdersStore } from "./orders.store";
|
import { OrdersStore } from "./orders.store";
|
||||||
import { ProductStore } from "./product.store";
|
import { ProductStore } from "./product.store";
|
||||||
|
import { RecordingsStore } from "./recordings.store";
|
||||||
import { SettingsStore } from "./settings.store";
|
import { SettingsStore } from "./settings.store";
|
||||||
import { SideBarsStore } from "./sidebars.store";
|
import { SideBarsStore } from "./sidebars.store";
|
||||||
import PostStore from "./test.store";
|
import PostStore from "./test.store";
|
||||||
@ -18,6 +19,7 @@ class RootStore {
|
|||||||
categoryStore: CategoryStore
|
categoryStore: CategoryStore
|
||||||
filtersStore: FiltersStore
|
filtersStore: FiltersStore
|
||||||
sideBarsStore: SideBarsStore
|
sideBarsStore: SideBarsStore
|
||||||
|
recordingsStore: RecordingsStore
|
||||||
ordersStore: OrdersStore
|
ordersStore: OrdersStore
|
||||||
settingsStore: SettingsStore
|
settingsStore: SettingsStore
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -29,6 +31,7 @@ class RootStore {
|
|||||||
this.categoryStore = new CategoryStore()
|
this.categoryStore = new CategoryStore()
|
||||||
this.filtersStore = new FiltersStore()
|
this.filtersStore = new FiltersStore()
|
||||||
this.sideBarsStore = new SideBarsStore()
|
this.sideBarsStore = new SideBarsStore()
|
||||||
|
this.recordingsStore = new RecordingsStore()
|
||||||
this.ordersStore = new OrdersStore()
|
this.ordersStore = new OrdersStore()
|
||||||
this.settingsStore = new SettingsStore()
|
this.settingsStore = new SettingsStore()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ export const headerMenu = {
|
|||||||
home:"На главную",
|
home:"На главную",
|
||||||
test:"Тест",
|
test:"Тест",
|
||||||
settings:"Настройки",
|
settings:"Настройки",
|
||||||
|
recordings:"Записи",
|
||||||
acessSettings:" Настройка доступа",
|
acessSettings:" Настройка доступа",
|
||||||
hostsConfig:"Серверы Frigate",
|
hostsConfig:"Серверы Frigate",
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/types/event.ts
Normal file
26
src/types/event.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
export interface Event {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
sub_label?: string;
|
||||||
|
camera: string;
|
||||||
|
start_time: number;
|
||||||
|
end_time?: number;
|
||||||
|
false_positive: boolean;
|
||||||
|
zones: string[];
|
||||||
|
thumbnail: string;
|
||||||
|
has_clip: boolean;
|
||||||
|
has_snapshot: boolean;
|
||||||
|
retain_indefinitely: boolean;
|
||||||
|
plus_id?: string;
|
||||||
|
model_hash?: string;
|
||||||
|
data: {
|
||||||
|
top_score: number;
|
||||||
|
score: number;
|
||||||
|
sub_label_score?: number;
|
||||||
|
region: number[];
|
||||||
|
box: number[];
|
||||||
|
area: number;
|
||||||
|
ratio: number;
|
||||||
|
type: "object" | "audio" | "manual";
|
||||||
|
};
|
||||||
|
}
|
||||||
46
src/types/record.ts
Normal file
46
src/types/record.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
export type Recording = {
|
||||||
|
id: string;
|
||||||
|
camera: string;
|
||||||
|
start_time: number;
|
||||||
|
end_time: number;
|
||||||
|
path: string;
|
||||||
|
segment_size: number;
|
||||||
|
duration: number;
|
||||||
|
motion: number;
|
||||||
|
objects: number;
|
||||||
|
dBFS: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RecordingSegment = {
|
||||||
|
id: string;
|
||||||
|
start_time: number;
|
||||||
|
end_time: number;
|
||||||
|
motion: number;
|
||||||
|
objects: number;
|
||||||
|
segment_size: number;
|
||||||
|
duration: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RecordingActivity = {
|
||||||
|
[hour: number]: RecordingSegmentActivity[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RecordingSegmentActivity = {
|
||||||
|
date: number;
|
||||||
|
count: number;
|
||||||
|
hasObjects: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RecordSummary {
|
||||||
|
day: string
|
||||||
|
events: number
|
||||||
|
hours: RecordHour[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecordHour {
|
||||||
|
duration: number
|
||||||
|
events: number
|
||||||
|
hour: string
|
||||||
|
motion: number
|
||||||
|
objects: number
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ export const testHeaderLinks: HeaderActionProps =
|
|||||||
{link: routesPath.MAIN_PATH, label: headerMenu.home, links: []},
|
{link: routesPath.MAIN_PATH, label: headerMenu.home, links: []},
|
||||||
{link: routesPath.TEST_PATH, label: headerMenu.test, links: []},
|
{link: routesPath.TEST_PATH, label: headerMenu.test, links: []},
|
||||||
{link: routesPath.SETTINGS_PATH, label: headerMenu.settings, links: []},
|
{link: routesPath.SETTINGS_PATH, label: headerMenu.settings, links: []},
|
||||||
|
{link: routesPath.RECORDINGS_PATH, label: headerMenu.recordings, links: []},
|
||||||
{link: routesPath.HOSTS_PATH, label: headerMenu.hostsConfig, links: []},
|
{link: routesPath.HOSTS_PATH, label: headerMenu.hostsConfig, links: []},
|
||||||
{link: routesPath.ROLES_PATH, label: headerMenu.acessSettings, links: []},
|
{link: routesPath.ROLES_PATH, label: headerMenu.acessSettings, links: []},
|
||||||
]
|
]
|
||||||
|
|||||||
205
yarn.lock
205
yarn.lock
@ -1140,6 +1140,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.11"
|
regenerator-runtime "^0.13.11"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.5.5":
|
||||||
|
version "7.23.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
|
||||||
|
integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
"@babel/template@^7.22.5", "@babel/template@^7.3.3":
|
"@babel/template@^7.22.5", "@babel/template@^7.3.3":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
|
||||||
@ -2599,6 +2606,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.17.tgz#0a6d1510395065171e3378a4afc587a3aefa7cc1"
|
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.17.tgz#0a6d1510395065171e3378a4afc587a3aefa7cc1"
|
||||||
integrity sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==
|
integrity sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==
|
||||||
|
|
||||||
|
"@types/video.js@^7.3.56":
|
||||||
|
version "7.3.56"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/video.js/-/video.js-7.3.56.tgz#b66001b64055d58fd49ad69543b0e92b9b850adf"
|
||||||
|
integrity sha512-T3cp/kDuNj8scIzK87u0uomUDKnYQE1uHAA0zFPNGc0qCF3aLxZmMtpWvGxofEPNOpUfvtbsQMvwbjU42q8omw==
|
||||||
|
|
||||||
"@types/ws@^8.5.5":
|
"@types/ws@^8.5.5":
|
||||||
version "8.5.5"
|
version "8.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
|
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
|
||||||
@ -2716,6 +2728,47 @@
|
|||||||
"@typescript-eslint/types" "5.61.0"
|
"@typescript-eslint/types" "5.61.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
|
"@videojs/http-streaming@3.10.0":
|
||||||
|
version "3.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-3.10.0.tgz#b20eaf7246cc014f2715c967a9cdc4240b6e7e61"
|
||||||
|
integrity sha512-Lf1rmhTalV4Gw0bJqHmH4lfk/FlepUDs9smuMtorblAYnqDlE2tbUOb7sBXVYoXGdbWbdTW8jH2cnS+6HWYJ4Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "4.0.0"
|
||||||
|
aes-decrypter "4.0.1"
|
||||||
|
global "^4.4.0"
|
||||||
|
m3u8-parser "^7.1.0"
|
||||||
|
mpd-parser "^1.3.0"
|
||||||
|
mux.js "7.0.2"
|
||||||
|
video.js "^7 || ^8"
|
||||||
|
|
||||||
|
"@videojs/vhs-utils@4.0.0", "@videojs/vhs-utils@^4.0.0":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz#4d4dbf5d61a9fbd2da114b84ec747c3a483bc60d"
|
||||||
|
integrity sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
url-toolkit "^2.2.1"
|
||||||
|
|
||||||
|
"@videojs/vhs-utils@^3.0.5":
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz#665ba70d78258ba1ab977364e2fe9f4d4799c46c"
|
||||||
|
integrity sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
url-toolkit "^2.2.1"
|
||||||
|
|
||||||
|
"@videojs/xhr@2.6.0":
|
||||||
|
version "2.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.6.0.tgz#cd897e0ad54faf497961bcce3fa16dc15a26bb80"
|
||||||
|
integrity sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.5.5"
|
||||||
|
global "~4.4.0"
|
||||||
|
is-function "^1.0.1"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
|
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
|
||||||
version "1.11.6"
|
version "1.11.6"
|
||||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
|
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
|
||||||
@ -2837,6 +2890,11 @@
|
|||||||
"@webassemblyjs/ast" "1.11.6"
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
"@xtuc/long" "4.2.2"
|
"@xtuc/long" "4.2.2"
|
||||||
|
|
||||||
|
"@xmldom/xmldom@^0.8.3":
|
||||||
|
version "0.8.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
|
||||||
|
integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
|
||||||
|
|
||||||
"@xtuc/ieee754@^1.2.0":
|
"@xtuc/ieee754@^1.2.0":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||||
@ -2906,6 +2964,16 @@ adjust-sourcemap-loader@^4.0.0:
|
|||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
regex-parser "^2.2.11"
|
regex-parser "^2.2.11"
|
||||||
|
|
||||||
|
aes-decrypter@4.0.1, aes-decrypter@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/aes-decrypter/-/aes-decrypter-4.0.1.tgz#c1a81d0bde0e96fed0674488d2a31a6d7ab9b7a7"
|
||||||
|
integrity sha512-H1nh/P9VZXUf17AA5NQfJML88CFjVBDuGkp5zDHa7oEhYN9TTpNLJknRY1ie0iSKWlDf6JRnJKaZVDSQdPy6Cg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "^3.0.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
pkcs7 "^1.0.4"
|
||||||
|
|
||||||
agent-base@6:
|
agent-base@6:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||||
@ -4276,6 +4344,11 @@ dom-serializer@^1.0.1:
|
|||||||
domhandler "^4.2.0"
|
domhandler "^4.2.0"
|
||||||
entities "^2.0.0"
|
entities "^2.0.0"
|
||||||
|
|
||||||
|
dom-walk@^0.1.0:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
|
||||||
|
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
|
||||||
|
|
||||||
domelementtype@1:
|
domelementtype@1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||||
@ -5278,6 +5351,14 @@ global-prefix@^3.0.0:
|
|||||||
kind-of "^6.0.2"
|
kind-of "^6.0.2"
|
||||||
which "^1.3.1"
|
which "^1.3.1"
|
||||||
|
|
||||||
|
global@4.4.0, global@^4.3.1, global@^4.4.0, global@~4.4.0:
|
||||||
|
version "4.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
|
||||||
|
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
|
||||||
|
dependencies:
|
||||||
|
min-document "^2.19.0"
|
||||||
|
process "^0.11.10"
|
||||||
|
|
||||||
globals@^11.1.0:
|
globals@^11.1.0:
|
||||||
version "11.12.0"
|
version "11.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||||
@ -5612,6 +5693,11 @@ indent-string@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||||
|
|
||||||
|
individual@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/individual/-/individual-2.0.0.tgz#833b097dad23294e76117a98fb38e0d9ad61bb97"
|
||||||
|
integrity sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==
|
||||||
|
|
||||||
inflight@^1.0.4:
|
inflight@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
@ -5739,6 +5825,11 @@ is-fullwidth-code-point@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||||
|
|
||||||
|
is-function@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
|
||||||
|
integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
|
||||||
|
|
||||||
is-generator-fn@^2.0.0:
|
is-generator-fn@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
||||||
@ -6630,6 +6721,11 @@ jwt-decode@^3.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
|
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
|
||||||
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
|
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
|
||||||
|
|
||||||
|
keycode@2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04"
|
||||||
|
integrity sha512-ps3I9jAdNtRpJrbBvQjpzyFbss/skHqzS+eu4RxKLaEAtFqkjZaB6TZMSivPbLxf4K7VI4SjR0P5mRCX5+Q25A==
|
||||||
|
|
||||||
kind-of@^6.0.2:
|
kind-of@^6.0.2:
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||||
@ -6792,6 +6888,15 @@ lz-string@^1.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
|
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
|
||||||
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
|
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
|
||||||
|
|
||||||
|
m3u8-parser@^7.1.0:
|
||||||
|
version "7.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-7.1.0.tgz#fa92ee22fc798150397c297152c879fe09f066c6"
|
||||||
|
integrity sha512-7N+pk79EH4oLKPEYdgRXgAsKDyA/VCo0qCHlUwacttQA0WqsjZQYmNfywMvjlY9MpEBVZEt0jKFd73Kv15EBYQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "^3.0.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
|
||||||
magic-string@^0.25.0, magic-string@^0.25.7:
|
magic-string@^0.25.0, magic-string@^0.25.7:
|
||||||
version "0.25.9"
|
version "0.25.9"
|
||||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||||
@ -6894,6 +6999,13 @@ mimic-fn@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
|
|
||||||
|
min-document@^2.19.0:
|
||||||
|
version "2.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||||
|
integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==
|
||||||
|
dependencies:
|
||||||
|
dom-walk "^0.1.0"
|
||||||
|
|
||||||
min-indent@^1.0.0:
|
min-indent@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
||||||
@ -6999,6 +7111,16 @@ monaco-yaml@^5.1.1:
|
|||||||
vscode-uri "^3.0.0"
|
vscode-uri "^3.0.0"
|
||||||
yaml "^2.0.0"
|
yaml "^2.0.0"
|
||||||
|
|
||||||
|
mpd-parser@^1.2.2, mpd-parser@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-1.3.0.tgz#38c20f4d73542b4ed554158bc1f0fa571dc61388"
|
||||||
|
integrity sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "^4.0.0"
|
||||||
|
"@xmldom/xmldom" "^0.8.3"
|
||||||
|
global "^4.4.0"
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
@ -7022,6 +7144,14 @@ multicast-dns@^7.2.5:
|
|||||||
dns-packet "^5.2.2"
|
dns-packet "^5.2.2"
|
||||||
thunky "^1.0.2"
|
thunky "^1.0.2"
|
||||||
|
|
||||||
|
mux.js@7.0.2, mux.js@^7.0.1:
|
||||||
|
version "7.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-7.0.2.tgz#410641dc922c5d173d7ce45fbdb2bb9e2a69137c"
|
||||||
|
integrity sha512-CM6+QuyDbc0qW1OfEjkd2+jVKzTXF+z5VOKH0eZxtZtnrG/ilkW/U7l7IXGtBNLASF9sKZMcK1u669cq50Qq0A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.11.2"
|
||||||
|
global "^4.4.0"
|
||||||
|
|
||||||
mz@^2.7.0:
|
mz@^2.7.0:
|
||||||
version "2.7.0"
|
version "2.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||||
@ -7425,6 +7555,13 @@ pirates@^4.0.1, pirates@^4.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
|
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
|
||||||
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
|
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
|
||||||
|
|
||||||
|
pkcs7@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/pkcs7/-/pkcs7-1.0.4.tgz#6090b9e71160dabf69209d719cbafa538b00a1cb"
|
||||||
|
integrity sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.5.5"
|
||||||
|
|
||||||
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||||
@ -8047,6 +8184,11 @@ process-nextick-args@~2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||||
|
|
||||||
|
process@^0.11.10:
|
||||||
|
version "0.11.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||||
|
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
||||||
|
|
||||||
promise@^8.1.0:
|
promise@^8.1.0:
|
||||||
version "8.3.0"
|
version "8.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a"
|
resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a"
|
||||||
@ -8412,6 +8554,11 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.9:
|
|||||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
|
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
|
||||||
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
||||||
|
|
||||||
|
regenerator-runtime@^0.14.0:
|
||||||
|
version "0.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
|
||||||
|
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
|
||||||
|
|
||||||
regenerator-transform@^0.15.1:
|
regenerator-transform@^0.15.1:
|
||||||
version "0.15.1"
|
version "0.15.1"
|
||||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
|
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
|
||||||
@ -8580,6 +8727,13 @@ run-parallel@^1.1.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
rust-result@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rust-result/-/rust-result-1.0.0.tgz#34c75b2e6dc39fe5875e5bdec85b5e0f91536f72"
|
||||||
|
integrity sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==
|
||||||
|
dependencies:
|
||||||
|
individual "^2.0.0"
|
||||||
|
|
||||||
safe-array-concat@^1.0.0:
|
safe-array-concat@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060"
|
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060"
|
||||||
@ -8600,6 +8754,13 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
|
safe-json-parse@4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-4.0.0.tgz#7c0f578cfccd12d33a71c0e05413e2eca171eaac"
|
||||||
|
integrity sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==
|
||||||
|
dependencies:
|
||||||
|
rust-result "^1.0.0"
|
||||||
|
|
||||||
safe-regex-test@^1.0.0:
|
safe-regex-test@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
|
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
|
||||||
@ -9554,6 +9715,11 @@ url-parse@^1.5.3:
|
|||||||
querystringify "^2.1.1"
|
querystringify "^2.1.1"
|
||||||
requires-port "^1.0.0"
|
requires-port "^1.0.0"
|
||||||
|
|
||||||
|
url-toolkit@^2.2.1:
|
||||||
|
version "2.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.2.5.tgz#58406b18e12c58803e14624df5e374f638b0f607"
|
||||||
|
integrity sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==
|
||||||
|
|
||||||
use-callback-ref@^1.3.0:
|
use-callback-ref@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
|
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
|
||||||
@ -9640,6 +9806,45 @@ vary@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||||
|
|
||||||
|
"video.js@^7 || ^8", video.js@^8.10.0:
|
||||||
|
version "8.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/video.js/-/video.js-8.10.0.tgz#603a49909ef33f839264da8b73513f9daf592b57"
|
||||||
|
integrity sha512-7UeG/flj/pp8tNGW8WKPP1VJb3x2FgLoqUWzpZqkoq5YIyf6MNzmIrKtxprl438T5RVkcj+OzV8IX4jYSAn4Sw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/http-streaming" "3.10.0"
|
||||||
|
"@videojs/vhs-utils" "^4.0.0"
|
||||||
|
"@videojs/xhr" "2.6.0"
|
||||||
|
aes-decrypter "^4.0.1"
|
||||||
|
global "4.4.0"
|
||||||
|
keycode "2.2.0"
|
||||||
|
m3u8-parser "^7.1.0"
|
||||||
|
mpd-parser "^1.2.2"
|
||||||
|
mux.js "^7.0.1"
|
||||||
|
safe-json-parse "4.0.0"
|
||||||
|
videojs-contrib-quality-levels "4.0.0"
|
||||||
|
videojs-font "4.1.0"
|
||||||
|
videojs-vtt.js "0.15.5"
|
||||||
|
|
||||||
|
videojs-contrib-quality-levels@4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.0.0.tgz#faa8096594cdbfc3ccbefe8572fc20531ba23f3d"
|
||||||
|
integrity sha512-u5rmd8BjLwANp7XwuQ0Q/me34bMe6zg9PQdHfTS7aXgiVRbNTb4djcmfG7aeSrkpZjg+XCLezFNenlJaCjBHKw==
|
||||||
|
dependencies:
|
||||||
|
global "^4.4.0"
|
||||||
|
|
||||||
|
videojs-font@4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-4.1.0.tgz#3ae1dbaac60b4f0f1c4e6f7ff9662a89df176015"
|
||||||
|
integrity sha512-X1LuPfLZPisPLrANIAKCknZbZu5obVM/ylfd1CN+SsCmPZQ3UMDPcvLTpPBJxcBuTpHQq2MO1QCFt7p8spnZ/w==
|
||||||
|
|
||||||
|
videojs-vtt.js@0.15.5:
|
||||||
|
version "0.15.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz#567776eaf2a7a928d88b148a8b401ade2406f2ca"
|
||||||
|
integrity sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==
|
||||||
|
dependencies:
|
||||||
|
global "^4.3.1"
|
||||||
|
|
||||||
vscode-jsonrpc@8.2.0:
|
vscode-jsonrpc@8.2.0:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9"
|
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user