mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 02:35:22 +03:00
Move player logic back to clips
This commit is contained in:
parent
5d0e4f799d
commit
50e4b82b01
@ -1,19 +1,14 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import Heading from './Heading';
|
|
||||||
import ActivityIndicator from './ActivityIndicator';
|
import ActivityIndicator from './ActivityIndicator';
|
||||||
import { formatUnixTimestampToDateTime } from '../utils/dateUtil';
|
import { formatUnixTimestampToDateTime } from '../utils/dateUtil';
|
||||||
import PlayIcon from '../icons/Play';
|
import PlayIcon from '../icons/Play';
|
||||||
import ExitIcon from '../icons/Exit';
|
import ExitIcon from '../icons/Exit';
|
||||||
import { Zone } from '../icons/Zone';
|
import { Zone } from '../icons/Zone';
|
||||||
import { useState } from 'preact/hooks';
|
import { useState } from 'preact/hooks';
|
||||||
import { useApiHost } from '../api';
|
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
import VideoPlayer from './VideoPlayer';
|
|
||||||
|
|
||||||
export default function TimelineSummary({ event }) {
|
export default function TimelineSummary({ event, onFrameSelected }) {
|
||||||
const apiHost = useApiHost();
|
|
||||||
const eventDuration = event.end_time - event.start_time;
|
|
||||||
const { data: eventTimeline } = useSWR([
|
const { data: eventTimeline } = useSWR([
|
||||||
'timeline',
|
'timeline',
|
||||||
{
|
{
|
||||||
@ -23,16 +18,11 @@ export default function TimelineSummary({ event }) {
|
|||||||
|
|
||||||
const { data: config } = useSWR('config');
|
const { data: config } = useSWR('config');
|
||||||
|
|
||||||
const [timeIndex, setTimeIndex] = useState(0);
|
const [timeIndex, setTimeIndex] = useState(-1);
|
||||||
|
|
||||||
const onSelectMoment = async (index) => {
|
const onSelectMoment = async (index) => {
|
||||||
setTimeIndex(index);
|
setTimeIndex(index);
|
||||||
|
onFrameSelected(eventTimeline[index].timestamp);
|
||||||
if (this.player) {
|
|
||||||
const videoOffset = this.player.duration() - eventDuration;
|
|
||||||
const startTime = videoOffset + (eventTimeline[index].timestamp - event.start_time);
|
|
||||||
this.player.currentTime(startTime);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!eventTimeline || !config) {
|
if (!eventTimeline || !config) {
|
||||||
@ -68,29 +58,6 @@ export default function TimelineSummary({ event }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center">
|
|
||||||
<Heading size="sm">{getTimelineItemDescription(config, eventTimeline[timeIndex], event)}</Heading>
|
|
||||||
<VideoPlayer
|
|
||||||
options={{
|
|
||||||
preload: 'auto',
|
|
||||||
autoplay: false,
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: `${apiHost}vod/event/${event.id}/master.m3u8`,
|
|
||||||
type: 'application/vnd.apple.mpegurl',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
seekOptions={{ forward: 10, backward: 5 }}
|
|
||||||
onReady={(player) => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
onDispose={() => {
|
|
||||||
this.player = null;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -181,6 +181,17 @@ export default function Events({ path, ...props }) {
|
|||||||
onFilter(name, items);
|
onFilter(name, items);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onEventFrameSelected = (event, frameTime) => {
|
||||||
|
const eventDuration = event.end_time - event.start_time;
|
||||||
|
|
||||||
|
if (this.player) {
|
||||||
|
this.player.pause();
|
||||||
|
const videoOffset = this.player.duration() - eventDuration;
|
||||||
|
const startTime = videoOffset + (frameTime - event.start_time);
|
||||||
|
this.player.currentTime(startTime);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const datePicker = useRef();
|
const datePicker = useRef();
|
||||||
|
|
||||||
const downloadButton = useRef();
|
const downloadButton = useRef();
|
||||||
@ -283,7 +294,7 @@ export default function Events({ path, ...props }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEventDetailTabChange = (index) => {
|
const handleEventDetailTabChange = (index) => {
|
||||||
setEventDetailType(index == 0 ? 'clip' : index == 1 ? 'image' : 'timeline');
|
setEventDetailType(index == 0 ? 'clip' : 'image');
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
@ -563,20 +574,22 @@ export default function Events({ path, ...props }) {
|
|||||||
<div className="mx-auto max-w-7xl">
|
<div className="mx-auto max-w-7xl">
|
||||||
<div className="flex justify-center w-full py-2">
|
<div className="flex justify-center w-full py-2">
|
||||||
<Tabs
|
<Tabs
|
||||||
selectedIndex={
|
selectedIndex={event.has_clip && eventDetailType == 'clip' ? 0 : 1}
|
||||||
event.has_clip && eventDetailType == 'clip' ? 0 : eventDetailType == 'timeline' ? 2 : 1
|
|
||||||
}
|
|
||||||
onChange={handleEventDetailTabChange}
|
onChange={handleEventDetailTabChange}
|
||||||
className="justify"
|
className="justify"
|
||||||
>
|
>
|
||||||
<TextTab text="Clip" disabled={!event.has_clip} />
|
<TextTab text="Clip" disabled={!event.has_clip} />
|
||||||
<TextTab text={event.has_snapshot ? 'Snapshot' : 'Thumbnail'} />
|
<TextTab text={event.has_snapshot ? 'Snapshot' : 'Thumbnail'} />
|
||||||
<TextTab text="Timeline" disabled={!event.has_clip} />
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{eventDetailType == 'clip' && event.has_clip ? (
|
{eventDetailType == 'clip' && event.has_clip ? (
|
||||||
|
<div>
|
||||||
|
<TimelineSummary
|
||||||
|
event={event}
|
||||||
|
onFrameSelected={(frameTime) => onEventFrameSelected(event, frameTime)}
|
||||||
|
/>
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
options={{
|
options={{
|
||||||
preload: 'auto',
|
preload: 'auto',
|
||||||
@ -589,8 +602,14 @@ export default function Events({ path, ...props }) {
|
|||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
seekOptions={{ forward: 10, backward: 5 }}
|
seekOptions={{ forward: 10, backward: 5 }}
|
||||||
onReady={() => {}}
|
onReady={(player) => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
onDispose={() => {
|
||||||
|
this.player = null;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{eventDetailType == 'image' || !event.has_clip ? (
|
{eventDetailType == 'image' || !event.has_clip ? (
|
||||||
@ -606,8 +625,6 @@ export default function Events({ path, ...props }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{eventDetailType == 'timeline' ? <TimelineSummary event={event} /> : null}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user