Playing Audio Files in a Blazor Application

With a little JavaScript Interop you can play mp3 files in your Blazor application.

The first step is to gather a few mp3 files you can play in your app. Remember, these will be playing in the browser, so keep the size of the file in mind. You can download my demo audio files here.

Next, create a new Blazor app with Visual Studio 2019. You can use the free Community Edition if you like.

Next, create a sounds folder under the wwwroot folder, and copy your mp3 files to it. For each file, make sure the Build Action property is set to Content, and the Copy to Output Directory property is set to Copy if newer.

audio_demo_shot1.png

For our demo, we’re going to hijack the Index.razor file, replacing it with the following:

@page "/"
@inject IJSRuntime js;

<h1>Play MP3 Files</h1>

<button class="btn btn-primary" @onclick="PlayAudioFile1">Duh</button>
<span>&nbsp;</span>
<button class="btn btn-primary" @onclick="PlayAudioFile2">Dwayne</button>

<audio id="player">
    <source id="playerSource" src="" />
</audio>

@code
{
    async Task PlayAudioFile1()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "/sounds/duh.mp3");
    }

    async Task PlayAudioFile2()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "/sounds/dwayne.mp3");

    }
}

All we’ve done here is set up a couple buttons to execute code that calls into a JavaScript function called "PlayAudioFile”, which we have yet to write. Let’s do that now.

Open your startup HTML file. In Blazor Server this is Pages/_Host.cshtml and for Blazor WebAssembly it’s wwwroot/Index.html.

Add the following to it, just below the script tag that loads the blazor JavaScript file:

    <script>
        window.PlayAudioFile = (src) => {
            var audio = document.getElementById('player');
            if (audio != null) {
                var audioSource = document.getElementById('playerSource');
                if (audioSource != null) {
                    audioSource.src = src;
                    audio.load();
                    audio.play();
                }
            }
        }
    </script>

This code finds your audio player, sets the source file, loads it, and plays it.

Go ahead and try it.

Play Multiple Audio Files Simultaneously

You’ll notice that if you click the first button, and then the second button immediately, the second mp3 file cuts off the first one. You can fix this in a rather inelegant, yet functional, way.

Create another audio tag for the second mp3 so you can play two simultaneously. More files? Just add more tags. You’ll have to modify your code to handle the change.

Change the contents of Index.razor to this:

@page "/"
@inject IJSRuntime js;

<h1>Play MP3 Files</h1>

<button class="btn btn-primary" @onclick="PlayAudioFile1">Duh</button>
<span>&nbsp;</span>
<button class="btn btn-primary" @onclick="PlayAudioFile2">Dwayne</button>

<audio id="player1">
    <source id="playerSource1" src="" />
</audio>
<audio id="player2">
    <source id="playerSource2" src="" />
</audio>

@code
{
    async Task PlayAudioFile1()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "1", "/sounds/duh.mp3");
    }

    async Task PlayAudioFile2()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "2", "/sounds/dwayne.mp3");

    }
}

We’ve added a second audio tag, and named them “player1” and “player2”. We’ve also updated the names of the source elements to “playerSource1” and “playerSource2”.

We’ve also modified our JavaScript calls to pass the player number as a string.

Modify your PlayAudioFile JavaScript function to handle the change:

    <script>
        window.PlayAudioFile = (playerNumber, src) => {
            var audio = document.getElementById('player' + playerNumber);
            if (audio != null) {
                var audioSource = document.getElementById('playerSource' + playerNumber);
                if (audioSource != null) {
                    audioSource.src = src;
                    audio.load();
                    audio.play();
                }
            }
        }
    </script>

Now you have two “channels” with which to play audio files. Great.

Load and play audio dynamically!

Wouldn’t it be great if we didn’t have to provision these audio controls before using them? With a little more JavaScript we can create them on the fly, load the audio file, and play them. Now the audio files will play completely asynchronously.

Change your Index.razor contents back to the first version minus the audio element:

@page "/"
@inject IJSRuntime js;

<h1>Play MP3 Files</h1>

<button class="btn btn-primary" @onclick="PlayAudioFile1">Duh</button>
<span>&nbsp;</span>
<button class="btn btn-primary" @onclick="PlayAudioFile2">Dwayne</button>

@code
{
    async Task PlayAudioFile1()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "/sounds/duh.mp3");
    }

    async Task PlayAudioFile2()
    {
        await js.InvokeVoidAsync("PlayAudioFile", "/sounds/dwayne.mp3");

    }
}

Now, let’s change the JavaScript function to create the audio tag, set the properties, add it to the document, load the audio, and play.

        window.PlayAudioFile = (src) => {
            var sound      = document.createElement('audio');
            sound.src      = src;
            sound.type     = 'audio/mpeg';
            document.body.appendChild(sound);
            sound.load();
            sound.play();
        }

Enjoy!



Carl Franklin has been a key leader in the Microsoft developer community since the very early days when he wrote for Visual Basic Programmers Journal. He authored the Q&A column of that magazine as well as many feature articles for VBPJ and other magazines. He has authored two books for John Wiley & Sons on sockets programming in VB, and in 1994 he helped create the very first web site for VB developers, Carl & Gary's VB Home Page.

Carl is a Microsoft MVP for Developer Technologies, and co-host of .NET Rocks!, one of the longest running podcasts ever (2002). Carl is also an accomplished musician and audio/video producer. He started Pwop Studios in 1999 as a record label for his first album, a collaboration with his brother Jay: Strange Communication. Franklin Brothers released Lifeboat To Nowhere in 2011, which has met with rave reviews. In 2013, Carl released his first solo album, Been a While, which features a tune with John Scofield on guitar, as well as an incredible group of musicians local to New London, CT.

Pwop Studios is a full-service audio and video post production studio in New London, CT, where Carl records and produces the podcasts as well as music and video projects - both for himself, Franklin Brothers Band, and the public.