I came across a problem the other day where I needed to play a sound file in a Blazor WebAssembly application, but there were very limited resources as to how to do this. So, once I figured it out, I also figured that someone else was going to have this problem.

(Even if that person is just me in the future).

A stylized picture of a moving sidewalk, with lights elongated and shiny glass panels to the left and right.
Future me arriving in three... two... one... Photo by Tomasz Frankowski / Unsplash

Let's see how to play a sound in Blazor!

The Sample Project

As always, there's a sample project on GitHub that has the code we're going to write in this post. Check it out!

exceptionnotfound/BlazorSoundDemo
Contribute to exceptionnotfound/BlazorSoundDemo development by creating an account on GitHub.

The Steps

There are five steps we need the ability to play a sound in Blazor:

  1. An HTML <audio> element.
  2. A JavaScript method to play the audio.
  3. An instance of IJSRuntime injected to our Blazor component.
  4. A C# method that uses IJSRuntime to invoke the JavaScript method.
  5. An HTML element that invokes the C# method when clicked.

Step 1 - The <audio> Element

Let's start with the markup we need for our <audio> element:

<audio id="roar" src="{audioSource}" />

This element tells the browser to render a simple media player to our HTML page.

Step 2 - JavaScript Method to Play Audio

We can now create a new JS file which will have our method that will play the audio element. We'll do this by adding a method PlaySound to the window object:

window.PlayAudio = (elementName) => {
    document.getElementById(elementName).play();
}

In the demo project, this file is called sounds.js, so we also need to include the file in a <script> element on the index.html page:

<!DOCTYPE html>
<html>

<head>
    <!--Head elements -->
</head>

<body>
    <!-- Other body elements -->
    <script src="js/sounds.js"></script>
</body>

</html>

Step 3 - Injecting the JSRuntime

Because we need Blazor to invoke JavaScript methods in order to play sounds, we must inject an instance of JSRuntime to our Blazor component. Here's the markup for our Blazor component:

@page "/"
@inject IJSRuntime _jsRuntime;

@code  {
    //TODO
}

<h1>Blazor Sound Demo</h1>

<p>To play the sound, click the button: <button id="soundButton">Click me!</button></p>

<audio id="roar" src="../sounds/lion-roaring.ogg" />

Note that the <button> element is not wired up to anything that will play a sound just yet; we need the C# method first.

Step 4 - C# Method to Invoke JS

The final piece we need is a C# method on the Blazor component that will use IJSRuntime to invoke our PlayAudio method. Here's the C# method:

@code  {
    public async Task PlaySound()
    {
        await _jsRuntime.InvokeAsync<string>("PlayAudio", "roar");
    }
}

Note that we are passing the ID of the audio element on the page, so this method is reusable if we want to have more than one sound on the page.

Step 5 - HTML Button

The last piece is to wire up the <button> on the Blazor component to invoke this method when it is pressed; we do this using the Blazor-specific @onclick attribute:

<p>To play the sound, click the button: <button id="soundButton" @onclick="PlaySound">Click me!</button></p>

With all of that in place, our Blazor app can now play sounds!

To make our app even more useful, there are a couple of options we could also choose to implement.

Option 1: Loop the Sound

If you want to have the audio file automatically start over once it is finished playing, you can add the loop attribute to the <audio> element:

<audio id="roar" src="{audioSource}" loop="loop"/>

Option 2: Stop Playback

We can also implement another control that will stop the <audio> element's playback. This requires several steps.

First, add a new JS method that will pause the element's playback:

window.PauseAudio = (elementName) => {
    document.getElementById(elementName).pause();
}

Then, write a C# method that will invoke that JS method:

@code  {
    public async Task PauseSound()
    {
        await _jsRuntime.InvokeAsync<string>("PauseAudio", "roar");
    }
}

Finally, add a new element to the page:

<p>To make the sound stop playing, click this button: <button id="stopButton" @onclick="StopSound">Stop sound!</button></p>

An Important Note

This particular example is trivially easy to move to pure JavaScript. If that works for you, please do that! No need to make things more complicated than they must be.

However, if you have some Blazor functionality that needs to trigger sounds to play, this solution is a fairly-straightforward way to do it.

Thanks for Reading

Thanks for reading! If this post helped you, I'd like to know about it. Share in the comments!

Happy Coding!