Quick answer: Track elapsed seconds with pygame.mixer.music.get_pos() before pausing. On resume, call play() + set_pos(seconds) if unpause restarted the track on your platform.

Pausing music and unpausing should resume in place. On some backends/platforms the track restarts — pause/unpause isn’t a guaranteed contract.

Save Position Before Pause

music_pos = pygame.mixer.music.get_pos() / 1000.0   # ms -> s
pygame.mixer.music.pause()

get_pos returns milliseconds since playback started — not absolute position. Track your own offset if you’ve called set_pos before.

Resume by Re-Play

pygame.mixer.music.unpause()

# if unpause didn't actually resume (rare backend), fall back:
if pygame.mixer.music.get_pos() < 50:
    pygame.mixer.music.play()
    pygame.mixer.music.set_pos(music_pos)

If unpause works on your platform, great — the fallback never triggers. Where it doesn’t, play + set_pos restores the spot.

Format Matters

OGG Vorbis supports accurate set_pos. MP3 set_pos is approximate. For seamless resume, prefer OGG — the same recommendation as for gapless looping.

Use a Music Manager

Wrap the get_pos / pause / unpause / re-play logic in one module so the whole game pauses music identically. Easier to fix once if a platform bug crops up.

Verifying

Pause music, wait, unpause — it resumes in place on every target platform. Setting position explicitly via set_pos still works.

“pause/unpause is mostly fine, but track position yourself and fall back to play + set_pos when a backend doesn’t cooperate.”

For long tracks, save the position to disk during the pause — you can resume the same spot even after an app restart.