c# - FFmpeg 在 20% 时暂停提取帧(但关闭时,会将所有帧转储到磁盘)

标签 c# ffmpeg

我正在尝试使用 FFmpeg 从视频中提取帧。我希望能够通过设置开始、结束和 FPS 值来控制要提取的帧。

问题是,在提取开始后,FFmpeg 在大约 20% 之后停止。它总是停在那里,与帧数无关。

这是我正在使用的代码:

var start = TimeSpan.FromMilliseconds(SelectionSlider.LowerValue);
var end = TimeSpan.FromMilliseconds(SelectionSlider.UpperValue);
var fps = FpsIntegerUpDown.Value;
var count = CountFrames(); //Duration x FPS
var folder = Path.Combine(RootFolder, "Import");
var path = Path.Combine(folder, $"%0{count.ToString().Length + 1}d.png");

try
{
    //Create temporary folder.
    if (Directory.Exists(folder))
        Directory.Delete(folder, true);

    Directory.CreateDirectory(folder);

    CaptureProgressBar.Value = 0;
    CaptureProgressBar.Maximum = count;

    var info = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
    {
        Arguments = $" -i \"{VideoPath}\" -vsync 2 -progress pipe:1 -vf scale={VideoWidth}:{VideoHeight} -ss {start:hh\\:mm\\:ss\\.fff} -to {end:hh\\:mm\\:ss\\.fff} -hide_banner -c:v png -r {fps} -vframes {count} \"{path}\"",
        CreateNoWindow = true,
        ErrorDialog = false,
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true
     };

     _process = new Process();
     _process.OutputDataReceived += (sender, e) =>
     {
         Debug.WriteLine(e.Data);

         if (string.IsNullOrEmpty(e.Data))
             return;

         var parsed = e.Data.Split('=');

         switch (parsed[0])
         {
             case "frame":
                 Dispatcher?.InvokeAsync(() => { CaptureProgressBar.Value = Convert.ToDouble(parsed[1]); });
                 break;

             case "progress":
                 if (parsed[1] == "end" && IsLoaded)
                     GetFiles(folder); //Get all files from the output folder.

                 break;
          }
    };

_process.ErrorDataReceived += (sender, e) =>
{
    if (!string.IsNullOrEmpty(e.Data))
        throw new Exception("Error while capturing frames with FFmpeg.") { HelpLink = $"Command:\n\r{info.Arguments}\n\rResult:\n\r{e.Data}" };
};

_process.StartInfo = info;
_process.Start();
_process.BeginOutputReadLine();

//Just to wait...
await Task.Factory.StartNew(() => _process.WaitForExit());

因此,在开始导入过程后,FFmpeg 会提取一些帧,在达到 20% 左右后,会暂停提取。
frame=95
fps=5.79
stream_0_0_q=-0.0
bitrate=N/A
total_size=N/A
out_time_us=1400000
out_time_ms=1400000
out_time=00:00:01.400000
dup_frames=0
drop_frames=0
speed=0.0854x

progress=continue
frame=106
fps=6.25
stream_0_0_q=-0.0
bitrate=N/A
total_size=N/A
out_time_us=1583333
out_time_ms=1583333
out_time=00:00:01.583333
dup_frames=0
drop_frames=0
speed=0.0933x
progress=continue

frame=117
fps=6.67
stream_0_0_q=-0.0
bitrate=N/A
total_size=N/A
out_time_us=1766667
out_time_ms=1766667
out_time=00:00:01.766667
dup_frames=0
drop_frames=0
speed=0.101x
progress=continue

奇怪的是:如果我在提取暂停时关闭应用程序,FFmpeg 会突然将所有帧转储到文件夹中。

为什么 FFmpeg 会完全暂停提取(但继续在内存中进行)?
我有什么办法可以强制 FFmpeg 正常提取帧吗?

PS:通过cmd使用FFmpeg时不会发生这种情况,所以它必须是代码中的东西。

最佳答案

我不能设置RedirectStandardError = true没有通过 BeginErrorReadLine() 实际处理其数据.

所以我只需要设置RedirectStandardError = false或者我应该添加 BeginErrorReadLine() .

关于c# - FFmpeg 在 20% 时暂停提取帧(但关闭时,会将所有帧转储到磁盘),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59130237/

相关文章:

c# - 构建 FFmpeg.NET .dll

android - 使用 ffmpeg 播放带有音轨的 mp3 数据

video - ffmpeg - 如何删除看到的扫描线

c# - EF : The underlying provider failed on Open

c# - 在 Azure 辅助角色 http 请求中获取 http 500

c# - 如何使用证书签署 ActiveX DLL

使用泛型类型或接口(interface)的 C# 集合

javascript - 将 canvas.toDataURL() 传递给 ffmpeg.wasm 问题

c# - FFmpeg 文件转换格式和文件扩展名

audio - 带有python子进程Popen的ffmpeg