2011-06-23 13 views
6

Chcę uzyskać czas trwania pliku wideo w ciągu przy użyciu C#. Przeszukałem internet i wszystko, co dostaję, to:Jak uzyskać czas trwania wideo za pomocą FFMPEG w C# asp.net

ffmpeg -i inputfile.avi 

I co 1 powiedzieć, że analizować wyjście na czas.

Tu jest mój kod, który jest

string filargs = "-y -i " + inputavi + " -ar 22050 " + outputflv; 
    Process proc; 
    proc = new Process(); 
    proc.StartInfo.FileName = spath; 
    proc.StartInfo.Arguments = filargs; 
    proc.StartInfo.UseShellExecute = false; 
    proc.StartInfo.CreateNoWindow = false; 
    proc.StartInfo.RedirectStandardOutput = false; 
    try 
    { 
     proc.Start(); 

    } 
    catch (Exception ex) 
    { 
     Response.Write(ex.Message); 
    } 

    try 
    { 
     proc.WaitForExit(50 * 1000); 
    } 
    catch (Exception ex) 
    { } 
    finally 
    { 
     proc.Close(); 
    } 

Teraz proszę mi powiedzieć, w jaki sposób można zapisać ciąg wyjściowy i przetwarza go na czas trwania wideo.

Dzięki i pozdrawiam,

+0

Zobacz tutaj: http: // stackoverflow.com/questions/186822/capture-the-console-output-in-net-c –

Odpowiedz

4

Nie ma innej opcji, aby uzyskać wideo Długość, przy użyciu nośnika informacji DLL

Korzystanie Ffmpeg:

proc.StartInfo.RedirectErrorOutput = true; 
string message = proc.ErrorOutput.ReadToEnd(); 

Filtrowanie nie powinno być problemem, więc nie jesteś sobą.

PS: używając ffmpeg nie powinieneś czytać StandardOutput, ale ErrorOutput i nie wiem dlaczego, ale działa to tylko tak.

+0

Dzięki temu twój kod nie zadziałał, użyłem następującego kodu: 'proc.StartInfo.RedirectStandardError = true; ciąg wiadomość = proc.StandardError.ReadToEnd(); ' Ale dzięki, pokazałeś mi pierwszy krok, który w końcu okazał się dla mnie dobry. Bądźcie błogosławieni !!! – Hamad

4

FFmpeg to odrobina przygody do przeanalizowania. Ale w każdym razie, oto, co powinieneś wiedzieć.

pierwsze, FFmpeg nie gra dobrze z opcji RedirectOutput

Co trzeba zrobić, to zamiast uruchamiania ffmpeg bezpośrednio uruchomić cmd.exe, przekazując ffmpeg jako argument, a przekierowanie wyjścia do "plik monitora" poprzez wyjście z wiersza poleceń, tak jak ... pamiętaj, że w pętli while (!proc.HasExited) możesz odczytać ten plik dla stanu FFmpeg w czasie rzeczywistym lub po prostu przeczytać go na końcu, jeśli jest to szybka operacja.

 FileInfo monitorFile = new FileInfo(Path.Combine(ffMpegExe.Directory.FullName, "FFMpegMonitor_" + Guid.NewGuid().ToString() + ".txt")); 

     string ffmpegpath = Environment.SystemDirectory + "\\cmd.exe"; 
     string ffmpegargs = "/C " + ffMpegExe.FullName + " " + encodeArgs + " 2>" + monitorFile.FullName; 

     string fullTestCmd = ffmpegpath + " " + ffmpegargs; 

     ProcessStartInfo psi = new ProcessStartInfo(ffmpegpath, ffmpegargs); 
     psi.WorkingDirectory = ffMpegExe.Directory.FullName; 
     psi.CreateNoWindow = true; 
     psi.UseShellExecute = false; 
     psi.Verb = "runas"; 

     var proc = Process.Start(psi); 

     while (!proc.HasExited) 
     { 
      System.Threading.Thread.Sleep(1000); 
     } 

     string encodeLog = System.IO.File.ReadAllText(monitorFile.FullName); 

Świetnie, teraz masz log tego, co FFmpeg po prostu wypluwa. Teraz, aby uzyskać czas trwania. Linia czas trwania będzie wyglądać mniej więcej tak:

Duration: 00:10:53.79, start: 0.000000, bitrate: 9963 kb/s

