如何在C# asp.net中使用FFMPEG获取视频时长

6

我希望使用C#获取视频文件的时长字符串。我在互联网上进行了搜索,但是找到的都是:

ffmpeg -i inputfile.avi

每个人都说要解析持续时间的输出。

以下是我的代码:

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

现在请告诉我如何保存输出字符串并解析视频持续时间。

谢谢和问候,


请看这里:https://dev59.com/WnVC5IYBdhLWcg3wykQt - Robert Harvey
3个回答

7

使用 Media Info DLL 可以获取视频长度的另一种选择。

使用 Ffmpeg:

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

过滤不应该是问题,所以请自行处理。

PS:使用FFmpeg时,您不应读取StandardOutput,而是ErrorOutput。我不知道为什么,但只有这样才能正常工作。


谢谢你的代码,但它没有起作用。我使用了以下代码:'proc.StartInfo.RedirectStandardError = true; string message = proc.StandardError.ReadToEnd();'不过还是要感谢你,因为你向我展示了第一步,最终帮助我成功了。 祝福你! - Hamad

5

FFmpeg是一个有点难以解析的工具,但无论如何,以下是您需要知道的内容。

首先,FFmpeg不支持RedirectOutput选项

您需要做的是,不直接启动ffmpeg,而是启动cmd.exe,将ffmpeg作为参数传入,并通过命令行输出将输出重定向到“监视文件”中...请注意,在while (!proc.HasExited)循环中,您可以读取此文件以获取实时FFmpeg状态,或者如果这是一个快速操作,则只需在最后读取它即可。

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

很好,现在你已经获得了FFmpeg输出的日志。接下来是获取持续时间。持续时间行看起来像这样:

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

将结果清理成一个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();

...然后循环遍历它们,寻找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);
            }
        }

以下是一些可以帮助您解析的代码:

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

抱歉,伙计!我无法理解你的代码。我的输入avi文件将放在哪里,我想要找到它的持续时间?此外,请解释一下你使用的变量,例如“encodeArgs”。这是什么意思? - Hamad
你的代码很好用,可以显示有关FFmpeg的信息。我该如何使用它将我的AVI文件作为输入并获取其信息???无论如何,谢谢你,你做得很好。 - Hamad
如果有一个名为“持续时间”且值为“00:00:00”的元数据,那么安全性并不完善。 - Roman Holzner

1
请查看:
    //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]));
        }
    }

感谢您,Gouranga Das。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接