1

I'm writing an app that uses ffmpeg to convert audio/video files. I can call ffmpeg and specify it's options, I can see that it's working. I want to be able to check how much of the job is done, so I can present it to user. As I've read ffmpeg doesn't support any progress bar or percentage and ffmpeg console output is not very friendly, so I cannot simply show it's output to user, because it will look awful. I am not using any wrapper and do not plan to use any because I need to write my own backend that call ffmpeg and frontend to communicate with user.

I'm using System.Threading to start ffmpeg in new process, I can say if the process is running, or get it's exit code, but I don't see any way to get info about how much of the job is done. I thought I can simply measure input file size and check periodically output file size, but it won't be any accurate, because the output file will have different size depending on what codec and container we use. I've read I can also use frame progress, but the way of obtaining it is still not clear to me. I also need to do it for audio files.

Is there any reasonable way to do so?

Aenye_Cerbin
  • 158
  • 10
  • 1
    See "-progress" option of ffmpeg. It will output machine readable progress info into specified file (you can also output that into stdout). Then parse this output periodically and get the info you need. It outputs progress as number of frames processed so you will first need to query number of frames in your input file. Then divide progress number of frames by total and you get the percentage. – Evk Dec 10 '22 at 18:37
  • 1
    You may take a look at my [following answer](https://stackoverflow.com/a/67409107/4926757) in Python. – Rotem Dec 10 '22 at 22:04

2 Answers2

1

Done it by adding -progress - to ffmpeg arguments, adding eventhandlers and calculating total number of frames before actually converting the file.

Adding event handlers:

process.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);

Event handler:

private void FfmpegOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) {
        if(outLine.Data != null) {
            if (outLine.Data.Contains("frame=")) {
                lastFrame = Int32.Parse(outLine.Data.Split("=")[1].Trim());
            }
        }
    }

Before the conversion I call ffmpeg with -vstats parameter for input file and parse it's response to get total duration and FPS. When I got this info I can calc total number of frames and pass it to the class making main ffmpeg call:

TotalNumberOfFrames = Time.TotalSeconds * FPS;

Then when I can get current frame and total number of frames in video I can calc the percentage done:

public double Progress { 
            get {
                return Math.Round((lastFrame / (metadata.TotalNumberOfFrames)) * 100, 1);
            } 
        }
Aenye_Cerbin
  • 158
  • 10
0

Try use FFmpegArgs or you can re-write from it

string args = "-i file.mp4 -y out.flv";
FFmpegRender fFmpegRender = FFmpegRender.FromArguments(args, new FFmpegRenderConfig()
{
    FFmpegBinaryPath = "Path to file ffmpeg",//or not set if available in PATH
    WorkingDirectory = YourWorkingDirectory,//default is Directory.GetCurrentDirectory()
});
fFmpegRender.OnEncodingProgress += FFmpegRender_OnEncodingProgress;
FFmpegRenderResult fFmpegRenderResult = await fFmpegRender.ExecuteAsync(CancellationToken);
if (fFmpegRenderResult.ExitCode != 0)
{
    //error
}

private void FFmpegRender_OnEncodingProgress(RenderProgress obj)
{
    Console.WriteLine($"{obj.Time:h\\:mm\\:ss}");
}