2011-06-23 63 views
6

Quiero obtener la duración del archivo de video en cadena usando C#. Busqué en internet y todo lo que obtengo es:Cómo obtener la duración del video usando FFMPEG en C# asp.net

ffmpeg -i inputfile.avi 

Y cada1 decir que analiza la salida para la duración.

Aquí está mi código, que es

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

Ahora por favor, dígame cómo puedo guardar la cadena de salida y analizarlo para la duración del vídeo.

Gracias y saludos,

+0

Eche un vistazo aquí: http: // stackoverflow.com/questions/186822/capturing-the-console-output-in-net-c –

Respuesta

4

Hay otra opción para conseguir duración del vídeo, mediante el uso de los Medios Info DLL

Usando Ffmpeg:

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

filtrado no debería ser un problema, también lo hacen eres tú mismo.

PD: al usar ffmpeg no debería leer StandardOutput pero ErrorOutput no sé por qué, pero funciona solo así.

+0

Gracias, hombre, su código no funcionó en su lugar usé el siguiente código: 'proc.StartInfo.RedirectStandardError = true; cadena mensaje = proc.StandardError.ReadToEnd(); ' Pero gracias de todos modos, me enseñaste el primer paso, que eventualmente resultará bien para mí. ¡Quédate bendecido! – Hamad

4

FFmpeg es un poco difícil de analizar. Pero en cualquier caso, esto es lo que necesita saber.

En primer lugar, FFmpeg no juega bien con opciones RedirectOutput

Lo que usted tiene que hacer es en lugar de lanzar directamente ffmpeg, lanzar cmd.exe, pasando en ffmpeg como un argumento, y redirigiendo la salida a un "archivo de monitor" a través de una salida de línea de comando como tal ... tenga en cuenta que en el lazo while (!proc.HasExited) puede leer este archivo para el estado de FFmpeg en tiempo real, o simplemente leerlo al final si se trata de una operación rápida.

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

Genial, ahora usted tiene el registro de lo que FFmpeg acaba de escupir. Ahora para obtener la duración. La línea de duración se verá algo como esto:

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

limpiar los resultados en un 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(); 

... a continuación, recorrer ellos en busca deDuration.

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

Aquí hay un código que puede hacer el análisis sintáctico para usted:

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

¡Lo siento amigo! No puedo entender tu código. ¿Dónde encajará mi archivo inputavi del cual quiero encontrar la duración? También explique las variables que ha utilizado, por ejemplo, "encodeArgs". Qué es. – Hamad

+0

su código funciona bien, que muestra información sobre ffmpeg cuando se usa ffmpeg como entrada. ¿Cómo puedo usar esto para enviar mi archivo avi como entrada y obtener su información? Gracias de todos modos. Yu está haciendo un gran – Hamad

+0

encodeArgs debería ser su "-i somefile.avi" – Brandon

1

Sólo echa un vistazo ::

//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])); 
     } 
    } 

Con agradecimiento, Gouranga Das.

+0

Realmente, me encanta tu respuesta, gracias :) –

Cuestiones relacionadas