2015-11-17 156 views
0

我試圖從命令行應用程序中使用ffmpeg庫將一些avi文件轉換爲mkv。我做了一個方法,可以讓我做到這一點:System.Diagnostics.Process程序繼續運行

public bool convertAvitoMkv(string path, string sourceName, string destName) 
    { 

     bool returncode = false; 
     try 
     { 
      string comando = string.Format("-i {0} -c:v libx264 -crf 19 -preset slow -c:a libfaac -b:a 192k -ac 2 {1}", string.Format("{0}\\{1}",path,sourceName), string.Format("{0}\\{1}",path,destName) + ".mkv"); 
      System.Diagnostics.Process process = new System.Diagnostics.Process(); 
      System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
      startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
      startInfo.FileName = "ffmpeg.exe"; 
      startInfo.WorkingDirectory = programPath; 
      startInfo.CreateNoWindow = true; 
      startInfo.Arguments = comando; 
      process.StartInfo = startInfo; 
      process.Start(); 
      while (!process.HasExited) 
      { 
       process.Kill(); 
       //continue hasta que termine la ejecucion 
      } 

      returncode = process.HasExited; 
     } 
     catch (Exception ex) 
     { 

     } 
     return returncode; 
    } 

以前的版本沒有的,而(!process.HasExited),但我說,因爲我注意到,有很多的ffmpeg的實例。 EXE運行,我不得不手動關閉。我如何保證每次轉換都已完成,並且ffmpeg的每個實例都已關閉? 關於

+0

當您嘗試手動轉換相同的文件時(通過直接從命令行運行它),ffmpeg是否會掛起? – xxbbcc

+2

啓動它後,你正在殺死進程 - 啓動一個進程是一個漫長而耗時的過程,調用'Start'後'HasExited'幾乎保證爲'false'。你應該使用'Process.WaitForExit'來代替。 https://msdn.microsoft.com/en-us/library/ty0d8k56%28v=vs.110%29.aspx – xxbbcc

+0

原來的行while(!process.HasExited) { process.Kill(); } 不在那裏。我在任務管理器上看到很多ffmpeg進程後添加了這些進程,以避免這種情況,但它沒有工作 – edotom

回答

0
public bool concatenarArchivos(string archivos, string path, string destName) 
    { 
     bool returncode = false; 
     try 
     { 
      string[] extensions = {".mp4"}; 
      string[] dirContents = System.IO.Directory.GetFiles(path, "*.*").Where(f => extensions.Contains(new FileInfo(f).Extension.ToLower())).ToArray(); 
      if (dirContents.Length > 0) 
      { 
       string comando = string.Format("-f concat -i {0} -c copy {1}", archivos, string.Format("{0}\\{1}", path, destName)); 
       System.Diagnostics.Process process = new System.Diagnostics.Process(); 
       System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
       startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
       startInfo.FileName = "ffmpeg.exe"; 
       startInfo.WorkingDirectory = programPath; 
       startInfo.CreateNoWindow = true; 
       startInfo.Arguments = comando; 
       process.StartInfo = startInfo; 
       process.Start(); 
       process.WaitForExit(); 
       //process.Close(); 
       process.Dispose(); 
       //returncode = process.HasExited; 
      } 
     } 
     catch (Exception ex) 
     { 

     } 
     return returncode; 
    } 
+0

在你調用Dispose之後,你不應該訪問'Process'的任何屬性。 – xxbbcc

+0

你是對的..過去的代碼是無用的 – edotom

0

我有同樣的問題。在調試時,我注意到當我使用WaitForExit時,它一直等待無限期。當我使用!process.HasExited的while循環時,它也沒有通過while循環。

只要我爲標準輸出和錯誤添加了重定向,並且讀取它開始按照預期工作的流。

看來,當有某種輸出(常規和/或錯誤)時,進程會一直等待,直到輸出處理完畢。在它不會退出之前。

如下更改您的代碼很可能會解決您的問題。

public bool convertAvitoMkv(string path, string sourceName, string destName) 
    { 

     bool returncode = false; 
     try 
     { 
      string comando = string.Format("-i {0} -c:v libx264 -crf 19 -preset slow -c:a libfaac -b:a 192k -ac 2 {1}", string.Format("{0}\\{1}",path,sourceName), string.Format("{0}\\{1}",path,destName) + ".mkv"); 
      System.Diagnostics.Process process = new System.Diagnostics.Process(); 
      System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
      startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
      startInfo.FileName = "ffmpeg.exe"; 
      startInfo.WorkingDirectory = programPath; 
      startInfo.CreateNoWindow = true; 
      startInfo.Arguments = comando; 
      startInfo.RedirectStandardOutput = true; 
      startInfo.RedirectStandardError = true; 
      process.StartInfo = startInfo; 
      process.Start(); 

      StreamReader readerOut = process.StandardOutput; 
      StreamReader readerErr = process.StandardError; 
      // Process the readers e.g. like follows 
      string errors = readerErr.ReadToEnd(); 
      string output = readerOut.ReadToEnd(); 

      while (!process.HasExited) 
      { 
       continue; 
      } 

      returncode = process.HasExited; 
     } 
     catch (Exception ex) 
     { 

     } 
     return returncode; 
    } 
+0

好評...最近我發現,對於一些不知情的原因,某些進程保持運行。我會盡力的..謝謝 – edotom