diff --git a/CHANGELOG.md b/CHANGELOG.md index d019ff3..7b662d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### v1.1.0 > v1.2.0 +- Add audio pan filter - Add video rotation filter ([#347](https://github.com/datarhei/restreamer/discussions/347)) - Add video h/v flip filter - Add audio volume filter ([#313](https://github.com/datarhei/restreamer/issues/313)) @@ -17,9 +18,9 @@ - Add Telegram to publication services (thx Martin Held) - Add Polish translations (thx Robert RykaƂa) - Mod extends the datarhei Core publication service with srt streaming -- Mod Allow decoders and encoders to set global options +- Mod allow decoders and encoders to set global options - Fix player problem with different stream formats (9:16) -- Mod Allow trailing slash on Core address +- Mod allow trailing slash on Core address - Fix process report naming - Fix publication service icon styles - Fix VAAPI encoder diff --git a/src/misc/filters/audio/Pan.js b/src/misc/filters/audio/Pan.js new file mode 100644 index 0000000..a3fabc6 --- /dev/null +++ b/src/misc/filters/audio/Pan.js @@ -0,0 +1,124 @@ +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'; + +// Pan Filter +// https://ffmpeg.org/ffmpeg-filters.html#pan-1 + +function init(initialState) { + const state = { + value: 'none', + ...initialState, + }; + + return state; +} + +function createGraph(settings) { + settings = init(settings); + + const mapping = []; + + switch (settings.value) { + case 'mute_left': + mapping.push('pan=stereo|c1=c1'); + break; + case 'mute_right': + mapping.push('pan=stereo|c0=c0'); + break; + default: + break; + } + + return mapping; +} + +// filter +function Pan(props) { + return ( + + + + Mute a channel. + + + ); +} + +Pan.defaultProps = { + value: '', + onChange: function (event) {}, +}; + +function Filter(props) { + const settings = init(props.settings); + + const handleChange = (newSettings) => { + let automatic = false; + if (!newSettings) { + newSettings = settings; + automatic = true; + } + + props.onChange(newSettings, createGraph(newSettings), automatic); + }; + + const update = (what) => (event) => { + const newSettings = { + ...settings, + }; + + newSettings[what] = event.target.value; + + handleChange(newSettings); + }; + + React.useEffect(() => { + handleChange(null); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + + + + + ); +} + +Filter.defaultProps = { + settings: {}, + onChange: function (settings, graph, automatic) {}, +}; + +const filter = 'pan'; +const name = 'Pan'; +const type = 'audio'; +const hwaccel = false; + +function summarize(settings) { + + + return `${name} (${settings.value.replace(/_/i, " ")})`; +} + +function defaults() { + const settings = init({}); + + return { + settings: settings, + graph: createGraph(settings), + }; +} + +export { name, filter, type, hwaccel, summarize, defaults, createGraph, Filter as component }; diff --git a/src/misc/filters/audio/Volume.js b/src/misc/filters/audio/Volume.js index 145e44f..7e606eb 100644 --- a/src/misc/filters/audio/Volume.js +++ b/src/misc/filters/audio/Volume.js @@ -54,7 +54,6 @@ function VolumeLevel(props) { 70% 80% 90% - 100% Custom ... diff --git a/src/misc/filters/index.js b/src/misc/filters/index.js index eebc322..306ce93 100644 --- a/src/misc/filters/index.js +++ b/src/misc/filters/index.js @@ -2,6 +2,7 @@ import * as AResample from './audio/Resample'; import * as Volume from './audio/Volume'; import * as Loudnorm from './audio/Loudnorm'; +import * as Pan from './audio/Pan'; // Video Filter import * as Transpose from './video/Transpose'; @@ -46,6 +47,7 @@ const audioRegistry = new Registry('audio'); audioRegistry.Register(AResample); audioRegistry.Register(Volume); audioRegistry.Register(Loudnorm); +audioRegistry.Register(Pan); // Video Filters const videoRegistry = new Registry('video');