如何确定FFmpeg进程何时完成

时间:2017-04-13 05:32:12

标签: c# .net audio ffmpeg

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

当文件被删除时,以下异常经常(可能是80%的时间)抛出:

  

IOException:进程无法访问文件&C; \ MyOriginalFile.webm'因为它正被另一个进程使用。

创建和运行FFmpeg进程的调用如下:

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

即使删除文件时进程已完成,但FFmpeg仍处理或未发布。

预计会出现这种情况吗?在继续之前,如何确保FFmpeg已完成文件处理?

1 个答案:

答案 0 :(得分:0)

如果是我,我会在后台线程上运行它并点击process.Exited事件并尝试删除那里的文件。

MSDN Documentation for the Process Exit Event使用此策略并轮询30秒,直到Exited事件触发并检查ExitCode。根据ExitCode,您可以给它更多时间,检查文件是否仍然被锁定或执行另一个操作,直到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);
}