zoukankan      html  css  js  c++  java
  • 获取音、视频时长(NAudio,Shell32,FFmpeg)

    参考网址:https://blog.csdn.net/u013810234/article/details/57471780

    以下为本次测试用到的音、视频格式:

    audio :”.wav;.mp3;.wma;.ra;.mid;.ogg;.ape;.au;.aac;”;

    vedio :”.mp4;.mpg;.mpeg;.avi;.rm;.rmvb;.wmv;.3gp;.flv;.mkv;.swf;.asf;”;

    Note:
    1. 测试音、视频均为对应格式的有效文件(下载自地址:包含了各种可供测试音视频格式,且不断更新中。。);
    2. 若某音/视频时长为0,表示对应库、组件无法解码文件,即不支持该格式;
    3. 类之间的关系:定义了Duration父类,三个测试方案均继承自Duration,并重写父类GetDuration方法。

    获取时长父类

    public abstract class Duration
    {
    /// <summary>
    /// Abstract method of getting duration(ms) of audio or vedio
    /// </summary>
    /// <param name="filePath">audio/vedio's path</param>
    /// <returns>Duration in original format, duration in milliseconds</returns>
    public abstract Tuple<string, long> GetDuration(string filePath);

    /// <summary>
    /// Convert format of "00:10:16" and "00:00:19.82" into milliseconds
    /// </summary>
    /// <param name="formatTime"></param>
    /// <returns>Time in milliseconds</returns>
    public long GetTimeInMillisecond(string formatTime)
    {
    double totalMilliSecends = 0;

    if (!string.IsNullOrEmpty(formatTime))
    {
    string[] timeParts = formatTime.Split(':');
    totalMilliSecends = Convert.ToInt16(timeParts[0]) * 60 * 60 * 1000
    + Convert.ToInt16(timeParts[1]) * 60 * 1000
    + Math.Round(double.Parse(timeParts[2]) * 1000);
    }

    return (long)totalMilliSecends;
    }
    }
    使用NAudio.dll

    下载、引用NAudio.dll;
    由于NAudio本身主要用于处理音频,用其获取视频时长并不合理(仅作统一测试),所以多数格式不支持,不足为奇;
    public class ByNAudio : Duration
    {
    /// <summary>
    /// Get duration(ms) of audio or vedio by NAudio.dll
    /// </summary>
    /// <param name="filePath">audio/vedio's path</param>
    /// <returns>Duration in original format, duration in milliseconds</returns>
    /// <remarks>return value from NAudio.dll is in format of: "00:00:19.820"</remarks>
    public override Tuple<string, long> GetDuration(string filePath)
    {
    TimeSpan ts;
    try
    {
    using (AudioFileReader audioFileReader = new AudioFileReader(filePath))
    {
    ts = audioFileReader.TotalTime;
    }
    }
    catch (Exception)
    {
    /* As NAudio is mainly used for processing audio, so some formats may not surport,
    * just use 00:00:00 instead for these cases.
    */
    ts = new TimeSpan();
    //throw ex;
    }

    return Tuple.Create(ts.ToString(), GetTimeInMillisecond(ts.ToString()));
    }
    }

    NAudio结果:

    使用Shell32.dll

    引用Shell32.dll,在COM里;
    Windows自带的组件,仅支持常见的音视频格式;
    public class ByShell32 : Duration
    {
    /// <summary>
    /// Get duration(ms) of audio or vedio by Shell32.dll
    /// </summary>
    /// <param name="filePath">audio/vedio's path</param>
    /// <returns>Duration in original format, duration in milliseconds</returns>
    /// <remarks>return value from Shell32.dll is in format of: "00:10:16"</remarks>
    public override Tuple<string, long> GetDuration(string filePath)
    {
    try
    {
    string dir = Path.GetDirectoryName(filePath);

    // From Add Reference --> COM
    Shell32.Shell shell = new Shell32.Shell();
    Shell32.Folder folder = shell.NameSpace(dir);
    Shell32.FolderItem folderitem = folder.ParseName(Path.GetFileName(filePath));

    string duration = null;

    // Deal with different versions of OS
    if (Environment.OSVersion.Version.Major >= 6)
    {
    duration = folder.GetDetailsOf(folderitem, 27);
    }
    else
    {
    duration = folder.GetDetailsOf(folderitem, 21);
    }

    duration = string.IsNullOrEmpty(duration) ? "00:00:00" : duration;
    return Tuple.Create(duration, GetTimeInMillisecond(duration));
    }
    catch (Exception ex)
    {
    throw ex;
    }
    }
    }

    Shell32结果:

    使用FFmpeg.exe

    下载FFmpeg.exe;
    异步调用“ffmpeg -i 文件路径”命令,获取返回文本,并解析出Duration部分;
    FFmpeg是对音视频进行各种处理的一套完整解决方案,包含了非常先进的音频/视频编解码库,因此可处理多种格式(本次测试的音、视频格式均可以进行有效解码)。
    public class ByFFmpeg : Duration
    {
    private StringBuilder result = new StringBuilder(); // Store output text of ffmpeg

    /// <summary>
    /// Get duration(ms) of audio or vedio by FFmpeg.exe
    /// </summary>
    /// <param name="filePath">audio/vedio's path</param>
    /// <returns>Duration in original format, duration in milliseconds</returns>
    /// <remarks>return value from FFmpeg.exe is in format of: "00:00:19.82"</remarks>
    public override Tuple<string, long> GetDuration(string filePath)
    {
    GetMediaInfo(filePath);
    string duration = MatchDuration(result.ToString());

    return Tuple.Create(duration, GetTimeInMillisecond(duration));
    }

    // Call exe async
    private void GetMediaInfo(string filePath)
    {
    result.Clear(); // Clear result to avoid previous value's interference

    Process p = new Process();
    p.StartInfo.FileName = "ffmpeg.exe";
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.Arguments = string.Concat("-i ", filePath);
    p.ErrorDataReceived += new DataReceivedEventHandler(OutputCallback);

    p.Start();
    p.BeginErrorReadLine();

    p.WaitForExit();
    p.Close();
    p.Dispose();
    }

    // Callback funciton of output stream
    private void OutputCallback(object sender, DataReceivedEventArgs e)
    {
    if (!string.IsNullOrEmpty(e.Data))
    {
    result.Append(e.Data);
    }
    }

    // Match the 'Duration' section in "ffmpeg -i filepath" output text
    private string MatchDuration(string text)
    {
    string pattern = @"Duration:s(d{2}:d{2}:d{2}.d+)";
    Match m = Regex.Match(text, pattern);

    return m.Groups.Count == 2 ? m.Groups[1].ToString() : string.Empty;
    }
    }


    ffmpeg -i filePath
    ……[mp3 @ 0233ca60] Estimating duration from bitrate, this may be inaccurate
    Input #0, mp3, from ‘2012.mp3’:
    Duration: 00:22:47.07, start: 0.000000, bitrate: 127 kb/s
    Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 128 kb/s
    At least one output file must be specified
    Note:以上为ffmpeg -i 命令的输出值,需要匹配到Duration的时长部分。

    FFmpeg结果:

    Source Code(含测试音、视频文件): Github

  • 相关阅读:
    Junit单元测试
    win7的6个网络命令
    WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS
    WOJ1022 Competition of Programming 贪心 WOJ1023 Division dp
    woj1019 Curriculum Schedule 输入输出 woj1020 Adjacent Difference 排序
    woj1018(HDU4384)KING KONG 循环群
    woj1016 cherry blossom woj1017 Billiard ball 几何
    woj1013 Barcelet 字符串 woj1014 Doraemon's Flashlight 几何
    woj1012 Thingk and Count DP好题
    woj1010 alternate sum 数学 woj1011 Finding Teamates 数学
  • 原文地址:https://www.cnblogs.com/zxtceq/p/10121411.html
Copyright © 2011-2022 走看看