A place to hold mainly reading notes, and some technical stuff occasionally. 这里主要是一些读书笔记、感悟;还有部分技术相关的内容。
目录[-]
需要用到第三方组件获取多种
格式
的音视频时长,现分别采用NAudio.dll,Shell32.dll,FFmpeg.exe获取音视频的时长,并对比三者对不同格式文件的支持程度;
以下为本次测试用到的音、视频格式:
audio
:”.wav;.mp3;.wma;.ra;.mid;.ogg;.ape;.au;.aac;”;
video
:”.mp4;.mpg;.mpeg;.avi;.rm;.rmvb;.wmv;.3gp;.flv;.mkv;.swf;.asf;”;
Note:
public abstract class Duration
{
/// <summary>
/// Abstract method of getting duration(ms) of audio or video
/// </summary>
/// <param name="filePath">audio/video'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;
}
}
public class ByNAudio : Duration
{
/// <summary>
/// Get duration(ms) of audio or video by NAudio.dll
/// </summary>
/// <param name="filePath">audio/video'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结果:
public class ByShell32 : Duration
{
/// <summary>
/// Get duration(ms) of audio or video by Shell32.dll
/// </summary>
/// <param name="filePath">audio/video'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结果:
public class ByFFmpeg : Duration
{
private StringBuilder result = new StringBuilder(); // Store output text of ffmpeg
/// <summary>
/// Get duration(ms) of audio or video by FFmpeg.exe
/// </summary>
/// <param name="filePath">audio/video'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结果:
If you have any questions or any bugs are found, please feel free to contact me.
Your comments and suggestions are welcome!