Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
Play mp3 on QAudioOutput with Python
Flanagan last edited by Flanagan
I've been trying this for a week and can't get it.
I need to play mp3 sounds through a specific device (not the default output of the operating system). For wav I have succeeded but when I need play mp3 I get into decoders everything becomes very complicated and superior to me.
In the documentation I have only found this:
QAudioFormat desiredFormat; desiredFormat.setChannelCount(2); desiredFormat.setCodec("audio/x-raw"); desiredFormat.setSampleType(QAudioFormat::UnSignedInt); desiredFormat.setSampleRate(48000); desiredFormat.setSampleSize(16); QAudioDecoder *decoder = new QAudioDecoder(this); decoder->setAudioFormat(desiredFormat); decoder->setSourceFilename("level1.mp3"); connect(decoder, SIGNAL(bufferReady()), this, SLOT(readBuffer())); decoder->start(); // Now wait for bufferReady() signal and call decoder->read()
- I don't know if that's enough to read mp3.
- if it is enough, I don't know how to send the bytes data to the
I have also found a couple of examples with c++:
But when reading the decoder it returns a
QAudioBufferand I don't know how to transmit the data of said buffer to the
I am working on python app. I am not a c ++ expert and what little I have found is in that language...
JonB last edited by
But when reading the decoder it returns a QAudioBuffer and I don't know how to transmit the data of said buffer to the QAudioOutput either.
With the proviso that I know nothing about this, so no point questioning me further... !
I would say, given a bunch of bytes to send:
QIODevice *QAudioOutput::start()returns a
QIODevice *, You can
QIODevice::write()to this from a byte array.
void QAudioOutput::start(QIODevice *device)takes a
QIODevice *argument, which could be a
QBufferclass provides a
QIODeviceinterface for a
@JonB But the problem is that reading the decoder returns a QAudioBuffer, not a QBuffer. They are different objects and do not inherit from each other.
I can access the data from the QAudioBuffer with .consData () but it returns a pointer and I can't use that data to send it through a QAudioOutput.
JonB last edited by JonB
Like I said, not my area. But I don't understand your response. For example,
QByteArray/bytes/chars whatever, and
QAudioBuffer::constData()provides access to the data, so I don't get
I can't use that data to send it through a QAudioOutput
but you may know better than I.
QAudioBuffer::constData()returns a pointer, i dont know, with python, how to make
QByteArrayfrom that pointer or send that data otherwise to
JonB last edited by
Ah, I forgot you were Python! I can see that might be a problem....
You really should say whether you are PyQt5 or PySide2? Does yours have
QAudioBuffer::data()? What does that say it returns? Have you tried just slapping in things like:
buf = QBuffer(audioBuf.constData()) buf = bytes(audioBuf.data())
and crossing your fingers?
At which point maybe I should butt out, perhaps someone knows more about what is required for your issue.
@JonB I use PySide2.
QAudioBuffer.data()return ´´´VoidPtr´´´ ->
Apparently with your second option I do manage to create a QByteArray and, therefore, QBuffer but I don't hear anything.
No error, but no sound.
from PySide2 import QtWidgets, QtMultimedia from PySide2.QtCore import QBuffer, QByteArray from PySide2.QtMultimedia import QAudioOutput, QAudioDecoder def my_read(): audio_buffer = decoder.read() data = bytes(audio_buffer.constData()) buffer = QBuffer(QByteArray(data)) output.start(buffer) app = QtWidgets.QApplication() devices = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioOutput) device = devices desire_audio_format = device.preferredFormat() output = QAudioOutput(device, desire_audio_format) decoder = QAudioDecoder() decoder.setAudioFormat(desire_audio_format) decoder.setSourceFilename('song.mp3') decoder.bufferReady.connect(my_read) decoder.start() app.exec_()
Something worth checking: QAudioOutputSelectorControl.
Try to get the one from QMediaPlayer and change the output to the one you want to use. That way you do not need to go low level.
Hope it helps
@SGaist Thank you for the approach, i see QAudioOutputSelectorControl is deprecated
Why is obsolete? There isn't alternative for change output of mediaplayer?
I have tried this but the output is not changed, I think I am not passing the correct string to the
QAudioOutputSelectorControl :: setActiveOutputmethod.
I have found this example and have relied on it to do the following: https://stackoverflow.com/questions/28408590/qt5-how-to-set-default-audio-device-for-qmediaplayer
Sounds good but it sounds in the output of the operating system (devices) and I want it in another (devices)
from PySide2 import QtWidgets, QtMultimedia from PySide2.QtCore import QBuffer, QByteArray, QUrl from PySide2.QtMultimedia import QAudioOutput, QAudioDecoder, QMediaPlayer app = QtWidgets.QApplication() devices = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioOutput) device = devices desire_audio_format = device.preferredFormat() player = QMediaPlayer() player.setMedia(QUrl.fromLocalFile('song.mp3')) player.play() service = player.service() control = service.requestControl('org.qt-project.qt.audiooutputselectorcontrol/5.0') control.setActiveOutput(device.deviceName()) service.releaseControl(control) app.exec_()
That is don't know, I completely missed the obsolete warning.
Did you try to change the output before starting to play the file ?
@SGaist Yes, it is the same :/. I read on stackoverflow i need device's id, not the name. I dont know where get that
Do you mean from the code on the stack overflow thread ?
@SGaist I have these output devices on my pc:
I have a output device (a virtual cable called CABLE Input) that emit sounds to a input device (called Cable Output). The list only show my output devices.
I want play mp3 on my second output -> CABLE Input (VB-Audio Virtual Cable)
It seems that is his name but not his ID, i saw in stackoverflow i need the ID and pass to the method
QAudioOutputSelectorControl.setActiveOutputa string ID.
So you have an external application that allows you to do input/output mixing ?
Although it doesn't matter, I only want to play mp3 in any output of my choice. That virtual cable or any other that is not the default of the operating system.