Przemysław Niedziela
Przemysław Niedziela

Reputation: 588

How can i play sound in a chrome extension

I would like to play sound in chrome extension. How can I do it? What should I write in myscript.js file?

I tried to write in myscript.js:

var audio = new Audio("alarm.wav");
audio.play();

and:

document.write('<audio id="player" src="alarm.wav" >');
document.getElementById('player').play();

but it does not work. I did not add anything more, so there are no unfulfilled conditions.

My manifest.json file:

{
  "name": "Alarm",
  "version": "1.0.0",
  "icons": {"64": "icon64.png"},
  "permissions": [
    "http://site1/",
    "http://site2/"
  ],
  "content_scripts": [
    {
      "matches": ["http://site1/", "http://site2/"],
      "js": ["myscript.js"],
      "run_at": "document_end"
    }
  ],
  "manifest_version": 2
}

If I add button to site in myscript.js file, this button works well, but i can't play sound. My audio file is mp3 and is in the same folder as manifest.json and myscript.js, and my myscript.js is:

var myAudio = new Audio();
myAudio.src = "alarm.mp3";
myAudio.play();

Upvotes: 21

Views: 29839

Answers (6)

Pedro Amaral
Pedro Amaral

Reputation: 21

A little late to the party, but hopefully this will help someone... You can have your script injected to the page, and then play the audio "file" if you put it inline.

const audio = new Audio("data:audio/mp3;base64,<BASE64AUDIO>");
audio.play();

You can find audio to base64 converters online. This solved my problem.

Upvotes: 0

gndps
gndps

Reputation: 851

Intuitive API

const options = {
  type: "basic",
  iconUrl: chrome.runtime.getURL('icons/icon48.png'),
  title: "Notification title",
  message: "test notification",
  sound: "https://samplelib.com/lib/preview/mp3/sample-3s.mp3",
  timeout: 5 // optional 5 seconds timeout of notification
};

chrome.notifications.create(options); // ❌ sound, timeout unknown options
createNotification(options); // ✅ work with following updates

I have combined multiple answers to achieve this:

Setting up the intuitive API

Include these permissions in manifest.json

"permissions": ["notifications", "offscreen"],

Create new file called audio.html

<!DOCTYPE html>
<html>
<head>
<title>Play MP3 File</title>
</head>
<body>
    <audio id="notification-sound" autoplay>
        <source src="sounds/notification.mp3" type="audio/mpeg">
    </audio>
</body>
<script src="updateSounds.js"></script>
</html>

Create new file updateSounds.js

document.addEventListener('DOMContentLoaded', function() {
    const url = new URL(window.location.href);
    const soundUrl = url.searchParams.get('sound');
    const audioElement = document.getElementById('notification-sound');
    audioElement.src = soundUrl;
    audioElement.load();
    audioElement.play();
});

Add these functions to background.js

function createSoundHtml(soundUrl){
    const url = chrome.runtime.getURL('audio.html') + `?sound=${soundUrl}`;
    chrome.offscreen.createDocument({
      url: url,
      reasons: ['AUDIO_PLAYBACK'],
      justification: 'notification',
    });
  }

/**
 * Creates a notification with audio and optional timeout.
 * 
 * @param {string} notificationId - The ID of the notification.
 * @param {object} options - Options for the notification.
 * @param {string} [options.sound] - The URL of the sound to play.
 * @param {number} [options.timeout] - The number of seconds after which the notification will dismiss.
 * @param {function} [callback] - A callback function to be called after the notification is created.
 */
function createNotification(notificationId, options, callback) {
    // Extract sound and timeout options
    const soundUrl = options.sound;
    const timeout = options.timeout;
    let sound;

    // Create sound object if sound URL is provided
    if (soundUrl) {
        sound = true;
    }

    // Remove sound and timeout options from notification options
    delete options.sound;
    delete options.timeout;

    // Create notification and play sound after creation
    chrome.notifications.create(notificationId, options, function(notificationId) {
        if (sound) {
            createSoundHtml(soundUrl);
        }
      if (timeout) {
            setTimeout(function() {
               chrome.notifications.clear(notificationId, function(wasCleared) {
                    if (!wasCleared) {
                        console.error(`Failed to clear notification with ID: ${notificationId}`);
                    }
                });
            }, timeout * 1000); // Convert seconds to milliseconds
        }
        if (callback) {
            callback(notificationId);
        }
    });
}

Usage

now you can create a notification by replacing your chrome.notifications.create with createNotification and it will accept additional params sound to which you can pass a local url (relative to background.js) or a full http url to an mp3 file.

Works as of Feb 2025

Upvotes: 0

frgoe
frgoe

Reputation: 41

Chrome finally added a solution for Manifest V3: The Offscreen API.

To use it, you need to add 'offscreen' to the permissions list in the manifest.json.

Here is an example how you can use it:

function createSoundHtml(){
  chrome.offscreen.createDocument({
    url: chrome.runtime.getURL('audio.html'),
    reasons: ['AUDIO_PLAYBACK'],
    justification: 'notification',
  });
}

The audio.html with the audio.mp3 in the same folder:

<!DOCTYPE html>
<html>
<head>
<title>Play MP3 File</title>
</head>
<body>
    <audio autoplay>
        <source src="audio.mp3" type="audio/mpeg">
    </audio>
</body>
</html>

You can easily combine the createSoundHtml() function call with the Chrome Message API in the service worker.

Upvotes: 4

MagTun
MagTun

Reputation: 6205

If the sound is from an external url like https://upload.wikimedia.org/wikipedia/commons/5/55/En-us-house-noun.ogg, you can simply call the link with an Audio without adding anything to your extension manifest:

var myAudio = new Audio();
myAudio.src = "https://upload.wikimedia.org/wikipedia/commons/5/55/En-us-house-noun.ogg";
myAudio.play();

Upvotes: 2

Kristiyan Tsvetanov
Kristiyan Tsvetanov

Reputation: 1047

According to the documentation, chrome.sound is deprecated in mv3.

An alternative is to use chrome.tts to read a message like "Hey, wake up". :/

Another way is to open a new tab which plays the audio. You could use the chrome.tabs.create() or window.open("https://....", "_blank")

Upvotes: 3

Marco Bonelli
Marco Bonelli

Reputation: 69522

Update: as of Chrome Extension Manifest v3, Chrome Extensions have switched to service workers for background pages, so if you are using Manifest v3, it is no longer possible to play audio directly from the background page of your extension. See also: Play a sound from a Service Worker. If you are still using Manifest v2, then go ahead and read the answer below.


The easiest way to play some sound/music using JavaScript is by using an Audio object: you just need to have the file you want to play inside your extension folder, and you can play it like this:

var myAudio = new Audio(chrome.runtime.getURL("path/to/file.mp3"));
myAudio.play();

You can play using play() and pause using pause().

Remember that if you want to play the sound in a content script (or anywhere else that is not under a chrome://extension URL) you'll have to declare the audio file in the web_accessible_resources manifest field:

"web_accessible_resources": [
    "path/to/file.mp3"
]

Working example

You can download a test extension I made from HERE. It plays a sound through a content script when you click anything inside a stackoverflow.com page.

Upvotes: 39

Related Questions