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')} /> );