diff --git a/src/misc/filters/audio/Resample.js b/src/misc/filters/audio/Resample.js
new file mode 100644
index 0000000..5cd7e1b
--- /dev/null
+++ b/src/misc/filters/audio/Resample.js
@@ -0,0 +1,224 @@
+import React from 'react';
+
+import { useLingui } from '@lingui/react';
+import { Trans, t } from '@lingui/macro';
+import Grid from '@mui/material/Grid';
+import Typography from '@mui/material/Typography';
+
+import SelectCustom from '../../../misc/SelectCustom';
+
+// Resample Filter
+// https://ffmpeg.org/ffmpeg-filters.html#toc-aresample-1
+
+function init(initialState) {
+ const state = {
+ channels: '2',
+ layout: 'stereo',
+ sampling: '44100',
+ ...initialState,
+ };
+
+ return state;
+}
+
+function createGraph(settings) {
+ const mapping = [];
+
+ const sampling = settings.sampling;
+ const layout = settings.layout;
+
+ if (sampling !== 'inherit') {
+ mapping.push(`osr=${sampling}`);
+ }
+
+ if (layout !== 'inherit') {
+ mapping.push(`ocl=${layout}`);
+ }
+
+ if (mapping.length === 0) {
+ return '';
+ }
+
+ return 'aresample=' + mapping.join(':');
+}
+
+function Layout(props) {
+ const { i18n } = useLingui();
+ const options = [
+ { value: 'mono', label: 'mono' },
+ { value: 'stereo', label: 'stereo' },
+ ];
+
+ if (props.allowAuto === true) {
+ options.unshift({ value: 'auto', label: 'auto' });
+ }
+
+ if (props.allowInherit === true) {
+ options.unshift({ value: 'inherit', label: i18n._(t`Inherit`) });
+ }
+
+ if (props.allowCustom === true) {
+ options.push({ value: 'custom', label: i18n._(t`Custom ...`) });
+ }
+
+ return (
+
+
+
+ The layout of the audio stream.
+
+
+ );
+}
+
+Layout.defaultProps = {
+ variant: 'outlined',
+ allowAuto: false,
+ allowInherit: false,
+ allowCustom: false,
+ label: Layout,
+ customLabel: Custom layout,
+ onChange: function () {},
+};
+
+function Sampling(props) {
+ const { i18n } = useLingui();
+ const options = [
+ { value: '96000', label: '96000 Hz' },
+ { value: '88200', label: '88200 Hz' },
+ { value: '48000', label: '48000 Hz' },
+ { value: '44100', label: '44100 Hz' },
+ { value: '22050', label: '22050 Hz' },
+ { value: '8000', label: '8000 Hz' },
+ ];
+
+ if (props.allowAuto === true) {
+ options.unshift({ value: 'auto', label: 'auto' });
+ }
+
+ if (props.allowInherit === true) {
+ options.unshift({ value: 'inherit', label: i18n._(t`Inherit`) });
+ }
+
+ if (props.allowCustom === true) {
+ options.push({ value: 'custom', label: i18n._(t`Custom ...`) });
+ }
+
+ return (
+
+
+
+ The sample rate of the audio stream.
+
+
+ );
+}
+
+Sampling.defaultProps = {
+ variant: 'outlined',
+ allowAuto: false,
+ allowInherit: false,
+ allowCustom: false,
+ label: Sampling,
+ customLabel: Custom sampling (Hz),
+ onChange: function () {},
+};
+
+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 value = event.target.value;
+
+ const newSettings = {
+ ...settings,
+ [what]: value,
+ };
+
+ if (what === 'layout') {
+ let channels = 2;
+
+ switch (value) {
+ case 'mono':
+ channels = 1;
+ break;
+ case 'stereo':
+ channels = 2;
+ break;
+ default:
+ break;
+ }
+
+ newSettings.channels = channels;
+ }
+
+ handleChange(newSettings);
+ };
+
+ React.useEffect(() => {
+ handleChange(null);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+Filter.defaultProps = {
+ settings: {},
+ onChange: function (settings, mapping) {},
+};
+
+const filter = 'aresample';
+const name = 'Resample';
+const type = 'audio';
+const hwaccel = false;
+
+function summarize(settings) {
+ return `${name} (${settings.layout}, ${settings.sampling}Hz)`;
+}
+
+function defaults() {
+ const settings = init({});
+
+ return {
+ settings: settings,
+ graph: createGraph(settings),
+ };
+}
+
+export { name, filter, type, hwaccel, summarize, defaults, Filter as component };
diff --git a/src/misc/filters/audio/Volume.js b/src/misc/filters/audio/Volume.js
index 06cc660..8aeb750 100644
--- a/src/misc/filters/audio/Volume.js
+++ b/src/misc/filters/audio/Volume.js
@@ -130,12 +130,22 @@ Filter.defaultProps = {
};
const filter = 'volume';
-const name = 'Volume level';
+const name = 'Volume';
const type = 'audio';
const hwaccel = false;
function summarize(settings) {
- return `${name}`;
+ let summary = `${name} (`;
+
+ if (settings.level === 'custom') {
+ summary += `${settings.db}dB`;
+ } else {
+ summary += `${settings.level}%`;
+ }
+
+ summary += ')';
+
+ return summary;
}
function defaults() {
diff --git a/src/misc/filters/index.js b/src/misc/filters/index.js
index f4f0b90..eebc322 100644
--- a/src/misc/filters/index.js
+++ b/src/misc/filters/index.js
@@ -1,4 +1,5 @@
// Audio Filter
+import * as AResample from './audio/Resample';
import * as Volume from './audio/Volume';
import * as Loudnorm from './audio/Loudnorm';
@@ -42,6 +43,7 @@ class Registry {
// Audio Filters
const audioRegistry = new Registry('audio');
+audioRegistry.Register(AResample);
audioRegistry.Register(Volume);
audioRegistry.Register(Loudnorm);
diff --git a/src/misc/filters/video/Transpose.js b/src/misc/filters/video/Transpose.js
index 2c5157b..80eb338 100644
--- a/src/misc/filters/video/Transpose.js
+++ b/src/misc/filters/video/Transpose.js
@@ -100,7 +100,7 @@ const type = 'video';
const hwaccel = false;
function summarize(settings) {
- return `${name}`;
+ return `${name} (${settings.value}° clockwise)`;
}
function defaults() {