2
var origFilePath = "C:/MyOriginalFile.webm";
var processedFilePath = "C:/MyProcessedFile.webm";

RunFfmpeg($"-i \"{origFilePath}\" -af \"silenceremove=1:0.1:0.001, areverse, silenceremove=1:0.1:0.001, areverse\" \"{processedFilePath}\" -y");

// fails with IOException as the file presumably not been released by FFmpeg
System.IO.File.Delete(origFilePath);

When the file is deleted, the following exception is frequently (maybe 80% of the time) thrown:

IOException: The process cannot access the file 'C:\MyOriginalFile.webm' because it is being used by another process.

The call to create and run the FFmpeg process goes like this:

private List<string> RunFfmpeg(string arguments)
{
    using (var process = new Process())
    {
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.FileName = _hostingEnvironment.ContentRootPath + _settings.FfmpegPath;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;

        // ffmpeg only uses strerr for its output
        var output = new List<string>();
        process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { 
            if (e.Data != null)
                output.Add(e.Data);
        });

        process.Start();
        process.BeginErrorReadLine();
        process.WaitForExit();
        return output;
    }
}

It appears that even though the process has completed when the file is deleted, FFmpeg is still processing or has otherwise not released it.

Is this behaviour expected? How do I go about ensuring that FFmpeg has finished processing the files before continuing?

ajbeaven
  • 9,265
  • 13
  • 76
  • 121
  • Check if the file doesn't have a lock on it before you delete it: http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use – Jeremy Thompson Apr 13 '17 at 05:51
  • @JeremyThompson so what if it is locked? I'd hoped there would be a more elegant way to do this than `Thread.Sleep`. – ajbeaven Apr 17 '17 at 21:32

1 Answers1

0

If it were me I'd run this on a background thread and tap into the process.Exited event and try to delete the File in there.

The MSDN Documentation for the Process Exit Event uses this strategy and polls for 30 seconds till the Exited event fires and checks the ExitCode. Depending on the ExitCode, you could give it more time, check if the file is still locked or perform another action until process.ExitCode == 0

private Process myProcess = new Process();
private int elapsedTime;
private bool eventHandled;

public void RunFfmpeg(string arguments)
{    
    elapsedTime = 0;
    eventHandled = false;    
    try
    {
        myProcess.StartInfo.FileName = _hostingEnvironment.ContentRootPath + _settings.FfmpegPath;
        myProcess.StartInfo.Arguments = arguments;
        myProcess.StartInfo.CreateNoWindow = true;
        myProcess.EnableRaisingEvents = true;
        myProcess.Exited += new EventHandler(myProcess_Exited);
        myProcess.Start();    
    }
    catch (Exception ex)
    {
        Console.WriteLine("An error occurred trying to print \"{0}\":" + "\n" + ex.Message, fileName);
        return;
    }

    // Wait for Exited event, but not more than 30 seconds.
    const int SLEEP_AMOUNT = 100;
    while (!eventHandled)
    {
        elapsedTime += SLEEP_AMOUNT;
        if (elapsedTime > 30000)
        {
            break;
        }
        Thread.Sleep(SLEEP_AMOUNT);
    }
}

private void myProcess_Exited(object sender, System.EventArgs e)
{    
    eventHandled = true;
    Console.WriteLine("Exit time:    {0}\r\n" +
        "Exit code:    {1}\r\nElapsed time: {2}", myProcess.ExitTime, myProcess.ExitCode, elapsedTime);
}
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • Is this expected behaviour that the C# process fires the exit event before the process has actually completed? – ajbeaven Apr 21 '17 at 02:55
  • No, the Process should exit. If this isn't the behavior you're seeing perhaps you should poll processes to be 100% sure the FFMpeg conversion has finished. – Jeremy Thompson Apr 21 '17 at 03:09
  • @ajbeaven I found [this ticket](https://stackoverflow.com/questions/43384242/how-to-determine-when-ffmpeg-process-completes) which led me to this SO question. I am currently having a [similar issue](https://stackoverflow.com/questions/64292363/calling-ffmpeg-from-command-line-does-not-wait-until-file-was-fully-written-do-h). cehoyo's assumptions in the ticket is wrong by the way. A process can still "process" something after it finished if that processing is done by a child process. I think this is the issue in my case. Any idea how to solve that problem? – Stefan Falk Oct 10 '20 at 10:59