0

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.

0

2 Answers 2

1

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;
    }

   

   
}

}

Sign up to request clarification or add additional context in comments.

6 Comments

i tried this but the output data only fires twice with a small amount off data, and the error output seems fine.
I don't really know what you want me to do with that info.. What does "the output data only fires twice" mean ? What have you implemented? What does "the error output seems fine" mean?
Most of ffmpeg's output is messages that start with "frame=" - this code deems those as not interesting so it doesn't keep any other than the last one.. It's fully incumbent upon you to adjust this code to meet your needs; your question doesn't contain enough info to know how to process FF's output for your case - that's all in your head only. Note that you don't need to tell FF to do anything special with the output (in your Q you said "pipe it to 1 rather than a file") - don't do any redirection arguments in the command line, just run ff as simply as you can while youre testing
sorry, i am still learning about ffmpeg and i thought that i should be getting a stream over and over again representing the footage and audio as mp4, i was using ffmpeg.StandardOutput.BaseStream before i tried your answer, so i thought that Ffmpeg_OutputDataReceived should be firing everytime ffmpeg gets the webcam footage and audio. even so, what i want is to get the output and convert it to an image/bitmap so i can display it in winforms picturebox. EDIT: i ran the commands in cmd and it all works well, when i pipe:1 i get a continuous stream of random characters i assume to be mp4 stream
Oh.. Hmmm, yeah I don't think you'll have much success with the "stream an mp4 into a picturebox as a sequence of image" idea. Performance will be horrendous
|
0

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.

2 Comments

Hi, you can self-answer and accept your answer by click on the mark below answer's score
@Elikill58 as it stands though it's not enough of an answer on its own..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.