mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-26 03:24:43 +00:00
Comskip Update
This commit is contained in:
parent
c76d68f382
commit
f652d2b233
9 changed files with 329 additions and 7 deletions
|
|
@ -170,6 +170,54 @@ export const WebsocketProvider = ({ children }) => {
|
|||
|
||||
// Handle standard message format for other event types
|
||||
switch (parsedEvent.data?.type) {
|
||||
case 'comskip_status': {
|
||||
const rid = parsedEvent.data.recording_id;
|
||||
const id = `comskip-${rid}`;
|
||||
const status = parsedEvent.data.status;
|
||||
const title = parsedEvent.data.title || 'Recording';
|
||||
if (status === 'started') {
|
||||
notifications.show({
|
||||
id,
|
||||
title: 'Removing commercials',
|
||||
message: `Processing ${title}...`,
|
||||
color: 'blue.5',
|
||||
autoClose: false,
|
||||
withCloseButton: false,
|
||||
loading: true,
|
||||
});
|
||||
} else if (status === 'completed') {
|
||||
notifications.update({
|
||||
id,
|
||||
title: 'Commercials removed',
|
||||
message: `${title} — kept ${parsedEvent.data.segments_kept} segments`,
|
||||
color: 'green.5',
|
||||
loading: false,
|
||||
autoClose: 4000,
|
||||
});
|
||||
try { await useChannelsStore.getState().fetchRecordings(); } catch {}
|
||||
} else if (status === 'skipped') {
|
||||
notifications.update({
|
||||
id,
|
||||
title: 'No commercials to remove',
|
||||
message: parsedEvent.data.reason || '',
|
||||
color: 'teal',
|
||||
loading: false,
|
||||
autoClose: 3000,
|
||||
});
|
||||
try { await useChannelsStore.getState().fetchRecordings(); } catch {}
|
||||
} else if (status === 'error') {
|
||||
notifications.update({
|
||||
id,
|
||||
title: 'Comskip failed',
|
||||
message: parsedEvent.data.reason || 'Unknown error',
|
||||
color: 'red',
|
||||
loading: false,
|
||||
autoClose: 6000,
|
||||
});
|
||||
try { await useChannelsStore.getState().fetchRecordings(); } catch {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'epg_file':
|
||||
fetchEPGs();
|
||||
notifications.show({
|
||||
|
|
|
|||
|
|
@ -1668,6 +1668,20 @@ export default class API {
|
|||
}
|
||||
}
|
||||
|
||||
static async runComskip(recordingId) {
|
||||
try {
|
||||
const resp = await request(`${host}/api/channels/recordings/${recordingId}/comskip/`, {
|
||||
method: 'POST',
|
||||
});
|
||||
// Refresh recordings list to reflect comskip status when done later
|
||||
// This endpoint just queues the task; the websocket/refresh will update eventually
|
||||
return resp;
|
||||
} catch (e) {
|
||||
errorNotification('Failed to run comskip', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// DVR Series Rules
|
||||
static async listSeriesRules() {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import useChannelsStore from '../store/channels';
|
|||
import useSettingsStore from '../store/settings';
|
||||
import useVideoStore from '../store/useVideoStore';
|
||||
import RecordingForm from '../components/forms/Recording';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import API from '../api';
|
||||
|
||||
dayjs.extend(duration);
|
||||
|
|
@ -253,6 +254,12 @@ const RecordingDetailsModal = ({ opened, onClose, recording, channel, posterUrl,
|
|||
{onWatchRecording && (
|
||||
<Button size="xs" variant="default" onClick={(e) => { e.stopPropagation?.(); onWatchRecording(); }} disabled={!canWatchRecording}>Watch</Button>
|
||||
)}
|
||||
{customProps.status === 'completed' && (!customProps?.comskip || customProps?.comskip?.status !== 'completed') && (
|
||||
<Button size="xs" variant="light" color="teal" onClick={async (e) => {
|
||||
e.stopPropagation?.();
|
||||
try { await API.runComskip(recording.id); notifications.show({ title: 'Removing commercials', message: 'Queued comskip for this recording', color: 'blue.5', autoClose: 2000 }); } catch {}
|
||||
}}>Remove commercials</Button>
|
||||
)}
|
||||
</Group>
|
||||
</Group>
|
||||
<Text size="sm">{start.format('MMM D, YYYY h:mma')} – {end.format('h:mma')}</Text>
|
||||
|
|
@ -344,6 +351,14 @@ const RecordingCard = ({ recording, category, onOpenDetails }) => {
|
|||
showVideo(fileUrl, 'vod', { name: recordingName, logo: { url: posterUrl } });
|
||||
};
|
||||
|
||||
const handleRunComskip = async (e) => {
|
||||
e?.stopPropagation?.();
|
||||
try {
|
||||
await API.runComskip(recording.id);
|
||||
notifications.show({ title: 'Removing commercials', message: 'Queued comskip for this recording', color: 'blue.5', autoClose: 2000 });
|
||||
} catch {}
|
||||
};
|
||||
|
||||
// Cancel handling for series groups
|
||||
const [cancelOpen, setCancelOpen] = React.useState(false);
|
||||
const [busy, setBusy] = React.useState(false);
|
||||
|
|
@ -494,6 +509,11 @@ const RecordingCard = ({ recording, category, onOpenDetails }) => {
|
|||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isUpcoming && customProps?.status === 'completed' && (!customProps?.comskip || customProps?.comskip?.status !== 'completed') && (
|
||||
<Button size="xs" variant="light" color="teal" onClick={handleRunComskip}>
|
||||
Remove commercials
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
</Stack>
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ const SettingsPage = () => {
|
|||
'dvr-movie-template': '',
|
||||
'dvr-tv-fallback-template': '',
|
||||
'dvr-movie-fallback-template': '',
|
||||
'dvr-comskip-enabled': false,
|
||||
},
|
||||
|
||||
validate: {
|
||||
|
|
@ -422,10 +423,17 @@ const SettingsPage = () => {
|
|||
{authUser.user_level == USER_LEVELS.ADMIN && (
|
||||
<>
|
||||
<Accordion.Item value="dvr-settings">
|
||||
<Accordion.Control>DVR Recording Paths</Accordion.Control>
|
||||
<Accordion.Control>DVR</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<form onSubmit={form.onSubmit(onSubmit)}>
|
||||
<Stack gap="sm">
|
||||
<Switch
|
||||
label="Enable Comskip (remove commercials after recording)"
|
||||
{...form.getInputProps('dvr-comskip-enabled', { type: 'checkbox' })}
|
||||
key={form.key('dvr-comskip-enabled')}
|
||||
id={settings['dvr-comskip-enabled']?.id || 'dvr-comskip-enabled'}
|
||||
name={settings['dvr-comskip-enabled']?.key || 'dvr-comskip-enabled'}
|
||||
/>
|
||||
<TextInput
|
||||
label="TV Path Template"
|
||||
description="Supports {show}, {season}, {episode}, {sub_title}, {channel}, {year}, {start}, {end}. Use format specifiers like {season:02d}. Relative paths are under your library dir."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue