0

I have an asp.net core API that was recently updated from .net5 to .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:

Unable to load shared library 'Msacm32.dll' or one of its dependencies.

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):

LibVLC could not be created. Make sure that you have done the following:

  • Installed latest LibVLC from nuget for your target platform. Unable to load shared library 'libX11' or one of its dependencies. 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)

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).

NineBerry
  • 26,306
  • 3
  • 62
  • 93
mobearette
  • 377
  • 10
  • 26

3 Answers3

2

I would encourage you to take a look at atldotnet. 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). 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);
sandreas
  • 101
  • 1
  • 7
1

The error you are seeing is because we were assuming that you would display a video on linux, using X11, so we are always initializing X11. See here.

We shouldn't do that for your use case(because you may not have a GUI available). Please report the issue here : https://code.videolan.org/videolan/LibVLCSharp/-/issues or even better, submit a pull request on github or 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.

cube45
  • 3,429
  • 2
  • 24
  • 35
  • That makes sense, I will report the issue, thank you. The error message from that machine that I get after update to .net6 is this: Unable to load shared library 'Msacm32.dll' or one of its dependencies. – mobearette Dec 28 '22 at 07:12
  • That happens in the last fallback and comes from NAudio. My assumption is that the VLC never worked on Linux, and last fallback may have worked because in the old version it didn't require the Msacm32.dll, but I still need to verify this – mobearette Dec 28 '22 at 07:19
1

If you install ffmpeg, you can do this quite easily. ffmpeg comes installed in most linux distros by default, but in case it isn't, you can install it with your favorite package manager.

sudo apt install ffmpeg

To install it in windows, you'll need to download the build files, extract it, and add it to the PATH.

Next, install Xabe.FFMpeg package in your project.

Finally, you can call the static method Xabe.FFMpeg.FFMpeg.GetMediaInfo() to get all information regarding your audio file. Here is a sample snippet that I tested on my linux machine.

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);
        }
    }
}
AzuxirenLeadGuy
  • 2,470
  • 1
  • 16
  • 27