using Shell32;
using System;
using System.IO;
ShellClass sh = new ShellClass();
Folder dir = sh.NameSpace(Path.GetDirectoryName("MP3绝对路径"));
FolderItem item = dir.ParseName(Path.GetFileName("MP3绝对路径"));
String durationStr = dir.GetDetailsOf(item, 27);    //获取时长字符串(00:00:01)
if (!durationStr.Equals(""))
{
    try {
        String[] durationArray = durationStr.Split(':');    //获取长度  iColumn:27
        int duration = 0;    //时长(毫秒)
        duration += int.Parse(durationArray[0]) * 60 * 60 * 1000;
        duration += int.Parse(durationArray[1]) * 60 * 1000;
        duration += int.Parse(durationArray[2]) * 1000;
    } catch (Exception ex) {
        //log
    }
}

其实代码并不长,但是其中还是遇到了一些挫折,最主要的就是dll的引用问题,顺便也吐槽下,现在搜索技术文章太难了,重复的太多了,而且是各家博客里面都搞一份,基本上搜东西第一篇找到了,后面几篇大部分都是一样的, 如果网站内做查重过滤是不是好一点。

上面代码遇到最大的问题就是Shell32这个命名空间的问题,一开始以为只要引入下就可以了,但是遇到坑了。首先这个Shell32在哪引入?

audiotrack获取时长 获取音频文件的时长_C#音频

引用里面直接搜索是找不到的,把32去掉,会发现有个 Microsoft Shell Controls And Automation

audiotrack获取时长 获取音频文件的时长_C#音频_02

把这个引入试试

audiotrack获取时长 获取音频文件的时长_服务器_03

audiotrack获取时长 获取音频文件的时长_audiotrack获取时长_04

引入后会提示“无法嵌入互操作类型"ShellClass"”,这里对C#熟悉的知道,只要改下“嵌入互操作类型即可”。

audiotrack获取时长 获取音频文件的时长_audiotrack获取时长_05

右键dll“属性”,然后改下类型即可。

audiotrack获取时长 获取音频文件的时长_C#音频_06

现在发现不报错了,于是启起来试试。

运行到这段代码时,报错了。

Folder dir = sh.NameSpace(Path.GetDirectoryName(""));

audiotrack获取时长 获取音频文件的时长_Parse_07

无法将类型为“Shell32.ShellClass”的 COM 对象强制转换为接口类型“Shell32.IShellDispatch6”。此操作失败的原因是对 IID 为“{286E6F1B-7113-4355-9562-96B7E9D64C54}”的接口的 COM 组件调用 QueryInterface 因以下错误而失败: 不支持此接口 (异常来自 HRESULT:0x80004002 (E_NOINTERFACE))。

这个错误,网上有一堆解决方案,就是将Shell32版本升级,因为现在用的是1.0.0.0

audiotrack获取时长 获取音频文件的时长_Parse_08

这个原因没有深究,挺纳闷的这个问题,为啥一直没解决。然后网上也很难下高版本的dll,都需要…搜索过这个问题的应该知道

我这里就直接贴上来,省的大家去找了,版本是1.2.107.0的。

下载地址 注意,如果就这样把代码放到服务器上了,还是无法获取音频时长的,会发现

dir.GetDetailsOf(item, 27);

获取到的始终都是空的。

解决方法就是服务器上需要添加角色和功能

audiotrack获取时长 获取音频文件的时长_音频时长_09

到达选择功能页面,将优质Windows音频视频体验勾上,然后点击安装。

audiotrack获取时长 获取音频文件的时长_服务器_10

但是,这里还需要重启服务器才能安装完成。对于线上服务器来说,这不太可能,所以这套方案可以用在,新服务器上,或者服务器重启不影响业务的情况下。

还有种方案就是使用ffmpeg去获取时长信息,通过命令获取文件信息

ffmpeg.exe -i test.mp3

audiotrack获取时长 获取音频文件的时长_Parse_11

在将数据截取出来就可以了

mp3Info.Substring(mp3Info.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00").Length);