fpghost
fpghost

Reputation: 2944

Sound file not playing in PySide app after PyInstaller

In my PySide app, I use the following bit of code to play a wav file:

media = Phonon.MediaObject()
audio = Phonon.AudioOutput(Phonon.MusicCategory)
Phonon.createPath(media, audio)
alarm_file = 'alarm_beep.wav'
f = QtCore.QFile(alarm_file)
if f.exists():
    source = Phonon.MediaSource(alarm_file)
    if source.type() != -1:              # -1 stands for invalid file
        media.setCurrentSource(source)
        media.play()
else:
    logger.debug('Alert media missing: %s' % alarm_file)

This works fine in Ubuntu when I run the Python script but when I compile the app to an exe with Pyinstaller for windows, the sound is not played.

I use the following pyinstaller command

pyinstaller  --onefile --add-data "alarm_beep.wav;." main.py

to attempt to add the media file, but it's to no avail.

The exception in the console is

WARNING: bool __cdecl Phonon::FactoryPrivate::createBackend(void) phonon backend plugin could not be loaded
             WARNING: bool __cdecl Phonon::FactoryPrivate::createBackend(void) phonon backend plugin could not be loaded
             WARNING: bool __cdecl Phonon::FactoryPrivate::createBackend(void) phonon backend plugin could not be loaded
             WARNING: bool __cdecl Phonon::FactoryPrivate::createBackend(void) phonon backend plugin could not be loaded
             WARNING: Phonon::createPath: Cannot connect  MediaObject ( no objectName ) to  AudioOutput ( no objectName ).

Alert media missing: alarm_beep.wav

So obviously it's as if the "alarm_beep.wav" doesn't exist.

Not sure why the add-data command isn't taking care of it?

Upvotes: 0

Views: 840

Answers (1)

apogalacticon
apogalacticon

Reputation: 789

Once the application in bundled, the external files will be saved in a temporary directory, which you will need to reference. See this post for a discussion on referencing these external files. In short, you will need to update the path to your resource file before referencing it:

#resource_path is the relative path to the resource file, which changes when built for an executable
def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath('.')
    return os.path.join(base_path, relative_path)

and in the body of your code:

alarm_file = resource_path('alarm_beep.wav')

Upvotes: 1

Related Questions