Working with audio and video can be a very daunting task if it's not your area of expertise. Luckily, there are some great tools that help you achieve difficult tasks with little media manipulation experience. In this tutorial, you'll learn how to use one of these tools, FFmpeg, to transcode audio from one format to another from a C# .NET application.
Here’s what you will need to follow along:
- .NET 7 SDK (earlier and newer versions may work too)
- A code editor or IDE (I recommend JetBrains Rider, Visual Studio, or VS Code with the C# plugin)
You can find the source code for this tutorial on GitHub. Use it if you run into any issues, or submit an issue if you run into problems.
Set up FFmpeg
FFmpeg is a command-line interface (CLI) tool capable of decoding, encoding, transcoding, muxing, demuxing, streaming, filtering, and playing a large variety of media. FFmpeg is open source and supported across platforms.
To use it, you'll first need to download and install the binary. You can find some options to download FFmpeg for your operating system on the FFmpeg download page, but I'd recommend you check if FFmpeg is available in your preferred package manager and install it that way.
If you use a package manager, it's likely already installed in your system path. Verify your FFmpeg installation by running the following command:
You should see output that looks like this:
ffmpeg version 5.1.1-1ubuntu2.1 Copyright (c) 2000-2022 the FFmpeg developers built with gcc 12 (Ubuntu 12.2.0-3ubuntu1) configuration: --prefix=/usr --extra-version=1ubuntu2.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-libplacebo --enable-shared libavutil 57. 28.100 / 57. 28.100 libavcodec 59. 37.100 / 59. 37.100 libavformat 59. 27.100 / 59. 27.100 libavdevice 59. 7.100 / 59. 7.100 libavfilter 8. 44.100 / 8. 44.100 libswscale 6. 7.100 / 6. 7.100 libswresample 4. 7.100 / 4. 7.100 libpostproc 56. 6.100 / 56. 6.100
If you don't see output similar to this, locate the folder where the
ffmpeg binary is stored, and add the path to that folder to your
While FFmpeg is capable of accomplishing many different tasks, however this tutorial will focus solely on changing audio from one format to another. For example, run the following command to download classic.mp3 and convert it to a wav-file:
ffmpeg -i https://demo.twilio.com/docs/classic.mp3 classic.wav
-i options told
ffmpeg where to find the input file, which was then followed by the output file; ./classic.wav on your disk. FFmpeg can detect the input file's format by analyzing it, and knows the format to transcode to because of the output file's .wav file extension. Enjoy the song, it's one of my favorites! 🕺
Convert audio files to different formats from .NET
Let's see how you can achieve the same task from .NET.
First, create a C# command-line project using the .NET CLI:
dotnet new console -o ConvertAudioFormats cd ConvertAudioFormats
While you could interact with FFmpeg using the Process APIs or libraries like CliWrap, there's already a very helpful library that wraps the
ffmpeg CLI for you: FFMpegCore.
Add the FFMpegCore NuGet package to your project using this command:
dotnet add package FFMpegCore
Now open the project in your preferred .NET IDE and update the Program.cs file with the following C#:
using FFMpegCore; FFMpegArguments .FromUrlInput(new Uri("https://demo.twilio.com/docs/classic.mp3")) .OutputToFile("classic.wav") .ProcessSynchronously();
This code will do the same as the
ffmpeg command you executed before, but the library makes it a lot more readable and self-explanatory.
Run the project using the .NET CLI:
After running the project, the classic.wav file should appear in your project directory.
If you're running the project from an IDE instead of the CLI, the classic.wav file will be located in the bin/Debug/netX.Y folder, where X and Y are the major and minor version numbers of the targeted .NET framework.
Convert audio streams to different formats
If you don't want to pull the media directly from a URL or disk, you can also use FFmpeg's pipes to pass in data and receive data back without network or file I/O.
Let's recreate the same functionality using the
OutputToPipe methods instead of the
OutputToFile methods, by updating Program.cs as follows.
using FFMpegCore; using FFMpegCore.Pipes; using var httpClient = new HttpClient(); await using var audioInputStream = await httpClient.GetStreamAsync("https://demo.twilio.com/docs/classic.mp3"); await using var audioOutputStream = File.Open("classic.wav", FileMode.OpenOrCreate); FFMpegArguments .FromPipeInput(new StreamPipeSource(audioInputStream)) .OutputToPipe(new StreamPipeSink(audioOutputStream), options => options.ForceFormat("wav")) .ProcessSynchronously();
The code above opens a network stream,
audioInputStream, to stream the audio from the internet, and creates a file stream,
audioOutputStream, to write the audio to. As you aren't passing an output file name directly to FFmpeg, FFmpeg cannot deduce the desired format, so you need to tell FFmpeg to use the
wav format using
Run the project again:
The result should be the same. So what's the big deal? Well, if the default
OutputToX methods don't fit your needs, using
Stream's gives you the ultimate flexibility to provide input to FFmpeg and where to write the output to.
You've just scratched the surfaces of what FFmpeg is capable of. There are a ton of extra arguments and capabilities to manipulate media files.
When building Twilio applications, FFmpeg can be a very useful tool too, for example, here's a tutorial that transcribes audio files sent through WhatsApp using the OpenAI Whisper API, but the Whisper API doesn't support the .ogg format that WhatsApp uses, so FFmpeg is used to convert the audio to a wav-file before the audio is passed to the Whisper API.
We can't wait to see what you build. Let us know!
Niels Swimberghe is a Belgian American software engineer and technical content creator at Twilio, and a Microsoft MVP in Developer Technologies. Get in touch with Niels on Twitter @RealSwimburger and follow Niels’ personal blog on .NET, Azure, and web development at swimburger.net.