如何在C#中获取MP3的长度

9

是的,这是这个问题的完全重复,但给出并接受的答案链接对我不起作用。它返回不正确的值(一个2分钟的MP3将被列为1'30,3分钟为2'20),没有明显的模式。

所以再来一次:如何使用C#获取MP3的长度?

或者

我在MP3Header类中做错了什么:

MP3Header mp3hdr = new MP3Header();
bool boolIsMP3 = mp3hdr.ReadMP3Information("1.mp3");
if(boolIsMP3)
  Response.Write(mp3hdr.intLength);

这是一种重复的问题;我在这里尝试回答了:https://dev59.com/N0bRa4cB1Zd3GeqPww4u#13269914 - Daniel Mošmondor
7个回答

13

显然,这个类使用fileSize / bitRate来计算持续时间。这只适用于常定比特率,我猜测你的 MP3 是可变比特率...

编辑:查看 TagLib Sharp,它可以为你提供持续时间。


看起来是恒定比特率(见我在Jon答案上的评论)。我该如何测试这个? - marcgg
关于你的修改:taglib可以获取时长吗?那太棒了,我现在就去检查一下。 - marcgg
它只返回0...我猜我得到的文件编码方式很奇怪,这可以解释所有的问题。我想我会找到一个解决方法。 - marcgg
TagLib Sharp 给我的结果只有真实时长的 70%。 - pupeno
现在几乎每个人在使用音乐时都会采用可变比特率。 - Joe Phillips

4
你是如何确定那些“错误”的MP3文件长度的呢?我经常发现头部信息可能会出错:例如,有一个特定版本的LAME就存在这个问题。
如果在Windows资源管理器中查看文件属性,会显示什么?

一个例子:MPEG Layer 3音频,持续时间1:29,比特率:128kbps,音频速率:44kHz。该函数会找到类似于1:12的持续时间。我将无法控制上传到系统的MP3类型,因此我需要它能够在任何编码/比特率/其他方面正常工作。 - marcgg
在使用taglib进行测试后,我认为我得到的MP3文件有些混乱或编码不同...我会想办法解决这个问题(请参阅我对Jon和Thomas答案的其他评论)。 - marcgg
4
我认为你应该接受Thomas的答案,因为它更普遍适用。 - Jon Skeet
@marcgg:你需要一个使用mpg123并能够确定确切的mp3文件持续时间的代码示例吗? - Daniel Mošmondor

3

我封装了mp3解码库,并使其可供 .net 开发人员使用。您可以在这里找到它:

http://sourceforge.net/projects/mpg123net/

包含将mp3文件转换为PCM和读取ID3标签的示例。
我猜你可以用它来读取mp3文件的时长。最坏的情况是你需要读取所有帧并计算持续时间 - VBR文件。
要准确确定mp3的持续时间,你必须读取所有帧并从它们的持续时间中计算出总持续时间。因为人们会在mp3文件中加入各种“元数据”,所以如果你通过比特率和文件大小来估计,你会猜错很多情况。

1

无法估计VBR文件的长度。它内部的每个mp3帧都可能具有不同的比特率,因此从读取文件的任何部分,您都无法知道文件的任何其他部分的数据密度。确定VBR mp3的确切长度的唯一方法是完全解码它,或者(如果您知道如何)逐个读取所有帧的标头,并收集它们的解码持续时间。

仅当您使用的CPU是需要节省的珍贵资源时,才会使用后一种方法。否则,请解码整个文件,您将获得持续时间。

您可以使用我的mpg123端口来完成此任务:http://sourceforge.net/projects/mpg123net/

更多信息:许多mp3文件都添加了“附加内容”,例如id3标签,如果您不浏览整个文件,则可能会错误地在持续时间计算中使用该标签。


0
这是我使用sox音频处理库的C#解决方案。
public static double GetAudioDuration(string soxPath, string audioPath)
{
    double duration = 0;
    var startInfo = new ProcessStartInfo(soxPath,
        string.Format("\"{0}\" -n stat", audioPath));
    startInfo.UseShellExecute = false;
    startInfo.CreateNoWindow = true;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    var process = Process.Start(startInfo);
    process.WaitForExit();

    string str;
    using (var outputThread = process.StandardError)
        str = outputThread.ReadToEnd();

    if (string.IsNullOrEmpty(str))
        using (var outputThread = process.StandardOutput)
            str = outputThread.ReadToEnd();

    try
    {
        string[] lines = str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
        string lengthLine = lines.First(line => line.Contains("Length (seconds)"));
        duration = double.Parse(lengthLine.Split(':')[1]);
    }
    catch (Exception ex)
    {
    }

    return duration;
}


0

我会考虑使用外部应用程序来完成这个任务。可以尝试使用Sox,并运行通过使用soxi(无exe)执行的程序版本,然后尝试解析该输出。鉴于您的选择,除非此功能是您正在进行的核心工作,否则最好相信已经花费时间解决mp3文件中所有奇怪问题的其他人。祝你好运!


sox 对于我想做的事情来说有点过头了,你不觉得吗? - marcgg
是的,但如果它每次都能正常工作,你可以继续生活,那不是值得的吗? - Jon
我想我只需另想办法。所有这些都是要发送到Flash播放器,但我知道如何在Flash中获取持续时间,所以一旦文件被发送,我就可以弄清楚。感谢您的答案! - marcgg

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