Add source selection for publication services

This commit is contained in:
Ingo Oppermann 2022-07-11 13:22:25 +02:00
parent 1984b9d12c
commit b9c7bda69e
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
8 changed files with 227 additions and 11 deletions

View File

@ -43,6 +43,7 @@ export default function Control(props) {
props.onChange(settings, false);
};
return (
<Grid container spacing={2}>
{/*

View File

@ -38,6 +38,7 @@ export default function Control(props) {
props.onChange(settings, false);
};
return (
<Grid container spacing={2}>
<Grid item xs={12}>

View File

@ -0,0 +1,97 @@
import React from 'react';
import { Trans } from '@lingui/macro';
import Grid from '@mui/material/Grid';
import MenuItem from '@mui/material/MenuItem';
import Typography from '@mui/material/Typography';
import Select from '../Select';
function init(settings) {
const initSettings = {
source: 'hls+memfs',
...settings,
};
switch (initSettings.source) {
case 'hls+diskfs':
case 'rtmp':
case 'srt':
break;
default:
initSettings.source = 'hls+memfs';
}
return initSettings;
}
export default function Control(props) {
const settings = init(props.settings);
// Set the defaults
React.useEffect(() => {
props.onChange(settings, true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleChange = (what) => (event) => {
const value = event.target.value;
settings[what] = value;
props.onChange(settings, false);
};
const items = [];
if (props.sources.includes('hls+memfs')) {
items.push(
<MenuItem key="hls+memfs" value="hls+memfs">
HLS (memfs)
</MenuItem>
);
}
if (props.sources.includes('hls+diskfs')) {
items.push(
<MenuItem key="hls+diskfs" value="hls+diskfs">
HLS (diskfs)
</MenuItem>
);
}
if (props.sources.includes('rtmp')) {
items.push(
<MenuItem key="rtmp" value="rtmp">
RTMP
</MenuItem>
);
}
if (props.sources.includes('srt')) {
items.push(
<MenuItem key="srt" value="srt">
SRT
</MenuItem>
);
}
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<Select label={<Trans>Source</Trans>} value={settings.source} onChange={handleChange('source')}>
{items}
</Select>
<Typography variant="caption">
<Trans>Stream source for publication service.</Trans>
</Typography>
</Grid>
</Grid>
);
}
Control.defaulProps = {
settings: {},
sources: [],
onChange: function (settings, automatic) {},
};

View File

@ -292,7 +292,7 @@ const defaultEgressMetadata = {
staleTimeout: 30,
},
source: {
source: 'memfs',
source: 'hls+memfs',
},
},
outputs: [],

View File

@ -2393,8 +2393,14 @@ class Restreamer {
// from the inputs only the first is used and only its options are considered.
let address = '';
if (control.source.source === 'memfs') {
if (control.source.source === 'hls+memfs') {
address = `{memfs}/${channel.channelid}.m3u8`;
} else if (control.source.source === 'hls+diskfs') {
address = `{diskfs}/${channel.channelid}.m3u8`;
} else if (control.source.source === 'rtmp') {
address = `{rtmp,name=${channel.channelid}.stream}`;
} else if (control.source.source === 'srt') {
address = `{srt,name=${channel.channelid},mode=request}`;
}
const config = {

View File

@ -144,6 +144,7 @@ export default function Main(props) {
state.onConnect = null;
}
}
if ($metadata.control.rtmp.enable) {
if (!$config.source.network.rtmp.enabled) {
state.state = 'error';

View File

@ -31,6 +31,7 @@ import Paper from '../../misc/Paper';
import PaperHeader from '../../misc/PaperHeader';
import PaperFooter from '../../misc/PaperFooter';
import ProcessControl from '../../misc/controls/Process';
import SourceControl from '../../misc/controls/Source';
import Services from './Services';
import TabPanel from '../../misc/TabPanel';
import TabsVerticalGrid from '../../misc/TabsVerticalGrid';
@ -70,6 +71,7 @@ export default function Add(props) {
const [$service, setService] = React.useState('');
const [$settings, setSettings] = React.useState(M.initEgressMetadata({}));
const [$sources, setSources] = React.useState([]);
const [$localSources, setLocalSources] = React.useState([]);
const [$filter, setFilter] = React.useState('all');
const [$tab, setTab] = React.useState('general');
const [$skills, setSkills] = React.useState(null);
@ -105,6 +107,20 @@ export default function Add(props) {
license: ingest.license,
});
const localSources = [];
localSources.push('hls+' + ingest.control.hls.storage);
if (ingest.control.rtmp.enable) {
localSources.push('rtmp');
}
if (ingest.control.srt.enable) {
localSources.push('srt');
}
setLocalSources(localSources);
setSources(helper.createSourcesFromStreams(ingest.streams));
};
@ -208,12 +224,12 @@ export default function Add(props) {
});
};
const handleProcessControlChange = (control) => {
const handleControlChange = (what) => (control) => {
setSettings({
...$settings,
control: {
...$settings.control,
process: control,
[what]: control,
},
});
};
@ -250,8 +266,6 @@ export default function Add(props) {
let service = {};
const enableProcessing = true;
if ($service === '') {
for (let s of Services.List()) {
if ($filter !== 'all') {
@ -375,7 +389,8 @@ export default function Add(props) {
<Tabs orientation="vertical" variant="scrollable" value={$tab} onChange={handleChangeTab} className="tabs">
<Tab className="tab" label={<Trans>General</Trans>} value="general" />
<Tab className="tab" label={<Trans>Process control</Trans>} value="process" />
{enableProcessing && <Tab className="tab" label={<Trans>Encoding</Trans>} value="encoding" />}
<Tab className="tab" label={<Trans>Source</Trans>} value="source" />
<Tab className="tab" label={<Trans>Encoding</Trans>} value="encoding" />
</Tabs>
<TabPanel value={$tab} index="general" className="panel">
<Grid container spacing={2}>
@ -446,7 +461,48 @@ export default function Add(props) {
</Typography>
</Grid>
<Grid item xs={12}>
<ProcessControl settings={$settings.control.process} onChange={handleProcessControlChange} />
<ProcessControl settings={$settings.control.process} onChange={handleControlChange('process')} />
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography>
<Trans>Maintainer:</Trans>{' '}
<Link color="secondary" target="_blank" href={service.author.creator.link}>
{service.author.maintainer.name}
</Link>
</Typography>
</Grid>
</Grid>
</TabPanel>
<TabPanel value={$tab} index="source" className="panel">
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
<ServiceIcon className={classes.serviceIcon} />
<Stack direction="column" justifyContent="center" alignItems="flex-start" spacing={0}>
<Typography variant="h1" className={classes.serviceName}>
{service.name}
</Typography>
<Typography>v{service.version}</Typography>
</Stack>
</Stack>
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography variant="h2">
<Trans>Source</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<SourceControl
settings={$settings.control.source}
sources={$localSources}
onChange={handleControlChange('source')}
/>
</Grid>
<Grid item xs={12}>
<Divider />

View File

@ -33,6 +33,7 @@ import Process from './Process';
import ProcessControl from '../../misc/controls/Process';
import ProcessModal from '../../misc/modals/Process';
import Services from './Services';
import SourceControl from '../../misc/controls/Source';
import TabPanel from '../../misc/TabPanel';
import TabsVerticalGrid from '../../misc/TabsVerticalGrid';
@ -68,6 +69,7 @@ export default function Edit(props) {
const [$ready, setReady] = React.useState(false);
const [$settings, setSettings] = React.useState(M.getDefaultEgressMetadata());
const [$sources, setSources] = React.useState([]);
const [$localSources, setLocalSources] = React.useState([]);
const [$tab, setTab] = React.useState('general');
const [$progress, setProgress] = React.useState({});
const [$processDetails, setProcessDetails] = React.useState({
@ -145,6 +147,20 @@ export default function Edit(props) {
license: ingest.license,
});
const localSources = [];
localSources.push('hls+' + ingest.control.hls.storage);
if (ingest.control.rtmp.enable) {
localSources.push('rtmp');
}
if (ingest.control.srt.enable) {
localSources.push('srt');
}
setLocalSources(localSources);
const sources = helper.createSourcesFromStreams(ingest.streams);
setSources(sources);
@ -247,12 +263,12 @@ export default function Edit(props) {
setUnsavedChanges(true);
};
const handleProcessControlChange = (control, automatic) => {
const handleControlChange = (what) => (control, automatic) => {
setSettings({
...$settings,
control: {
...$settings.control,
process: control,
[what]: control,
},
});
@ -389,6 +405,7 @@ export default function Edit(props) {
<Tabs orientation="vertical" variant="scrollable" value={$tab} onChange={handleChangeTab} className="tabs">
<Tab className="tab" label={<Trans>General</Trans>} value="general" />
<Tab className="tab" label={<Trans>Process control</Trans>} value="process" />
<Tab className="tab" label={<Trans>Source</Trans>} value="source" />
<Tab className="tab" label={<Trans>Encoding</Trans>} value="encoding" />
</Tabs>
<TabPanel value={$tab} index="general" className="panel">
@ -454,7 +471,7 @@ export default function Edit(props) {
</Typography>
</Grid>
<Grid item xs={12}>
<ProcessControl settings={$settings.control.process} onChange={handleProcessControlChange} />
<ProcessControl settings={$settings.control.process} onChange={handleControlChange('process')} />
</Grid>
<Grid item xs={12}>
<Grid container spacing={1} className={classes.gridContainer}>
@ -497,6 +514,43 @@ export default function Edit(props) {
</Grid>
</Grid>
</TabPanel>
<TabPanel value={$tab} index="source" className="panel">
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
<ServiceIcon className={classes.serviceIcon} />
<Stack direction="column" justifyContent="center" alignItems="flex-start" spacing={0}>
<Typography variant="h1" className={classes.serviceName}>
{$service.name}
</Typography>
<Typography>v{$service.version}</Typography>
</Stack>
</Stack>
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography variant="h2">
<Trans>Source</Trans>
</Typography>
</Grid>
<Grid item xs={12}>
<SourceControl settings={$settings.control.source} sources={$localSources} onChange={handleControlChange('source')} />
</Grid>
<Grid item xs={12}>
<Divider />
</Grid>
<Grid item xs={12}>
<Typography>
<Trans>Maintainer:</Trans>{' '}
<Link color="secondary" target="_blank" href={$service.author.maintainer.link}>
{$service.author.maintainer.name}
</Link>
</Typography>
</Grid>
</Grid>
</TabPanel>
<TabPanel value={$tab} index="encoding" className="panel">
<Grid container spacing={2}>
<Grid item xs={12}>