0

I compile my Qt Resource Collection (QRC) and import it in my Python project, now I would like to be able to access a file in my QRC using subprocess. How can I do this?

I tried this below, but it does not access the compiled QRC...

import application_rc

test = QUrl("qrc:///resources/sounds/LRMonoPhase4.wav").path()

process = subprocess.Popen(["aplay", test],
                           shell=False, stderr=subprocess.PIPE)
Aaron
  • 759
  • 1
  • 7
  • 15
  • 2
    qrc resources are compressed base64-encoded files that can only be loaded by Qt libraries as long as the resource module file is loaded. This obviously means that you cannot use a QUrl path of a resource as a path for an external program which wouldn't know anything about what modules loaded loaded in python. You *could* write a copy of the resource file you need to disk, but that would make the whole concept of qrc pointless. Is the `aplay` just an example command, or do you need to play an audio file? If that's the case, why can't you use the Qt audio related classes? – musicamante Mar 09 '21 at 20:28
  • Thanks, I am using aplay because there is a bug in Pyside2 for capturing the audiooutputbuffer. – Aaron Mar 09 '21 at 20:33
  • What bug? Is it known/reported? Is it on a specific version you're bound to? Have you considered using pyaudio or simpleaudio as a fallback? – musicamante Mar 09 '21 at 20:38
  • Here is the bug : https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-934?filter=allissues – Aaron Mar 09 '21 at 20:44
  • Do pyaudio and simpleaudio output the level of sound? – Aaron Mar 09 '21 at 20:47
  • @Aaron If you mean the bytes of the sound to be played then python offers many alternatives: https://stackoverflow.com/questions/2060628/reading-wav-files-in-python – eyllanesc Mar 09 '21 at 20:54
  • I can check them out, but I need the sound package to stream data for me to do something like this: https://thumbs.gfycat.com/AgonizingThinAustralianfreshwatercrocodile-max-1mb.gif – Aaron Mar 09 '21 at 21:18
  • @Aaron Those are precisely the bytes: intensity of the sound or, in a mathematical / physical way: the amplitude of the sound wave. please use `@username` – eyllanesc Mar 09 '21 at 21:20
  • okay understood – Aaron Mar 09 '21 at 21:40

1 Answers1

2

QResource is only a resource that is known by Qt, so other technologies do not know how to handle the .qrc scheme, so in this case you must create a temporary file where you save the audio and aplay can use it:

import subprocess
from PySide2.QtCore import QFile, QFileInfo, QIODevice, QTemporaryFile
import application_rc


filename = ":///resources/sounds/LRMonoPhase4.wav"
file = QFile(filename)
fi = QFileInfo(file)
if file.open(QIODevice.ReadOnly):
    fp = QTemporaryFile("XXXXXX.{}".format(fi.completeSuffix()))
    if fp.open():
        fp.write(file.readAll())
        fp.seek(0)
        tmp_filename = fp.fileName()
        process = subprocess.Popen(
            ["aplay", "-vvv", tmp_filename], shell=False, stderr=subprocess.PIPE
        )
        process.communicate()

Note: If it is to be used within an application that uses the Qt eventloop then it is better to use QProcess than subprocess.Popen.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Right now I am using Python threading. If I use QProcess does it create its own thread? What are the advantages of using QProcess over subprocess, other than terminating when I close my program? – Aaron Mar 09 '21 at 21:20
  • @Aaron Exactly: Use the eventloop to run the program instead of a new thread. Threads should always be the last option in Qt since they add unnecessary complexity and if it is not handled correctly then you have silent problems (many of Qt's questions in SO, I would say 30%, are about mishandling of threads with Qt). – eyllanesc Mar 09 '21 at 21:22