Method for embedding sound files into your RP document

advanced-prototyping

#1

Sometimes your prototype needs sounds, amirite?

I’d been using the method described here and referencing audio files hosted on my own site. It got the job done, but I didn’t love it – external resources are, well, external; they might take a while to load, the domain might be blocked for some reason, and your prototype just isn’t as nicely self-contained.

I was recently poking around and discovered that you can use a data URI as an audio source in html5(!!!), meaning that you can base64-encode an mp3 and then just paste it into the audio element!

Live example | base64-embedded-sound.rp (123.7 KB)

It’s the same exact method, only instead of referencing a file on another site, you’re just including the audio data in the page itself.

Those of us on a Mac can use this terminal command:
base64 filename.mp3 > filename.txt
(or anyone can use a tool like this)

then just copy the contents of filename.txt into your audio player, like so:
javascript:void( $('[data-label="audioPlayer"]').append("<audio controls id='player'><source src='data:audio/mp3;base64,YOUR_BASE64-ENCODED_MP3_HERE' type='audio/mp3'></audio>") );

It’ll be a very long and unsightly string:

Then paste this as an “open external link” action into the event you want to trigger the sound:
javascript:void( $("#player")[0].play() );

Et voila! Hope you all are as chuffed by this as I am.


Autoplay sound on iPad
#2

Thanks for this.

What would the code need to be if I want 2 files?

I tried a few different ways like copying the HTML part of the script and copying the widget but didn’t seem to work.


#3

You can achieve this by adding a player for each sound file within the “append” function:

