Twine: HTML5 sound macros

Here's version 1.1.1 of some Twine macros to play sound files with HTML5 audio.

These macros accept either strings or string variables as their first argument. I recommend you set the filenames to specific variables and then use those as arguments to the macros.
<<playsound "carolofthebells.mp3" >> plays the file "carolofthebells.mp3" from the start.
<<loopsound $heartbeat >> starts playing $heartbeat, over and over. Note: currently browsers are not that good at looping audio seamlessly - brief silences between loops may occur.
<<fadeinsound $heartbeat >> is identical to loopsound, but fades in the sound over 2 seconds.
<<unloopsound $heartbeat >> makes $heartbeat no longer repeat when it finishes.
<<stopsound "birds.ogg" >> stops playing "birds.ogg". When <<playsound "birds.ogg" >> is used again, it will start from the beginning.
<<fadeoutsound "birds.ogg" >> is identical to stopsound, but fades out the sound over 2 seconds.
<<pausesound "trees.ogg" >> pauses "trees.ogg" at its current location. Use <<playsound "trees.ogg" >> to resume it.
<<stopallsound>> stops all the sounds.

Important instructions:

  1. This macro does not work if you have ROT13 obfuscation enabled in StorySettings - sorry.
  2. Included with the macros is a script that will preload all of the music files as soon as you begin the game. It does this by searching through all of your passages for anything that resembles a music filename - a string in either single or double quotes that ends with ".ogg", ".mp3", ".wav" or ".webm". Then, it will attempt to load that as a file. I consider this to be simpler and more desired behaviour than explicitly requiring you to put preloader macros at the start of the story, but bear this in mind when you write passages.
  3. For legal and free software advocacy reasons, the Apple and Microsoft browsers (Safari, Internet Explorer) do not support OGG format, whereas the cross-platform browsers (Opera, Firefox) do not support MP3. (Google Chrome supports both.) So, you may have to include your music file in both formats. Give each of these files the same name ("ghost.mp3", "ghost.ogg") and store them in the same directory. You only need to <<playsound>> one of these files - if it can't be played, the other one will be used instead. If you only have the music in one format, consider opening the file in Audacity and saving it using "Export as..." in the File menu.


  4. For short sound effects, it would be safe to use "wav" format for them, but be warned - Wavs don't work in Internet Explorer. So, you may need them in MP3 format too. Again, provided both are available, you only need to use one of them in your <<playsound>> macros.
  5. Implementation-wise, this creates an object, "macros.playsound.soundtracks", which stores Audio objects for every found sound file. I'm not sure if this is the most usable method just yet. This may change in future versions.

There's a lot that can be done to expand on this. Something I might add is a way to bind looping sounds to a specific passage tag. So, you could perhaps write <<tagsound "trees" "Howling_Monkeys.mp3">> and then give a passage a tag of "trees", and it will keep looping "Howling_Monkeys.mp3" if you're at such a passage, and stop it when you leave. Also on the list of possibilities: support for base64-encoded sounds (which no one except me will ever use).


Regard this script as public domain using CC0. I don't really care for attribution - if you're using Twine, you're already running code I wrote. It's welcome if you want, but entirely optional.

Version history:

  1. 29-9-14 - Added CC0 "license".
  2. 29-9-13 - Fixed bug where <<stopallsound>> would crash if one of your sounds wasn't loaded correctly (+ maybe other situations).
  3. 4-3-13 - Added <<fadeinsound>> and <<fadeoutsound>>. 1.1.1 edit: No longer force-restarts or force-starts music that's already looping/stopped.
  4. 15-2-13 - Now play and loop no longer explicitly reset the position to the beginning, so playing something that's already playing won't cause it to reset. (Use stopsound to do this on purpose). This also fixes a bug with the back and forward browser buttons.
  5. 15-2-13 - Initial.
Feel free to report any bugs to @webbedspace.

TwineMacros-SoundMacros-1.1.2.txt3.36 KB


Storing files

first of all thank you for so many awesome Twine scripts. It's amazing how many of your scripts I used in my story.

I have a question regarding the audio script. It seems obvious, but I can't find any answer and I can't do it myself, so I'll ask: Is it possible to link to audio files for this script? I get it to work perfectly when the audio files are in the same directory as the story, but what if I just wanted to link to an audio file stored somewhere else. My idea was to have just a .html file that I could send to people, and all they would have to do is click it.

Thanks for all the scripts and all the best,


I'm getting the javascript error "cannot read property 'firstChild' of null"
I'm not sure if that's just because I don't have any audio files in the associated folder, or if I'm doing something horribly wrong or what.
Any advice?

How to fix this error:

How to fix this error: scroll down to the bottom of the javascript and replace where it says "startArea" with "start-area". Capitalization exact.

They must have changed the internal format at some point.

Edit sound java script.

I am sure that most people will figure this out on their own, but it me a couple of tries to notice. The line that has to be changed for some people is "store-area" as opposed to "start-area". It's working like a champ for me now. :-)

Struggling with something simple

Ugh, so I put the attached macro in a separate script, then put <>, and it says "expected ;". I'm really a beginner to this, can you help me? All I would like is for a sound file to play when a certain passage is reached.

Thanks L!

Hi L.
I am so many years too late saying thankyou for this.
I teach game composition at 2 universities and I am not a coder.
I have used this in a slightly different form for 6 years with students and they LOVE making Twines.
What I did was I changed your loopsound to zero volume and then students can make like a stem mixing system on different passages with fade, if they loop everything silently on one passage.
It worked perfectly until 2 years ago. Then I changed the loopsounds to the second passage so they could preload on the first and it worked perfectly again until now ...
Something has changed about browsers in a way I totally don't understand.
Now the files simply don't loop in line.
Any ideas?
Thanks so much. Have loved your work.


Also, I've done experiments.
loopsound "example1.wav"
loopsound "example2.wav"
This now puts example 2 slightly behind. (It never used to.) Something to do with the way a browser is dealing with this now?

A friend of mine thinks it'll need to be rewritten with current.Time.

Anyway, thanks again. My students appreciated this while it lasted. If I can figure out how to rejig, I'll share.