Skip to content
SFXMint

Sound effects for Pygame

By · Published · Code tested with WAV files on pygame 2.6.1 (SDL 2.28.4), Python 3.11, macOS, on 2026-10-31

Your Pygame game runs, but it is silent. Below is an arcade set (pickup, jump, hit, power-up, laser, explosion, game over) and the code that plays it, which we ran with this set's WAV files before publishing. The part most tutorials skip is at the end: what happens when ten pickups land in the same frame. The sounds are CC0, so the game can be sold.

The whole thing as a game you can run, with mute, volume and a headless test: pygame-arcade on GitHub.

Press play to hear each event; OGG downloads one free. All 7 are in the retro game sound set.
PlayEventSoundLengthDownload
Coin / item pickupDouble-Chime 8-Bit Coin Pickup 52 (No Reverb)1.1 s
JumpClassic Rising 8-Bit Video Game Jump 490.33 s
Hit / damageShort Zap Retro Game Hit 020.13 s
Power-upMajor-Key 8-Bit Power-Up 500.30 s
Shoot / laserPiercing 8-Bit Laser Shot 510.73 s
ExplosionShort Burst 8-Bit Explosion 650.41 s
Game overSlow 8-Bit Game Over Jingle 650.38 s

1. Put the files next to your code

From the folder with your game's .py file:

npx sfxmint add --set retro-game --format wav --out assets/sounds

That writes pickup.wav, jump.wav, hit.wav, powerup.wav, laser.wav, explosion.wav and gameover.wav, plus a SOUNDS.md with each sound's page and license. WAV comes with the download pack ($9.90 for 30 days, one payment), so this command takes a pack's key in SFXMINT_API_KEY. A puzzle or platformer game may fit the puzzle or platformer set better; the command takes their names too.

No pack? pygame.mixer.Sound documents OGG as well as WAV, and this set comes as free OGG:

npx sfxmint add --set retro-game --format ogg --out assets/sounds

Then change .wav to .ogg in the code below. We ran that code with WAV, and a library MP3, WAV and OGG each load and play in pygame.mixer.Sound on pygame 2.6.1; the pygame-arcade example's test also checks that its OGG files load. A whole set takes a free account's API key in SFXMINT_API_KEY; without a key you get the first 5 sounds. No Node.js? Use the download buttons in the table and rename the files the same way.

2. Load once, play by name

from pathlib import Path
import pygame

pygame.mixer.pre_init(44100, -16, 2, 512)  # before init; matters on pygame 1.9
pygame.init()
pygame.mixer.set_num_channels(16)          # see "pitfalls" below

SOUND_DIR = Path(__file__).parent / "assets" / "sounds"
SOUNDS = {
    name: pygame.mixer.Sound(SOUND_DIR / f"{name}.wav")
    for name in ("jump", "pickup", "hit", "powerup", "explosion", "gameover")
}

def play(name):
    SOUNDS[name].play()

# In the game loop:
#   if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
#       player.jump(); play("jump")
#   if player.rect.colliderect(coin.rect):
#       play("pickup")

Loading the six files took under a millisecond in our run, so doing it at startup costs nothing; doing it inside the loop reads the disk every frame. The path is built from the script's folder, so the game also runs when started from somewhere else.

3. Looping music or ambience

npx sfxmint add rain --format ogg --out assets/sounds
pygame.mixer.music.load(SOUND_DIR / "rain.ogg")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)   # -1 loops forever

# Later: pygame.mixer.music.fadeout(1500)

pygame.mixer.music streams one long file and does not use the effect channels. Other loops: forest, wind, dark ambience.

4. A volume setting

def set_sfx_volume(value):          # 0.0 to 1.0, from your settings menu
    for sound in SOUNDS.values():
        sound.set_volume(value)

def set_music_volume(value):
    pygame.mixer.music.set_volume(value)

5. Pitfalls we hit while testing

  • Sounds are dropped, silently. With the default 8 channels, ten pickups played in the same frame started only 7; the other calls returned None and made no sound and no error. That is why the code raises the count to 16. To keep one important sound from being dropped, reserve a channel for it: pygame.mixer.set_reserved(1) and play it with pygame.mixer.Channel(0).play(sound).
  • get_length() is the file, not the sound. It returned 1.00 s for the jump, whose page says 0.35 s of sound in a 1 s file; the rest is silence. Do not time animations or cooldowns from get_length(): use the length of sound each page lists.
  • The browser needs OGG. pygbag's wiki asks for every audio file in OGG, not WAV or MP3. Download the set again with --format ogg, or keep WAV on desktop and switch by platform:
import sys

EXT = "ogg" if sys.platform == "emscripten" else "wav"
SOUNDS = {name: pygame.mixer.Sound(SOUND_DIR / f"{name}.{EXT}") for name in ("jump", "pickup")}

In the browser, like every web game, sound starts only after the player's first click or key.

6. If ChatGPT or Claude wrote your game

Put the files in assets/sounds first, then give it this:

Add sound effects to my Pygame game using the sound files in assets/sounds
(jump, pickup, hit, powerup, explosion, gameover). Load each file once at startup into a dict,
call pygame.mixer.set_num_channels(16) after pygame.init(), and play the right sound at each
event in the game loop. Add a volume setting for effects and one for music.

With Claude Code, Cursor or Codex, the assistant can fetch the files itself: see add sound effects with a coding assistant.

Questions

WAV, OGG or MP3 for pygame.mixer.Sound?

On pygame 2.6 all three load into a Sound. WAV is the safe default for desktop; a browser build with pygbag needs OGG. WAV comes with the download pack ($9.90 for 30 days, one payment); MP3 and, for older sounds, OGG download free.

Why is there a delay before each sound?

On pygame 1.9 the mixer's default buffer was 4096 samples, which you can hear; pygame.mixer.pre_init(44100, -16, 2, 512) before pygame.init() fixes it, and pygame 2 already defaults to 512. If a sound still starts late, the file begins with silence: each sound page shows how long its audible part is.

Do I need str() around a pathlib.Path?

Not on pygame 2.6: pygame.mixer.Sound and pygame.mixer.music.load both took a Path in our test. str() does no harm if you support older versions.

Can I use these sounds in a game I sell?

Yes, they are CC0. See CC0 sound effects for commercial games for what that allows and the AI disclosure Steam and itch.io ask for.