【问题标题】:ffmpeg.exe freezesffmpeg.exe 冻结
【发布时间】:2011-10-24 21:36:54
【问题描述】:

我正在使用 Asp.Net C# Framework 4,目前正在开发一个视频转换应用程序。我还使用 ffmpeg 将所有上传的格式转换为 flv。由于有时在尝试从 mp4 直接转换为 flv 时遇到的问题,我首先将上传的文件转换为 mpg,然后再转换为 flv。但是 ffmpeg 一旦完成转换为 mpg 文件的过程就会冻结。当我运行任务管理器并检查进程列表时,它只是站在那里不使用 CPU 资源。当我直接从任务管理器结束 ffmpeg 进程时,会发生其他进程,从 mpg 转换为 flv 和预览文件(jpg)并且工作顺利。由于第一个进程冻结,当我尝试从网页的文件上传表单上传时,第二个进程无法启动。我很感激从现在开始的任何回应。这是我的代码:

        string duration = "00:00:00";

        //converting video
        Process ffmpeg;
        ffmpeg = new Process();

        // convert to mpg 1st
        ffmpeg.StartInfo.Arguments = " -i \"" + Server.MapPath("static/user/vid/") + videolink + "\" -f mpeg -b 300k -ac 2 -ab 128k -ar 44K \"" + Server.MapPath("static/user/vid/") + mpglink + "\"";
        ffmpeg.StartInfo.FileName = Page.MapPath("bin/ffmpeg.exe");
        ffmpeg.StartInfo.CreateNoWindow = true;
        ffmpeg.StartInfo.UseShellExecute = false;
        ffmpeg.StartInfo.RedirectStandardOutput = true;
        ffmpeg.StartInfo.RedirectStandardError = true;
        ffmpeg.Start();

        ffmpeg.WaitForExit();
        ffmpeg.Close();


        // mpg 2 flv
        ffmpeg = new Process();
        ffmpeg.StartInfo.Arguments = " -i \"" + Server.MapPath("static/user/vid/") + mpglink + "\" -f flv -s 624x352 \"" + Server.MapPath("static/user/vid/") + flvlink + "\"";
        ffmpeg.StartInfo.FileName = Page.MapPath("bin/ffmpeg.exe");
        ffmpeg.StartInfo.CreateNoWindow = true;
        ffmpeg.StartInfo.UseShellExecute = false;
        ffmpeg.StartInfo.RedirectStandardOutput = true;
        ffmpeg.StartInfo.RedirectStandardError = true;
        ffmpeg.Start();

        ffmpeg.BeginOutputReadLine();
        string error = ffmpeg.StandardError.ReadToEnd();
        ffmpeg.WaitForExit();

        try
        {
            duration = error.Substring(error.IndexOf("Duration: ") + 10, 8);
        }
        catch
        {
        }

        if (ffmpeg.ExitCode != 0)
        {
            ltrUpload.Text = "<div class=\"resultbox-negative\" id=\"divResult\">Problem occured during upload process. Error code: " + error + "<br>" + "</div>";
            return;
        }
        ffmpeg.Close();


        // generate preview image
        ffmpeg.StartInfo.Arguments = " -i \"" + Server.MapPath("static/user/vid/") + flvlink + "\" -s 624x352 -ss 00:00:03 -an -vframes 1 -f image2 -vcodec mjpeg \"" + Server.MapPath("static/user/vid/") + flvlink.Replace(".flv", ".jpg") + "\"";
        ffmpeg.StartInfo.FileName = Page.MapPath("bin/ffmpeg.exe");
        ffmpeg.StartInfo.CreateNoWindow = true;
        ffmpeg.StartInfo.UseShellExecute = false;
        ffmpeg.StartInfo.RedirectStandardOutput = true;
        ffmpeg.StartInfo.RedirectStandardError = true;
        ffmpeg.Start();
        ffmpeg.WaitForExit();
        ffmpeg.Close();

        // deleting original file and mpg
        FileInfo fi = new FileInfo(Server.MapPath("static/user/vid/") + videolink);
        if (fi.Exists) fi.Delete();
        fi = new FileInfo(Server.MapPath("static/user/vid/") + mpglink);
        if (fi.Exists) fi.Delete();

【问题讨论】:

  • 与您的问题并不真正相关(但它可能会有所帮助) - 您确实应该将这样一个长时间运行的进程移至一个单独的应用程序,如 Windows 服务。它可以监视文件夹并进行多线程转换等。Web 应用程序并不适合这种事情。

标签: c# asp.net visual-studio ffmpeg


