The class that I've created for ffmpeg that derives from System.Diagnostics.Process. I'm looking for any help with arguments that can be added for more support. A little background, I built this to work with a solution I've created using NAudio and AForge. NAudio is used to record audio while AForge Displays Images from a webcam and saves the images. This class is then used to first combine the images to a video then combine the video and audio for a final result. Anyhow, here is the code.
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Webcam
{
public sealed class FFMPEG_PROCESS : Process
{
private bool _createdWithOptions;
private string _args;
public static FFMPEG_PROCESS WithOptions() = new FFMPEG_PROCESS();
private FFMPEG_PROCESS() { _createdWithOptions = true; }
public FFMPEG_PROCESS(string args) { _args = args; }
//Don't allow setting processes StartInfo
public new ProcessStartInfo StartInfo
{
get => base.StartInfo = new ProcessStartInfo("ffmpeg.exe", _args)
{
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true
};
}
public FFMPEG_PROCESS WithOutput(string value)
{
if (!_createdWithOptions) return this;
_args += $" {value}"; return this;
}
public FFMPEG_PROCESS WithInput(string value)
{
if (!_createdWithOptions) return this;
_args += $" -i {value}"; return this;
}
public FFMPEG_PROCESS WithAudioType(string value)
{
if (!_createdWithOptions) return this;
_args += $" -c:a {value}"; return this;
}
public FFMPEG_PROCESS WithConcatList(string value)
{
if (!_createdWithOptions) return this;
_args += $" -f concat -safe 0 -i {value}"; return this;
}
public FFMPEG_PROCESS WithVideoFilter(string value)
{
if (!_createdWithOptions) return this;
_args += $" -vf {value}"; return this;
}
/// <summary>
/// The CRF of x264 and x265 video
/// </summary>
public FFMPEG_PROCESS WithConstantRateFactor(int value)
{
if (!_createdWithOptions) return this;
_args += $" -crf {value}"; return this;
}
public new Task<FFMPEG_PROCESS> Start()
{
//initialize our StartInfo
var result = StartInfo;
if (base.StartInfo.Arguments != result.Arguments)
throw new ArgumentException(nameof(StartInfo));
if(!base.Start()) throw new Exception(nameof(Start));
return Task.FromResult(this);
}
}
}
Examples of using the class.
var ffmpegProcess = await FFMPEG_PROCESS
.WithOptions()
.WithInput(input.mp4)
.WithInput(((IAudioRecorder)audio).Filename)
.WithAudioType("flac")
.WithOutput(output.mp4)
.Start();
ffmpegProcess.WaitForExit();
var ffmpegProcess = await FFMPEG_PROCESS
.WithOptions()
.WithConcatList(frameList)
.WithVideoFilter("\"fps=30, format=yuv420p\"")
.WithConstantRateFactor(30)
.WithOutput(output.mp4)
.Start();
ffmpegProcess.WaitForExit();
New FFMPEG_PROCESS Additions
public FFMPEG_PROCESS WithNoVideo()
{
if (!_createdWithOptions) return this;
_args += " -vn"; return this;
}
public FFMPEG_PROCESS WithVideoFrameRate(int value)
{
if (!_createdWithOptions) return this;
_args += $" -r {value}"; return this;
}