javascript:void( $('[data-label="audioPlayer"]').append("
<audio controls id='playSound1'><source src='data:audio/mp3;base64,ENCODED_Sound1' type='audio/mp3'></audio>
<audio controls id='playSound2'><source src='data:audio/mp3;base64,ENCODED_Sound2' type='audio/mp3'></audio>
<audio controls id='playSoundX'><source src='data:audio/mp3;base64,ENCODED_SoundX' type='audio/mp3'></audio>
") );

(Might need to clean up the hard breaks)

Tip: For efficiency reasons: save the entire part with the players and the sound data within “append” function as a global variable e.g. append("[[SOUNDDATA]]"), so you have to save the data only once and you can call them anywhere on your prototype (you will need to have a copy of the player parent element on each page you need sound though).

Then you can call each one of them by:

javascript:void( $("#playSound1")[0].play() );
javascript:void( $("#playSound2")[0].play() );
javascript:void( $("#playSoundX")[0].play() );

As far as i know only one can be played at the moment. (Creating another parent element with another player e.g. “playerAudio2” would not work, I tried that)


#4

Hi @Ishllman, great tip. I have it working fine on a Mac with Safari but mixed results with Chrome. Any thoughts on why this might be? I did notice that when I converted the file to Base 64, there is a message at the end “your browser does not support the audio element”… 19%20AM

Thanks in advance for any tips or advice
j


#5

Hi, I got this working in Chrome and Safari. Chrome works on PCs as well. My problem was that I had the data for the Base64 code on “page load”. I moved it up a level and all worked fine. I can now trigger it with a keyboard command.

Thanks@Ishillman


#6

Hey! Sorry @uiguyjohn, I just saw this. Glad to see you got it working. The message between the audio tags, “Your browser does not support the audio element”, is just what shows up for your user if their browser doesn’t support html5 audio. The text can be whatever you want it to be, or nothing at all. In most of my use cases, the actual html5 audio player is hidden, so I don’t typically put a message there.


#7

Hi!
Thank you all for sharing your hard earned knowledge!
I got audio working as described. What I can’t figure out is how to stop playing sound.
Imagine a long slider. When you drag the slider a sound is played. When released, the sound should stop immediately.
You might already have noticed: I’m totally new to coding, thus appreciating your help even more!

Thanks in advance,
Ben


#8

You can use the .pause() javascript method (function.) Just copy the javascript call you are using to play the audio stream and replace .play() with .pause()

If you use .pause() the audio stream can be restarted from that point (same timecode) …by simply calling the .play() method again. If you want the sound to play again from the start, you can stop playing and reset the audio stream by using the .load() method instead of .pause() method.

Using the example above, if this plays your sound,

Then this would stop it:
javascript:void( $("#playSound1")[0].pause() );


#9

Hey mbc66!
That helped a ton.
Maybe you know how to overcome my next hurdle, too!?
For the example above, a base64 coded audio ist used, to have it locally.
This works fine with one sound effect. I’d like to find a way to control multiple sounds, ideally playing simultaneously.
You yourself made a sample file here, but with the files stored online. I need the sources to be kept off-line. Is there any chance to combine the best of these two methods?
I hope it’s just a litte line, that a know-nothing like me just could not come up with.

Again, thank you. I appreciate you taking your time for me.
Greetings from Germany,
Ben


#10

The post from @ProtoAlex earlier in this thread shows how this can be done. I guess it doesn’t work for playing multiple files simultaneously, and that’s your issue.

Yeah, that was like 5 years ago, and in RP8. I’m kind of surprised it still works. It used an embedded javascript library where I cobbled some custom audio/video functions, using a “javascript injection” method posted by one of the original Axure gurus, Gregor. At the core of it, the javascript code creates an array of audio streams. Each audio stream comes from an mp3 file. These files could be on your local system–a folder on a computer or mobile device, although you might get some performance issues trying to play multiple sounds.

If you are running your prototype on a computer, this would be the easiest thing to try, I think. In my sample RP file you link to above, just replace the online mp3 filenames with your own filenames on the same computer. The trick will be using the correct directory syntax. Easiest thing for this is to publish your prototype locally then put the mp3 files in the same folder as the prototype’s HTML files. Then you can just call the filename itself, e.g., “MySound1.mp3” To test changes (with audio) you’d need to publish locally again instead of using Axure’s Preview option.

Beyond that, you’ll need to roll up your sleeves and get ready for a fair bit of trial and error. …But maybe not new coding. The base-64 approach from @lshillman at the start of this thread essentially translates the audio content from a stream into base-64 text and embeds that into the page. In theory, you should be able to use that text block the same as you would an mp3 filename to point to the audio content. And in theory, you could paste the base-64 text block into any widget and then send a pointer to that to create an audio stream in javascript.

If I lost you here, don’t worry, but it’s leading me to another idea you should be able to easily test. In my sample file, replace the mp3 filenames with your base-64 text --the same long string you pasted in as the <source src=' ...> in the Open Link javascript call.

If I get some more time I’ll try this base-64 conversion again and see if I can get it to work.


#11

I can confirm you can have a lot of base64-encoded files playing simultaneously. I used that method to make this, in which each piano key plays an mp3. When you select a chord from the chord bar under the piano, all the notes play at once—well, okay, they play sequentially, but if your computer is fast enough they ought to sound more or less simultaneous.

I’d post the rp, but at this point it has spaghettified into a completely unreadable mess; even I have trouble with it if I go back to it after a week. But it’s doable!

PS: @mbc66, you’ve been here for nearly ten years and post advanced stuff all the time. I guess there’s no hope of making it past “apprentice level” on this new forum!


#12

@mbc66
Thank you so much. I think I got some homework now!

One question regarding the Base64 thing: The longer the audio, the longer the Base64 code. Right?
What is the actual limit of characters you can enter into the variable/function window? I can’t find any documentation on that.


#13

You won’t find any from Axure, as javascript injection it is not supported.


#14

Hi again!
I got it working all together using the Base64 method. Thanks gain!
Is there anyone having experience in modifying the audio via changing the sampling rate?
I would like to have a tone that changes with the movement of a slider.
Slide right- tone becomes higher, slide left, tone becomes lower. Realtime of course.
Naive idea is to use some math to control the sampling rate in relation to the x- position.
Any suggestions on that would -again- be much appreciated!

Greetings, Ben


#15

You might try experimenting with tone.js:
https://tonejs.github.io/

Or using oscillatorNode in vanilla js:

You could always fake it by using several mp3 files played at different pitches, but that approach would mean you go (for example) directly from a B♭ to a B, rather than “sliding” up to it. But if you don’t want to mess around with javascript, this would definitely be the easiest way to prototype it.