【解决方案1】:
private bool ReturnVideo(string fileName)
{
  string html = string.Empty;
  //rename if file already exists

  int j = 0;
  string AppPath;
  string inputPath;
  string outputPath;
  string imgpath;
  AppPath = Request.PhysicalApplicationPath;
  //Get the application path
  inputPath = AppPath + "Upload\\Videos\\OriginalVideo";
  //Path of the original file
  outputPath = AppPath + "Upload\\Videos\\ConvertVideo";
  //Path of the converted file
  imgpath = AppPath + "Upload\\Videos\\Thumbs";
  //Path of the preview file
  string filepath = Server.MapPath("../Upload/Videos/OriginalVideo/" + fileName);
  while (File.Exists(filepath))
  {
    j = j + 1;
    int dotPos = fileName.LastIndexOf(".");
    string namewithoutext = fileName.Substring(0, dotPos);
    string ext = fileName.Substring(dotPos + 1);
    fileName = namewithoutext + j + "." + ext;
    filepath = Server.MapPath("../Upload/Videos/OriginalVideo/" + fileName);
  }
  try
  {
    this.fileuploadImageVideo.SaveAs(filepath);
  }
  catch
  {
    return false;
  }
  string outPutFile;
  outPutFile = "../Upload/Videos/OriginalVideo/" + fileName;
  int i = this.fileuploadImageVideo.PostedFile.ContentLength;
  System.IO.FileInfo a = new System.IO.FileInfo(Server.MapPath(outPutFile));
  while (a.Exists == false)
  { }
  long b = a.Length;
  while (i != b)
  { }

  string cmd = " -i \"" + inputPath + "\\" + fileName + "\" \"" + outputPath + "\\" + fileName.Remove(fileName.IndexOf(".")) + ".flv" + "\"";
  ConvertNow(cmd);
  ViewState["fileName"] = fileName.Remove(fileName.IndexOf(".")) + ".wmv";
  string imgargs = " -i \"" + inputPath + "\\" + fileName.Remove(fileName.IndexOf(".")) + ".wmv" + "\" -f image2 -ss 1 -vframes 1 -s 280x200 -an \"" + imgpath + "\\" + fileName.Remove(fileName.IndexOf(".")) + ".jpg" + "\"";
  ConvertNow(imgargs);

  return true;
}

private void ConvertNow(string cmd)
{
  string exepath;
  string AppPath = Request.PhysicalApplicationPath;
  //Get the application path
  exepath = AppPath + "ffmpeg.exe";
  System.Diagnostics.Process proc = new System.Diagnostics.Process();
  proc.StartInfo.FileName = exepath;
  //Path of exe that will be executed, only for "filebuffer" it will be "wmvtool2.exe"
  proc.StartInfo.Arguments = cmd;
  //The command which will be executed
  proc.StartInfo.UseShellExecute = false;
  proc.StartInfo.CreateNoWindow = true;
  proc.StartInfo.RedirectStandardOutput = false;
  proc.Start();

  while (proc.HasExited == false)
  { }
}

if (fileuploadImageVideo.HasFile)
{
  ReturnVideo(this.fileuploadImageVideo.FileName.ToString());

  string filename = fileuploadImageVideo.PostedFile.FileName;
  fileuploadImageVideo.SaveAs(Server.MapPath("../upload/Video/"+filename));
  objfun.Video = filename ;
}

【讨论】:

  • 嗨@Munish,欢迎来到SO。如果您的答案解释了为什么您的代码回答了原始问题,这可能会有所帮助
【解决方案2】:

我知道这是一个非常古老的问题,但如果有人因为谷歌搜索而来到这里,答案如下:

您也必须阅读第一个 ffmpeg 进程的重定向错误输出,即使您不需要它。如果您不读取重定向的错误输出,则会导致死锁,因为您的程序将等待进程完成,但进程等待读取填充的错误输出流。你可以查一下here

    // convert to mpg 1st
    ffmpeg.StartInfo.Arguments = " -i \"" + Server.MapPath("static/user/vid/") + videolink + "\" -f mpeg -b 300k -ac 2 -ab 128k -ar 44K \"" + Server.MapPath("static/user/vid/") + mpglink + "\"";
    ffmpeg.StartInfo.FileName = Page.MapPath("bin/ffmpeg.exe");
    ffmpeg.StartInfo.CreateNoWindow = true;
    ffmpeg.StartInfo.UseShellExecute = false;
    ffmpeg.StartInfo.RedirectStandardOutput = true;
    ffmpeg.StartInfo.RedirectStandardError = true;
    ffmpeg.Start();

    // Use asynchronous read operations on at least one of the streams.
    // Reading both streams synchronously would generate another deadlock.
    ffmpeg.BeginOutputReadLine();
    string tmpErrorOut = ffmpeg.StandardError.ReadToEnd();

    ffmpeg.WaitForExit();
    ffmpeg.Close();

因此,您必须像使用第二个 ffmpeg 进程一样读取重定向的错误和输出流。

生成图像预览部分也是如此!

【讨论】:

  • 对我来说,它冻结在线ffmpeg.StandardError.ReadToEnd();
  • 你是不是也用了异步方法ffmpeg.BeginOutputReadLine();
  • 最后我简单地复制/粘贴你的代码sn-p,它就成功了。谢谢。
  • 感谢@MichaelArmbruster 我已经为这个问题苦苦挣扎了两天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
  • 2015-11-17
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多