Home > front end >  c# winforms display ffmpeg output
c# winforms display ffmpeg output

Time:09-30

i am working on a app that can record video/audio using webcam and microphone while also displaying it on winforms.

Process.Start(new ProcessStartInfo
            {
                FileName = "ffmpeg",
                Arguments = $"-f dshow -video_size 1280x720 -framerate 30 -vcodec mjpeg -i video=\"{video device}\":audio=\"{audio device}\" -pix_fmt yuv420p -f mp4 -movflags frag_keyframe empty_moov {output}"
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            });

currently using this ffmpeg command to record and save mp4. i want to know how can i display the output stream in winforms if i use pipe:1 as output rather than a file path. i have used aforge.Directshow before but the quality of the video saved is very poor. Any other suggestions on how to do this are welcome.

CodePudding user response:

Here's a class that starts FF and attaches event handlers to the relevant process events so it can see the output data as it's generated. It is used within a context where it's interesting to know if audio has started or stopped, which relied on ff having an extension that monitored the audio channels and pumped a message when silence started or stopped, but it demonstrates how you could have your own events on this class and raise them when ffmpeg pumps messages of interest. Mostly the class just captures the output into a log

public class FfmpegRecorder 
{
    public event Action SilenceDetected;
    public event Action NoiseDetected;

    private StringBuilder _ffLog = new StringBuilder();
    private Process _ffmpeg;
    private string _streamStats;

    public override void StartRecording()
    {
        ProcessStartInfo psi = new ProcessStartInfo
        {
            FileName = Properties.Settings.Default.CommandLineFfmpegPath,
            Arguments = string.Format(
                Properties.Settings.Default.CommandLineFfmpegArgs,
                OutputPath
            ),
            WindowStyle = ProcessWindowStyle.Hidden,
            CreateNoWindow = true,
            UseShellExecute = false,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        };

        _ffmpeg = System.Diagnostics.Process.Start(psi);
        _ffmpeg.OutputDataReceived  = Ffmpeg_OutputDataReceived;
        _ffmpeg.ErrorDataReceived  = Ffmpeg_ErrorDataReceived;
        _ffmpeg.BeginOutputReadLine();
        _ffmpeg.BeginErrorReadLine();

        _ffmpeg.PriorityClass = ProcessPriorityClass.High;
    }

    void Ffmpeg_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        if (e.Data != null && IsInteresting(e.Data))
        {
            _ffLog.Append("STDOUT: ").AppendLine(e.Data);
        }
    }
    void Ffmpeg_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        if (e.Data != null && IsInteresting(e.Data))
        {
            _ffLog.Append("STDERR: ").AppendLine(e.Data);
        }
    }

    bool IsInteresting(string data)
    {
        if (data.StartsWith("frame="))
        {
            _streamStats = data;
            return false;
        }

        try
        {
            if (SilenceDetected != null && data.Contains("silence_start"))
                SilenceDetected();
            else if (NoiseDetected != null && data.Contains("silence_end"))
                NoiseDetected();
        }
        catch { }

        return true;
    }

   

   
}

}

CodePudding user response:

Found out vlc has a lib for winforms. here is a tutorial on how to add it. for the VlcLibDirectory property you will need to download vlc. just pass the ffmpeg.StandardOutput.BaseStream into its play method.

  • Related