Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the video duration using FFMPEG in C# asp.net

I want to get the video file duration in string using C#. I searched the internet and all i get is:

ffmpeg -i inputfile.avi

And every1 say that parse the output for duration.

Here is my code which is

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

Now please tell me how can i save the output string and parse it for the video duration.

Thanks and regards,

like image 315
Hamad Avatar asked Jun 23 '11 17:06

Hamad


People also ask

How do I get video duration in FFmpeg?

Get duration by decoding You can also use ffmpeg to get the duration by fully decoding the file. The null muxer is used so no output file is created. Refer to time= in the next-to-last line of the console output. In this example the input has a duration of 00:57:28.87 .

How do I get the length of a video in C#?

Use a Shell object (found in shell32. dll in the system32 directory) to get the video length from the file metadata. Instantiate a WindowsMediaPlayer object (found in wmp. dll if WMP is installed on your machine), load the file into it and then get the length from the corresponding object property.

How do I find the length of a video in HTML?

To display the duration in a pretty fashion, you'll need to use parseInt and modulus ( % ): // Assume "video" is the video node var i = setInterval(function() { if(video. readyState > 0) { var minutes = parseInt(video. duration / 60, 10); var seconds = video.


3 Answers

There is another Option to get Video Length ,by using Media Info DLL

Using Ffmpeg :

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

Filtering shouldn't be an issue ,so do it you're self.

PS : using ffmpeg you should not read the StandardOutput but ErrorOutput i dont know why ,but it work's only like that.

like image 136
Rosmarine Popcorn Avatar answered Sep 20 '22 00:09

Rosmarine Popcorn


FFmpeg is a little bit of an adventure to parse. But in any case, here's what you need to know.

First, FFmpeg doesn't play well with RedirectOutput options

What you'll need to do is instead of launching ffmpeg directly, launch cmd.exe, passing in ffmpeg as an argument, and redirecting the output to a "monitor file" through a command line output like so... note that in the while (!proc.HasExited) loop you can read this file for real-time FFmpeg status, or just read it at the end if this is a quick operation.

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

Great, now you've got the log of what FFmpeg just spit out. Now to get the duration. The duration line will look something like this:

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

Clean up the results into a 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();

... then loop through them looking for Duration.

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

Here's some code that can do the parse for you:

    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];
    }
like image 29
Brandon Avatar answered Sep 20 '22 00:09

Brandon


Just check it out::

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

With thanks, Gouranga Das.

like image 26
Gouranga Das Avatar answered Sep 21 '22 00:09

Gouranga Das