Skip to content
SFXMint

Sound effects for visual novels and Ren'Py

By · Published · Code tested in Ren'Py 8.5.3 on macOS, on 2026-10-31

A visual novel lives on a few small sounds: the blip as a line types out, a knock before someone walks in, rain behind a quiet scene, a heartbeat when it turns tense, and the click of each choice. Below are thirteen of those, free and CC0, each one a page to play and download, and the Ren'Py code that plays them. We ran every block in a test project before publishing, and it caught three things the documentation does not warn about: they are in steps 5 and 6.

1. The sounds a visual novel uses

Each link opens a page with several versions to play and compare; the name in brackets is the event for the command in step 2.

Dialogue

Moving between scenes

Backgrounds that loop

The menus need a click, a hover and a confirm. This set plays them in place:

Soft menu sounds; hover, click and confirm are the ones a VN menu needs. All 12 are in the soft ui sound set.
PlayEventSoundLengthDownload
Button click / tapWooden User Interface Click 560.15 s
Hover / focus tickSubtle Interface Hover Tick 150.09 s
Toggle / switchSoft Toggle Switch Flip 54 (No Reverb)0.32 s
Swipe / page transitionSubtle Interface Swipe Whoosh 50 (No Reverb)0.73 s
Small feedback popGentle Interface Pop 570.07 s
Menu selectionShort Menu Selection Blip 120.06 s
Dialog / modal openRising Whoosh Modal Dialog Open 330.67 s
Alert / needs attentionDigital Alert Tone 020.81 s
Notification chimeTriple-Tone Notification Chime 52 (No Reverb)0.65 s
Confirm / positive actionSingle Soft Confirmation Tone 67 (No Reverb)0.16 s
Success / task completedWarm Gentle Success Chime 68 (No Reverb)0.93 s
Error / invalid inputMuted Thud-Like Error Buzz 621.3 s

2. Put the files in game/audio

From the project folder (the one with game/), one command writes these as MP3, each file named after its event:

npx sfxmint add dialogue-blip gasp laugh heartbeat door-open knock footsteps-wood page-turn vibrate rain room-tone wind dark-ambience click hover confirm --out game/audio

Next to the files is a SOUNDS.md listing each sound's page and license; move it out of game/ before you build. All 16 take a free account's API key in SFXMINT_API_KEY; without a key you get the first 5. Or download single files from the pages above and drop them into game/audio.

3. Play sounds from your script

label start:
    scene bg room
    play music "audio/rain.mp3" fadein 2.0   # the music channel loops
    "The rain hasn't stopped all day."

    play sound "audio/knock.mp3"
    "Someone is at the door."

    play sound "audio/door-open.mp3"
    play audio "audio/footsteps-wood.mp3"     # audio: overlaps other sounds
    "..."

    stop music fadeout 3.0
  • play sound plays once on the sound channel; a second play sound replaces the first.
  • play audio plays once and can overlap anything else, which suits footsteps under a door.
  • play music loops until stopped; fadein and fadeout take seconds.
  • Short names read better: define audio.knock = "audio/knock.mp3", then play sound knock.

4. Background sound alongside music

Rain under a music track needs its own looping channel. Register one on the effects mixer, so the player's sound volume slider covers it:

init python:
    renpy.music.register_channel("ambience", mixer="sfx", loop=True)

label rooftop:
    play music "audio/theme.ogg"
    play ambience "audio/wind.mp3" fadein 2.0
    "It's colder up here."
    stop ambience fadeout 2.0

5. Menu and button sounds

Give every button a hover and a click sound in one place, for example at the end of screens.rpy:

style button:
    hover_sound "audio/hover.mp3"
    activate_sound "audio/click.mp3"

This does not reach the choice menu. In the default screens.rpy (Ren'Py 8.5), choice_button is declared is button and then again is default; the second one wins, so choices inherit nothing from button. Give them their own:

style choice_button:
    hover_sound "audio/hover.mp3"
    activate_sound "audio/click.mp3"

The same goes for any style in that file declared is default; check the parent before you expect it to inherit.

6. Text blips while a line types

A character callback runs as a line is shown. Start a looping blip once the text begins to type, and stop it when the line has finished. Play it on a channel of its own:

init python:
    renpy.music.register_channel("blip", mixer="voice", loop=True)

    def blip(event, interact=True, blipfile="audio/dialogue-blip.mp3", **kwargs):
        if not interact:
            return
        if event == "show_done":
            renpy.music.play(blipfile, channel="blip")
        elif event in ("slow_done", "end"):
            renpy.music.stop(channel="blip")

define m = Character("Mina", callback=blip)
define k = Character("Kai", callback=blip, cb_blipfile="audio/blip-low.mp3")

The cb_ prefix passes a different blip to each character, so voices are told apart: download a lower one as blip-low.mp3. The voice mixer puts blips under the player's voice volume slider.

  • Why not renpy.sound.play, as Ren'Py's own example does? The blip then shares the sound channel with play sound. In our test, the knock from step 3 was still playing when Kai's line began, and the blip replaced it at once. On its own channel the knock plays out.
  • A new project shows text instantly, so the blip starts and stops at once and is never heard: the template's options.rpy has default preferences.text_cps = 0. Set a speed there, for example 40 characters a second; in our test a 32-character line then blipped for 0.8 s. Players who already ran the game keep their own Text Speed setting.
  • Sound setup in its own file needs init -1. Ren'Py runs files in name order, so a sounds.rpy holding blip() runs after script.rpy defines the characters that use it, and the game stops with NameError: name 'blip' is not defined. Write init -1 python: instead of init python: there.

All of this as a project you can launch and test: renpy-visual-novel on GitHub.

Where the code comes from

Every statement above follows the Ren'Py documentation and ran in Ren'Py 8.5.3 on macOS, on 2026-10-31, in a test project that played through every line, logged what each channel was playing, and checked the button and choice styles:

Questions

Which audio format does Ren'Py play?

Ren'Py plays OGG Vorbis, Opus, MP3, WAV and FLAC. MP3 files from the library play as they are; convert to OGG or Opus if you want the smallest build.

Where do the files go in a Ren'Py project?

In game/audio. Paths in your script are relative to the game folder, so game/audio/door-open.mp3 is "audio/door-open.mp3".

Why does a second sound stop the first?

The sound channel plays one file at a time. Use play audio for sounds that may overlap, or register a channel of your own for a loop that should keep going.

Can I sell my visual novel with these sounds?

Yes, they are CC0. Steam and itch.io ask you to disclose AI-generated content; CC0 sound effects for commercial games covers both.