oczyścić wyniki do List<string>:

var encodingLines = encodeLog.Split(System.Environment.NewLine[0]).Where(line => string.IsNullOrWhiteSpace(line) == false && string.IsNullOrEmpty(line.Trim()) == false).Select(s => s.Trim()).ToList(); 

... wtedy pętla przez nich szukaDuration.

 foreach (var line in encodingLines) 
     { 
      // Duration: 00:10:53.79, start: 0.000000, bitrate: 9963 kb/s 
      if (line.StartsWith("Duration")) 
      { 
       var duration = ParseDurationLine(line); 
      } 
     } 

Oto niektóre kod, który może zrobić dla ciebie parse:

private TimeSpan ParseDurationLine(string line) 
    { 
     var itemsOfData = line.Split(" "[0], "="[0]).Where(s => string.IsNullOrEmpty(s) == false).Select(s => s.Trim().Replace("=", string.Empty).Replace(",", string.Empty)).ToList(); 

     string duration = GetValueFromItemData(itemsOfData, "Duration:"); 

     return TimeSpan.Parse(duration); 
    } 

    private string GetValueFromItemData(List<string> items, string targetKey) 
    { 
     var key = items.FirstOrDefault(i => i.ToUpper() == targetKey.ToUpper()); 

     if (key == null) { return null; } 
     var idx = items.IndexOf(key); 

     var valueIdx = idx + 1; 

     if (valueIdx >= items.Count) 
     { 
      return null; 
     } 

     return items[valueIdx]; 
    } 
+0

Przepraszam, koleś! Nie mogę zrozumieć Twojego kodu. Gdzie zmieści się mój plik inputavi, w którym chcę znaleźć czas trwania? Wyjaśnij również używane zmienne np. "EncodeArgs" Co to jest? – Hamad

+0

Twój kod działa poprawnie, co pokazuje informacje o ffmpeg, gdy użyto ffmpeg jako danych wejściowych. Jak mogę tego użyć, aby wysłać mój plik avi jako dane wejściowe i uzyskać jego informacje? W każdym razie dzięki. Yu świetnie się spisują – Hamad

+0

encodeArgs powinien być twoim "-i somefile.avi" – Brandon

1

Wystarczy to sprawdzić ::

//Create varriables 

    string ffMPEG = System.IO.Path.Combine(Application.StartupPath, "ffMPEG.exe"); 
    system.Diagnostics.Process mProcess = null; 

    System.IO.StreamReader SROutput = null; 
    string outPut = ""; 

    string filepath = "D:\\source.mp4"; 
    string param = string.Format("-i \"{0}\"", filepath); 

    System.Diagnostics.ProcessStartInfo oInfo = null; 

    System.Text.RegularExpressions.Regex re = null; 
    System.Text.RegularExpressions.Match m = null; 
    TimeSpan Duration = null; 

    //Get ready with ProcessStartInfo 
    oInfo = new System.Diagnostics.ProcessStartInfo(ffMPEG, param); 
    oInfo.CreateNoWindow = true; 

    //ffMPEG uses StandardError for its output. 
    oInfo.RedirectStandardError = true; 
    oInfo.WindowStyle = ProcessWindowStyle.Hidden; 
    oInfo.UseShellExecute = false; 

    // Lets start the process 

    mProcess = System.Diagnostics.Process.Start(oInfo); 

    // Divert output 
    SROutput = mProcess.StandardError; 

    // Read all 
    outPut = SROutput.ReadToEnd(); 

    // Please donot forget to call WaitForExit() after calling SROutput.ReadToEnd 

    mProcess.WaitForExit(); 
    mProcess.Close(); 
    mProcess.Dispose(); 
    SROutput.Close(); 
    SROutput.Dispose(); 

    //get duration 

    re = new System.Text.RegularExpressions.Regex("[D|d]uration:.((\\d|:|\\.)*)"); 
    m = re.Match(outPut); 

    if (m.Success) { 
     //Means the output has cantained the string "Duration" 
     string temp = m.Groups(1).Value; 
     string[] timepieces = temp.Split(new char[] {':', '.'}); 
     if (timepieces.Length == 4) { 

      // Store duration 
      Duration = new TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3])); 
     } 
    } 

Z podziękowaniami, Gouranga DAS.

+0

Naprawdę, kocham twoją odpowiedź, dziękuję :) –

Powiązane problemy