YouTube-Like Unmute Button in NuxtJS

Teri Eyenike

The representation of content in video format has grown substantially. It's arguably the primary means of sharing moments with the rest of the world.

YouTube is one of the many platforms online that accepts the streaming and upload of videos, making it easy to watch on any device.

This article highlights how to build a YouTube-like application using Cloudinary in Nuxt.js. A video plays muted on mobile and allows the user to listen to the audio by clicking the unmute button.


The working demo is in a CodeSandbox. Fork and run it to quickly get started.

1<CodeSandbox title="YouTube unmute sound" id="youtube-unmute-sound-c8bpdn" />

Check out the complete source code for reference.


We need to have the following for this post:

  • A Cloudinary account — sign up here for free!
  • Familiarity with Vue.
  • Basic knowledge of JavaScript.

Getting started

To begin, run the following command to create a new Nuxt.js app.

1npx create-nuxt-app unmute-feature

The process above presents a series of prompts that should look like this:

1create-nuxt-app v4.0.0
2 ✨ Generating Nuxt.js project in unmute-feature
3 Project name: accept the default, press Enter
4 Programming language: JAVASCRIPT
5 Package manager: Npm
6 UI framework: Tailwind CSS
7 Nuxt.js modules: N/A
8 Linting tools: N/A
9 Testing framework: None
10 Rendering mode: Universal (SSR / SSG)
11 Deployment target: Static (Static/Jamstack hosting)
12 Development tools: jsconfig.json
13 What is your GitHub username? <your-github-username>
14 Version control system: GIT

With the boilerplate files and folders in place, run the command to start the development environment accessible on http://localhost:3000.

1# change directory to project folder
2 cd unmute-feature
4 # start the development environment
5 npm run dev

Creating the YouTube-like video

Before building the YouTube unmute video feature, we'll use the Cloudinary Video Player, a JavaScript-based HTML5 video player. Navigate to the nuxt.config.js file and include the video player package files from the Unpkg CDN in the head object section.

1export default {
2 ...
3 head: {
4 link: [
5 {
6 href:"", rel:"stylesheet"
7 }
8 ],
9 script: [
10 {
11 src:"",
12 type:"text/javascript"
13 }
14 ]
15 }

Next, in the pages/index.vue file, remove the component <Tutorial /> and add the following code.

2 <div>
3 <div class="relative">
4 <video id="doc-player" muted class="cld-video-player cld-fluid"></video>
5 <button class="absolute bg-blue-700 text-white top-0 left-0 px-3 py-2">Unmute</button>
6 </div>
7 </div>
8 </template>
11 <script>
12 export default {
13 name: 'IndexPage',
14 data() {
15 return {
16 player: null,
17 videoId: 'video-player/early_morning'
18 }
19 },
20 mounted() {
21 this.player = cloudinary.videoPlayer('doc-player', {
22 cloud_name: 'terieyenike',
23 autoplay: true,
24 controls: true
25 })
26 this.player.source(this.videoId)
27 }
28 }
29 </script>

In the code block above, we rendered the Cloudinary Video Player with the video tag and a button that allows for the unmute/mute click event. The muted attribute on the video tag mutes the video.

For the data object property, we pass a set of reactive data such as the player variable set to null and the videoId set to the uploaded video asset with a public ID, early_morning, placed in a folder called video-player.

Finally, we call the lifecycle hook mounted function after the app is mounted on the document object model (DOM). Also included within the mounted function is our Cloudinary cloud name and the video features such as autoplay and the player controls set to true.

Our app should look like the image below.

Adding Button to Listen to Audio

Now that we have successfully set up the video on our browser, we need to create a function that conditionally changes the text from unmute to mute on the button tag based on the user interaction. Doing this will allow us to hear the video.

Let's update our code and include the ref parameter to the video and button tags, which will allow us to reference the HTML element attributes.

2 <div>
3 <div class="relative">
4 <video @click.prevent="unmuteVideo" id="doc-player" ref="video" muted class="cld-video-player cld-fluid"></video>
5 <button @click.prevent="unmuteVideo" ref="text" class="absolute bg-blue-700 text-white top-0 left-0 px-3 py-2">Unmute</button>
7 </div>
8 </div>
9 </template>
11 <script>
12 export default {
13 name: 'IndexPage',
14 ...
15 methods: {
16 unmuteVideo() {
17 const vid = this.$
18 if (!vid.muted) {
19 this.$refs.text.textContent = "Unmute"
20 } else {
21 this.$refs.text.textContent = "Mute"
22 }
23 vid.muted = !vid.muted
24 }
25 },
26 }
27 </script>

From the code above, we have:

  • @click.prevent: a v-on that listens to DOM events and prevents the reloading of the page
  • The unmuteVideo function defined on the Vue instance triggers the muted attribute on the video tag, enabling us to toggle between listening to the audio or not using the refs and changing the button text on each click
  • refs: an object that contains a property for each element pointed by the ref attribute defined in the template

With the YouTube-like video app completed, here's how it should look:


This post showed us the implementation of a YouTube-like app with the "click to unmute" feature on videos, giving users control over whether to listen to the audio.


Teri Eyenike

Software Developer

Teri Eyenike is a software developer interested in making things simple and usable.