Play audio in Frappe Framework

Hi Everyone,

I’m currently working on a project within the Frappe framework where I’m aiming to incorporate a feature where upon clicking a button in a DocType, a new audio file in MP3 format is generated and played. However, I’m encountering challenges in getting this functionality to work seamlessly within the Frappe environment.

Initially, I attempted to use a Python library like playsound for audio playback, but I realized that this approach wouldn’t suffice for deployment on the server side since it relies on local machine capabilities.

As an alternative, I explored implementing the audio playback functionality on the client-side using JavaScript, leveraging the Audio object. However, I encountered an issue where Frappe’s DOM structure might be causing exceptions, preventing the audio from playing as intended.

Furthermore, I experimented with using Frappe’s built-in sound utility, specifically frappe.utils.play_sound, to trigger audio playback. While this approach seemed promising, I encountered an issue where subsequent clicks on the button would generate new MP3 files in the same location, but the audio playback remained stuck on the initial sound generated when the server was first started.

I’m now seeking guidance on the best approach to achieve dynamic audio playback within the Frappe framework. How can I effectively play audio files on button click events in a Frappe application, ensuring compatibility with server-side deployment and overcoming any potential DOM-related hurdles?

Any insights or suggestions would be greatly appreciated!

Thank you.

Hi there,

Whatever solution you end up going with, it’s just going to be regular frontend design without much Frappe-specific involvement. Frappe doesn’t handle the audio for you, so it’s just a matter of getting the audio file into normal javascript/html.

I’m not sure what you’re encountering as Frappe’s DOM structure. Frappe’s web frontend “Desk” doesn’t do anything particularly unusual with the DOM. Can you be more specific about what problems you are having?

		frm.add_custom_button(__('Play Music'), function() {
			var audio = new Audio('speech.mp3');

			audio.play();
		});

this is the code i wrote in js to play music.

and this is error i got in console.:

Uncaught (in promise) DOMException: Failed to load because no supported source was found.

I’ve not used Audio functions much in HTML, but at first look here it appears that you’ve created an audio node but haven’t actually attached it anywhere. This doesn’t have anything to do with Frappe. You might look up a general tutorial for audio playback and see waht that suggests.

How do i attach an audio node in frappe ?

That’s what I’m saying: you don’t.

Frappe doesn’t have any special DOM manipulation interface. This is just plain old javascript.

1 Like

to be honest… i getting no where.

ok lets start over.
How do i Play mp3 file on a click of button using frappe framework.? (make sure to do this in javascript)

It sounds like you’re new to javascript, which is going to make learning Frappe at the same time potentially challenging.

In any case, I don’t have access to a computer right now, so I can’t test, but you probably want something like this:

const audioNode = new Audio('speech.mp3');
const button = cur_frm.add_custom_button(__('Play Music'), function() {
    audioNode.play();
});
document.querySelector('body').appendNode(audioNode)

(This is completely untested. YMMV!)

1 Like

@peterg i have tried your given code but still got the same error:

Uncaught (in promise) DOMException: Failed to load because no supported source was found.


Uncaught TypeError: document.querySelector(...).appendNode is not a function
    at eval (agents__js:33:34)
    at _action (page.js:605:19)
    at HTMLAnchorElement.<anonymous> (page.js:469:11)
    at HTMLAnchorElement.dispatch (jquery.js:5430:27)
    at elemData.handle (jquery.js:5234:28)

Solution I got for this Problem was: I was trying to load the audio file from my file system. This did’nt work, I had to pass a URL to the audio source.

function playAudio() {
    var audio = document.createElement('audio');
	var uniqueTimestamp = new Date().getTime();
	const sitePath = frappe.urllib.get_base_url()
	audio.src = 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3?timestamp='+uniqueTimestamp;
	audio.play()

}

and i am using uniqueTimestamp because the audio was getting stored in cache and even if i change the url, Previous audio was getting played.
This can happen if the browser caches the audio data from the URL you’re providing.

To prevent caching issues in my JavaScript code while playing audio, I can append a unique query parameter to the audio URL each time you play it.

By appending a unique timestamp to the audio URL each time it is played, I ensured that the browser does not cache the audio data. This prevents the playback of outdated audio files and ensures an accurate representation of the content.