简体   繁体   English

在 Linux 和 .net 上读取 C# 中的音频文件时长 6

[英]Read audio file duration in C# on Linux with .net 6

I have an asp.net core API that was recently updated from .net5 to .net6.我有一个 asp.net 核心 API,最近从 .net5 更新到 .net6。 There is a piece of code that should read a duration of an audio file.有一段代码应该读取音频文件的持续时间。 The code that seems to have worked on previous versions was this:似乎适用于以前版本的代码是这样的:


try
{
    //
    // NAudio -- Windows only
    //
    using var fileReader = new AudioFileReader(filePath);
    return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (DllNotFoundException)
{
    try
    {
        //
        // LibVLCSharp is crossplatform
        //
        using var libVLC = new LibVLC();
        using var media = new Media(libVLC, filePath, FromType.FromPath);
        MediaParsedStatus parsed = Task.Run(async () => await media.Parse(MediaParseOptions.ParseNetwork, timeout: 2000).ConfigureAwait(false)).Result;
        if (parsed != MediaParsedStatus.Done) throw new ArgumentException("Could not read audio file");
        if (!media.Tracks.Any(t => t.TrackType == TrackType.Audio) || (media.Duration <= 100)) throw new ArgumentException("Could not read audio from file");
        return Convert.ToInt32(Math.Ceiling(TimeSpan.FromMilliseconds(media.Duration).TotalSeconds));
    }
    catch (Exception ex) when (ex is DllNotFoundException || ex is LibVLCSharp.Shared.VLCException)
    {
        try
        {
            using var fileReader = new Mp3FileReader(filePath);
            return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
        }
        catch (InvalidOperationException)
        {
            throw new ArgumentException("Could not read audio file");
        }
    }
}

The application was deployed on Linux and, I don't know which part of the code did the exact calculation (I am assuming the VLC part), but since the update to .NET6, all of these fail, and since the last fallback is NAudio, we get the following exception:该应用程序部署在 Linux 上,我不知道代码的哪一部分进行了准确的计算(我假设是 VLC 部分),但是自从更新到 .NET6 后,所有这些都失败了,并且由于最后一个回退是NAudio,我们得到以下异常:

Unable to load shared library 'Msacm32.dll' or one of its dependencies.无法加载共享库“Msacm32.dll”或其依赖项之一。

I am using Windows, but I tried running the app with WSL, and I can't get the VLC part to run either - it always throws the following exception (even after installing vlc and vlc dev SDK):我正在使用 Windows,但我尝试使用 WSL 运行该应用程序,但我也无法运行 VLC 部分 - 它总是抛出以下异常(即使在安装 vlc 和 vlc dev SDK 之后):

LibVLC could not be created.无法创建 LibVLC。 Make sure that you have done the following:确保您已完成以下操作:

  • Installed latest LibVLC from nuget for your target platform.从 nuget 为您的目标平台安装最新的 LibVLC。 Unable to load shared library 'libX11' or one of its dependencies.无法加载共享库“libX11”或其依赖项之一。 In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibX11: cannot open shared object file: No such file or directory at LibVLCSharp.Shared.Core.Native.XInitThreads() at LibVLCSharp.Shared.Core.InitializeDesktop(String libvlcDirectoryPath) at LibVLCSharp.Shared.Helpers.MarshalUtils.CreateWithOptions(String[] options, Func`3 create)为了帮助诊断加载问题,请考虑设置 LD_DEBUG 环境变量:liblibX11:无法打开共享 object 文件:在 LibVLCSharp.Shared.Core.Native.XInitThreads() 处没有此类文件或目录在 LibVLCSharp.Shared.Core.InitializeDesktop(String libvlcDirectoryPath) 在 LibVLCSharp.Shared.Helpers.MarshalUtils.CreateWithOptions(String[] options, Func`3 create)

Is there any clean way to read a duration of an audio file on all platforms?有什么干净的方法可以在所有平台上读取音频文件的持续时间吗? Needless to say, NAudio works like a charm on Windows, and so does the VLC (with the proper nuget package).不用说,NAudio 在 Windows 上工作起来就像一个魅力,VLC 也是如此(使用适当的 nuget 包)。

If you install ffmpeg , you can do this quite easily.如果你安装ffmpeg ,你可以很容易地做到这一点。 ffmpeg comes installed in most linux distros by default, but in case it isn't, you can install it with your favorite package manager. ffmpeg默认安装在大多数 linux 发行版中,但如果没有,您可以使用您最喜欢的 package 管理器安装它。

sudo apt install ffmpeg sudo apt 安装 ffmpeg

To install it in windows, you'll need to download the build files , extract it, and add it to the PATH.要在 windows 中安装它,您需要下载构建文件,解压缩并将其添加到 PATH。

Next, install Xabe.FFMpeg package in your project.接下来,在您的项目中安装Xabe.FFMpeg package。

Finally, you can call the static method Xabe.FFMpeg.FFMpeg.GetMediaInfo() to get all information regarding your audio file.最后,您可以调用 static 方法Xabe.FFMpeg.FFMpeg.GetMediaInfo()来获取有关您的音频文件的所有信息。 Here is a sample snippet that I tested on my linux machine.这是我在 linux 机器上测试的示例片段。

using System;
using System.IO;
using Xabe.FFmpeg;
namespace Program;
public static class Program
{
    public static void Main(string[] args)
    {
        string filename;
        if (args.Length == 0)
        {
            Console.WriteLine("No arguments found! Provide the audio file path as argument!");
            return;
        }
        else if (File.Exists(filename = args[0]) == false)
        {
            Console.WriteLine("Given file does not exist!");
            return;
        }
        try
        {
            var info = FFmpeg.GetMediaInfo(filename).Result;
            TimeSpan duration = info.Duration;
            Console.WriteLine($"Audio file duration is {duration}");
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}

The error you are seeing is because we were assuming thzt you would display a video on linux, using X11, so we are always initializing X11.您看到的错误是因为我们假设您将使用 X11 在 linux 上显示视频,所以我们总是初始化 X11。 See here .这里

We shouldn't do that for your use case(because you may not have a GUI available).我们不应该为您的用例这样做(因为您可能没有可用的 GUI)。 Please report the issue here: https://code.videolan.org/videolan/LibVLCSharp/-/issues or even better, submit a pull request on github or gitlab.请在此处报告问题: https://code.videolan.org/videolan/LibVLCSharp/-/issues或者更好,在 github 或 gitlab 上提交拉取请求。

As for your question of why did it work on .net 5 and not anymore, I'm not sure we have enough info to tell why, because you didn't send us the error message from that machine.至于你的问题,为什么它在 .net 5 上工作,而不是现在,我不确定我们是否有足够的信息来说明原因,因为你没有从那台机器向我们发送错误消息。

I would encourage you to take a look at atldo.net .我鼓励您看看atldo.net It is a small, well maintained completely managed code / cross platform library without any external dependencies and was accurate detecting audio file duration in all of my test cases (more accurate than ffmpeg ).它是一个小型、维护良好的完全托管代码/跨平台库,没有任何外部依赖性,并且在我的所有测试用例中都能准确检测音频文件持续时间(比ffmpeg更准确)。 Most common audio formats are supported.支持最常见的音频格式。

    var t = new Track(audioFilePath);    
    // Works the same way on any supported format (MP3, FLAC, WMA, SPC...)
    System.Console.WriteLine("Duration (ms) : " + t.DurationMs);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM