I am generating a large collection MP4 videos from an OpenGL source. This has worked perfectly so far but I recently noticed that some TV media player don't like video without audio, see here for more info.
So far i hve been using the following code:
private bool StartRecording()
{
_ffmpeg = new Process();
_ffmpeg.StartInfo.FileName = "ffmpeg.exe";
_ffmpeg.StartInfo.Arguments = $"-f rawvideo -pix_fmt rgba -s {RecordSize.Width}x{RecordSize.Height} -r 30 -i - -c libx264 -crf 17 -pix_fmt yuv420p -b:v 1024k -bufsize:v 1835008 {RecordFile} -tune animation";
_ffmpeg.StartInfo.RedirectStandardInput = true;
_ffmpeg.Start();
if(_ffmpeg.HasExited)
{
IsRecording = false;
return false;
}
return true;
}
private void RecordFrame(RenderUpdate update)
{
if (_ffmpeg == null)
return;
var frame = Project.RecordFrame(update);
var data = new byte[frame.Length];
var height = RecordSize.Height;
var width = RecordSize.Width;
for (var k = 0; k < height; k++)
{
var j = height - k - 1;
Buffer.BlockCopy(
frame, k * width * 4,
data, j * width * 4,
width * 4);
}
_ffmpeg.StandardInput.BaseStream.Write(data, 0, data.Length);
}
private void StopRecording()
{
Project.StopRecording();
if (_ffmpeg == null)
return;
_ffmpeg.StandardInput.Flush();
_ffmpeg.StandardInput.Close();
_ffmpeg.Close();
_ffmpeg.Dispose();
}
And it has worked perfectly until I modified the 'ffmpeg' cmd line arguments to include '-i anullsrc' for the audio.
_ffmpeg.StartInfo.Arguments = $"-f rawvideo -pix_fmt rgba -s {RecordSize.Width}x{RecordSize.Height} -r 30 -i - -f lavfi -i anullsrc=channel_layout=mono:sample_rate=8k -c:v libx264 -crf 17 -pix_fmt yuv420p -b:v 1024k -bufsize:v 1835008 {RecordFile} -tune animation";
The moment I add '-f lavfi -i anullsrc' to the cmd line the call to 'StopRecording()' has no effect and ffmpeg continues to run.
I can manually stop it by closing the console window or even using ctrl-c, but the job needs to be automated so this is just not an option.
Ultimately my question is Why is ffmpeg behaving this way?
I've come up with a couple of work arounds, but I don't like either:
- Post process the videos as per the link I mentioned earlier. Not practical. I need to generate 1000s of videos and a single batch of 350 takes around 6 hours. 50% of that time is consumed by ffmpeg encoding, so to re-encode them all just to add a null audio track would nearly double the time.
- Try to push a 'ctrl-c' through to the ffmpeg process as per this post. I did some quick tests with 'GenerateConsoleCtrlEvent' without sucess, and the idea of having to manually start and stop the Process via 'kernel32.dll' seems excessive not to mention old school.
Any insight would be greatly appreciated.