2009-11-10 27 views
16

Me gustaría poder usar FFmpeg para convertir un archivo de video desde mi programa C#. Sé que puedo llamar a un comando de shell, , pero ¿hay una mejor manera?C# y FFmpeg preferiblemente sin comandos de shell?

El problema con invocar un comando a través del shell, es que no estoy seguro de que pueda hacer cosas como una barra de progreso, etc ... o podría?

Si no hay una manera, ¿alguien puede sugerir la mejor manera de diseñar un marco para ejecutar comandos de shell. Pasar una gran cuerda larga es muy caótico.

+0

¿Alguien? Vamos, alguien debe haber usado ffmpeg con .net –

Respuesta

33

Puede implementar fácilmente una barra de progreso si ejecuta ffmpeg. La salida de ffmpeg mientras se ejecuta es algo así como:

frame= 3366 fps=465 q=31.0 Lsize= 6474kB time=140.35 bitrate= 377.9kbits/s 

Y se actualiza ~ dos veces por segundo. Puede analizar esa línea y obtener los datos que necesita para mostrar el progreso. Cuando se ejecuta en la línea de comando, solo ve una línea que se actualiza todo el tiempo, pero lo que hace ffmpeg es escribir la línea seguida de \ r. Es por eso que no ves líneas múltiples. Sin embargo, al usar StreamReader.ReadLine() en la salida de error del programa, se obtiene una línea por cada actualización.

A continuación se muestra un código de muestra para leer la salida. Tendría que ignorar cualquier línea que no comience con 'frame', quizás use BeginErrorReadLine() + ErrorDataReceived si quiere que las líneas de lectura sean asincrónicas, etc., pero se entiende (lo he probado):

using System; 
using System.Diagnostics; 
using System.IO; 

class Test { 
     static void Main (string [] args) 
     { 
       Process proc = new Process(); 
       proc.StartInfo.FileName = "ffmpeg"; 
       proc.StartInfo.Arguments = "-i " + args [0] + " " + args [1]; 
       proc.StartInfo.RedirectStandardError = true; 
       proc.StartInfo.UseShellExecute = false; 
       if (!proc.Start()) { 
         Console.WriteLine ("Error starting"); 
         return; 
       } 
       StreamReader reader = proc.StandardError; 
       string line; 
       while ((line = reader.ReadLine()) != null) { 
         Console.WriteLine (line); 
       } 
       proc.Close(); 
     } 
} 
+0

Ahh ... He estado tratando de redirigir a standardOutput ... no error. De repente funciona: P –

+0

+1: He hecho lo mismo en Java y estoy muy, muy satisfecho con los resultados. Sin embargo, hay algunas capturas: al igual que el valor del 'tiempo', puede ser algo así como 100000000 en la salida de la línea de progreso para la primera actualización. Mi intuición dice que es un valor inicializado interno. –

+0

Probablemente sí. Solo use una declaración de predicado para eliminar valores por encima de un cierto rango razonable. Sucio, pero va a funcionar –

6

Hay una biblioteca wrapper sobre FFmpeg para .NET.

+0

"En la actualidad, la decodificación de audio y la codificación son maduras y las capacidades de video están en desarrollo (actualmente tenemos la decodificación de video funcionando pero sin audio sincronizado)." Necesito audio funcionando correctamente. –

+0

Me parece que están en él, pero todavía no está allí ... – Abel

+0

Desafortunadamente, el proyecto no se ha actualizado desde los comentarios anteriores de hace +2 años. Y no hay distribución binaria; debes verificar el código y compilarlo tú mismo. –

2

¿Qué le parece escribir un envoltorio C++/CLI alrededor de la interfaz nativa de ffmpeg y luego llamar a la interfaz del contenedor desde su aplicación?

+1

El compilador de VC no es compatible con muchas construcciones de lenguaje C utilizadas en ffmpeg. El equipo de ffmpeg está interesado en ver si alguien tiene éxito en portar el código a VC. –

2

Acabo de encontrar fflib en sourceforge. Parece bastante prometedor, sin embargo no lo he usado.

+0

cualquier muestra completa? – Kiquenet

Cuestiones relacionadas