diff --git a/src/misc/coders/Encoders/video/H264V4L2M2M.js b/src/misc/coders/Encoders/video/H264V4L2M2M.js
index d153eac..6a1796e 100644
--- a/src/misc/coders/Encoders/video/H264V4L2M2M.js
+++ b/src/misc/coders/Encoders/video/H264V4L2M2M.js
@@ -1,15 +1,26 @@
import React from 'react';
+import SemverSatisfies from 'semver/functions/satisfies';
import Grid from '@mui/material/Grid';
+import Typography from '@mui/material/Typography';
+import { Trans } from '@lingui/macro';
+
+import BoxText from '../../../BoxText';
+import TextField from '../../../TextField';
import Video from '../../settings/Video';
function init(initialState) {
const state = {
bitrate: '4096',
fps: '25',
- gop: '2',
+ gop: '4',
profile: 'auto',
+ force_key_frames: 'expr:gte(t,n_forced*1)',
+ num_capture_buffers: '256',
+ num_output_buffers: '512',
+ fps_mode: 'cfr',
+
...initialState,
};
@@ -64,10 +75,20 @@ Codec Controls
4: High
*/
-function createMapping(settings) {
+function createMapping(settings, skills) {
+ let ffversion = 4;
+ if (SemverSatisfies(skills.ffmpeg.version, '^5.0.0')) {
+ ffversion = 5;
+ }
const local = [
'-codec:v',
'h264_v4l2m2m',
+ '-num_capture_buffers',
+ `${settings.num_capture_buffers}`,
+ '-num_output_buffers',
+ `${settings.num_output_buffers}`,
+ '-force_key_frames',
+ `${settings.force_key_frames}`,
'-b:v',
`${settings.bitrate}k`,
'-maxrate',
@@ -78,10 +99,22 @@ function createMapping(settings) {
`${settings.fps}`,
'-pix_fmt',
'yuv420p',
+ '-sc_threshold',
+ '0',
+ '-copyts',
+ '-avoid_negative_ts',
+ 'disabled',
+ '-max_muxing_queue_size',
+ '2048'
];
if (settings.gop !== 'auto') {
- local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`);
+ local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`,);
+ local.push('-keyint_min', `${parseInt(settings.fps)}`);
+ }
+
+ if (ffversion === 5) {
+ local.push('-fps_mode', `${settings.fps_mode}`);
}
if (settings.profile !== 'auto') {
@@ -98,6 +131,10 @@ function createMapping(settings) {
function Coder(props) {
const settings = init(props.settings);
+ let ffversion = 4;
+ if (SemverSatisfies(props.skills.ffmpeg.version, '^5.0.0')) {
+ ffversion = 5;
+ }
const handleChange = (newSettings) => {
let automatic = false;
@@ -106,7 +143,7 @@ function Coder(props) {
automatic = true;
}
- props.onChange(newSettings, createMapping(newSettings), automatic);
+ props.onChange(newSettings, createMapping(newSettings, props.skills), automatic);
};
const update = (what) => (event) => {
@@ -125,6 +162,12 @@ function Coder(props) {
return (
+
+
+ V4L2_M2M is unstable and experimental.
+ For Raspberry Pi (3/4), OMX, which requires a 32-bit operating system, is recommended.
+
+
@@ -133,6 +176,23 @@ function Coder(props) {
+
+ Increasing the HLS segment length by 2-3 * keyframe interval is recommended (Processing & Control.)
+
+
+ {ffversion === 5 && (
+
+
+
+ )}
+
+ Force key framesr} type="text" value={settings.force_key_frames} onChange={update('force_key_frames')} />
+
+
+ Capture buffer} type="number" value={settings.num_capture_buffers} onChange={update('num_capture_buffers')} />
+
+
+ Output buffer} type="number" value={settings.num_output_buffers} onChange={update('num_output_buffers')} />
);