获取音、视频时长(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

原文地址:https://www.cnblogs.com/zxtceq/p/10121411.html

时间: 2024-11-06 03:29:19

获取音、视频时长(NAudio,Shell32,FFmpeg)的相关文章

vue / js使用video获取视频时长

项目中遇到上传视频功能,需要有预览和获取视频时长功能,因之前使用upload(有需要的话可以参考下我之前的文章),这里就不赘述,直接用来上传视频,不过在上传之前和上传成功后的钩子里,获取不到时长: 没有时长怎么办呢,只能用原生JS来获取: 上传成功以后,将成功的路径绑定给video 使用js获取duration并赋给时间参数 这时你会发现,你得到的值是NaN 视频还未加载下来,无法同步获取到,使用定时器即可解决 OK了,现在可以获取到了 希望本文对你有所帮助! 原文地址:https://www.

layui上传视频并获得视频时长的方法

layui官方上传视频时并没直接提供获取视频时长的方法,需要我们间接获得 HTML增加一个<video>标签,因为video标签可以帮我们获取视频时长 <video id="videoattr" width="250" height="100" ></video> 当然,你也可以设置隐藏. 然后JS就可以利用<video>的duration来得到时长. //同时绑定多个元素,并将属性设定在元素上 u

统计指定目录下的视频时长

有时间可以写成递归的 1 package org.zln.video.demo1; 2 3 import it.sauronsoftware.jave.Encoder; 4 import it.sauronsoftware.jave.EncoderException; 5 import it.sauronsoftware.jave.InputFormatException; 6 import it.sauronsoftware.jave.MultimediaInfo; 7 8 import ja

javascript 获得以秒计的视频时长

<!DOCTYPE html> <html> <body> <h3>演示如何访问 VIDEO 元素</h3> <video id="myVideo" width="320" height="240" controls> <source src="/i/movie.mp4" type="video/mp4"> <sour

使用ffmpeg获取视频时长等

查看视频信息的命令:ffmpeg -i 视频文件,如下: ffmpeg -i ryzh.mp4 控制台输出: 原文地址:http://blog.51cto.com/4754569/2324534

获取视频时长

//            NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] //                                                             forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; //            AVURLAsset *urlAsset

asp.net 获取mp3 播放时长

1 Shell32 //添加引用:COM组件的Microsoft Shell Controls And Automation //然后引用 using Shell32; //如果出现"无法嵌入互操作类型 请改用适用的接口"报错----修改引用里面的shell32属性嵌入互操作类型改为false public static string GetMP3FileDurationAll(string fileName) { ShellClass sh = new ShellClass(); F

【Android端 APP 启动时长获取】启动时长获取方案及具体实施

一.什么是启动时长? 1.启动时长一般包括三种场景,分别是:新装包的首次启动时长,冷启动时长.热启动时长 冷启动 和 热启动 : (1)冷启动:当启动应用时,后台没有该程序的进程,此时启动的话系统会分配一个新的进程给应用. (2)热启动:程序的进程依然存在,启动时通过已有进程启动进入到Activity显示页面的,就是热启动,或者从Android官网来看我们获取到的其实是温启动时长,就是Activity不存在的情况. (3)新装包的启动时长: 新装包的启动时长,预估是最长的,并且在5.0以下及5.

【d3.js实践教程特别篇】PornHub发布基于d3的网民观看成人视频时长分布交互式地图

学习d3.js(以下都简称d3)也有一段时间了,运行d3做了几个项目.我发现中文的d3教程很少,国外资料多但要求有一定的英文阅读能力(推荐网址:http://bl.ocks.org/mbostock),于是就萌发了写一个d3实际运用系列文章的想法,现在开始付之行动.在系列中,我会用d3+html5 canvas实现一些实际效果(如统计结果展示,地图数据展示等),希望可以跟大家共同学习交流. 代码我公布在git.cschina.com上,大家可以clone到本地运行,地址是:http://git.