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:
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).
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);
}
}
}