Ich hasse zu sagen, wie lange ich brauchte, um zu diesem Punkt zu kommen, aber ich hatte echte Schwierigkeiten, vollständig zu verstehen PyQt5 und wie es sich auf den C++ - Code bezieht auf der Qt-Website, aber ich denke .. ich verstehe, oder ... zumindest dachte ich, dass ich es getan habe, bis das völlig versagt hat. Ich beginne mit der Ausgabe, die ich bekomme, die mir sagt, dass ich eine Datei habe, die wirklich existiert. Ich habe mp3 und ogg Version aus irgendeinem Grund versucht, AudioDecoder kann die MP3 nicht dekodieren, obwohl andere Teile von QtMultimedia in der Lage waren, es zu spielen (Ich versuche, niedrigeres Niveau zu erreichen, damit ich Schwenken auf das Audio und anwenden kann) verschiebe das linke/rechte Gleichgewicht und vielleicht andere lustige Dinge, wenn ich das herausgefunden habe).QtMultimedia - QAudioDecoder - Python - Statusänderungen, aber Puffer nie verfügbar
Debug-Ausgabe:
MP3 exists:True
Decoder stopped:True <- expected at this point, just confirming state works
Decoder state changed? <- this means state change signal is being sent
Decoder stopped?:False <- ok, state did actually change, that's expected
Decoder decoding?:True <- expected, confirming there are only 2 states as documentation indicates
Init finished, Decoder started? <- after this, i expect to see position changes, buffer availability changes, or errors ... but I get nothing and it just exits the script.
Code:
from PyQt5 import QtCore, QtMultimedia
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QByteArray, QIODevice, QFileInfo
from PyQt5.QtMultimedia import QAudioDecoder, QAudioFormat, QMediaObject, QAudioBuffer, QAudioOutput, QAudio
class AudioDecoder(QObject):
def __init__(self):
super(AudioDecoder,self).__init__()
self.desiredFormat = QAudioFormat()
self.desiredFormat.setChannelCount(2)
self.desiredFormat.setCodec('audio/pcm')
self.desiredFormat.setSampleType(QAudioFormat.UnSignedInt)
self.desiredFormat.setSampleRate(48000)
self.desiredFormat.setSampleSize(16)
self.decoder = QAudioDecoder()
self.decoder.setAudioFormat(self.desiredFormat)
self.decoder.setSourceFilename('D:\\python\\sounds\\30.mp3')
fs = QFileInfo()
print('MP3 exists:' + str(fs.exists('D:\\python\\sounds\\30.mp3')))
#self.connect(decoder,bufferReady(),None,readBuffer())
self.decoder.bufferReady.connect(self.readBuffer)
self.decoder.finished.connect(self.play)
self.decoder.error.connect(self.error)
self.decoder.stateChanged.connect(self.stateChanged)
self.decoder.positionChanged.connect(self.positionChanged)
self.decoder.bufferAvailableChanged.connect(self.bufferAvailableChanged)
#using this to determine if we need to start byte array or append to it
self.readamount = 0
#Expect this to be true since we haven't started yet
print('Decoder stopped:' + str(self.decoder.state() == QAudioDecoder.StoppedState))
self.decoder.start()
print('Init finished, Decoder started?')
def bufferAvailableChanged(self):
print(str(decoder.available))
def positionChanged(self):
print(str(decoder.position())+'/'+str(decoder.duration))
def stateChanged(self):
#Confirm state is what we expect
print('Decoder state changed?')
print('Decoder stopped?:' + str(self.decoder.state() == QAudioDecoder.StoppedState))
print('Decoder decoding?:' + str(self.decoder.state() == QAudioDecoder.DecodingState))
def error(self):
print('Decoder error?')
print(self.decoder.errorString())
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
print('Bytecount in buffer:' + str(buffer.byteCount))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.data(),buffer.byteCount())
else:
self.ba.append(buffer.data(),buffer.byteCount())
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
ad = AudioDecoder()
Revised Code, WAV versuchen, immer noch nicht funktioniert aber:
from PyQt5 import QtCore, QtMultimedia
from PyQt5.QtTest import QSignalSpy
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QByteArray, QIODevice, QFileInfo
from PyQt5.QtMultimedia import QAudioDecoder, QAudioFormat, QMediaObject, QAudioBuffer, QAudioOutput, QAudio
class AudioDecoder(QObject):
def __init__(self):
super(AudioDecoder,self).__init__()
self.desiredFormat = QAudioFormat()
self.desiredFormat.setChannelCount(2)
self.desiredFormat.setCodec('audio/pcm')
self.desiredFormat.setSampleType(QAudioFormat.UnSignedInt)
self.desiredFormat.setSampleRate(48000)
self.desiredFormat.setSampleSize(16)
self.decoder = QAudioDecoder()
self.decoder.bufferReady.connect(self.readBuffer)
self.decoder.finished.connect(self.play)
self.decoder.error.connect(lambda: self.error(self.decoder.error()))
self.decoder.stateChanged.connect(lambda: self.stateChanged(self.decoder.state()))
self.decoder.positionChanged.connect(lambda: self.positionChanged(self.decoder.position(),self.decoder.duration()))
self.decoder.bufferAvailableChanged.connect(lambda: self.bufferAvailableChanged(self.decoder.available()))
self.decoder.setAudioFormat(self.desiredFormat)
self.decoder.setSourceFilename('D:\\python\\sounds\\piano2.wav')
fs = QFileInfo()
print('File exists:' + str(fs.exists('D:\\python\\sounds\\piano2.wav')))
#using this to determine if we need to start byte array or append to it
self.readamount = 0
#Expect this to be true since we haven't started yet
print('Decoder stopped?:' + str(self.decoder.state() == QAudioDecoder.StoppedState))
self.decoder.start()
print('Init finished, Decoder started on file:' + self.decoder.sourceFilename())
@pyqtSlot()
def bufferAvailableChanged(self,available):
print('Available:' + str(available))
@pyqtSlot()
def positionChanged(self,position,duration):
print('Position:' + str(position())+'/'+str(duration()))
@pyqtSlot()
def stateChanged(self,state):
#Confirm state is what we expect
print('Decoder state changed')
if state == QAudioDecoder.StoppedState:
print('Decoder stopped?:' + str(state == QAudioDecoder.StoppedState))
else:
print('Decoder decoding?:' + str(state == QAudioDecoder.DecodingState))
@pyqtSlot()
def error(self,err):
print('Decoder error')
print(self.decoder.errorString())
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
print('Bytecount in buffer:' + str(buffer.byteCount))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.data(),buffer.byteCount())
else:
self.ba.append(buffer.data(),buffer.byteCount())
self.readamount = self.readamount + 1
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
ad = AudioDecoder()
von unten Meine Update-Code Post Antwort, und es funktioniert mit mp3 :)
01 Hier
* Ich habe ein paar Dinge fehlen bemerkt im obigen Code nichts, was das Ergebnis, das ich bekomme, verursachen sollte, aber Dinge, die zu unerwartetem Verhalten führen würden. Ich habe vergessen, readamount nach dem Lesen zu aktualisieren, und ich habe festgestellt, dass ich vermeiden kann, decoder.state im angeschlossenen Python-Slot aufzurufen, wenn ich den Funktionsaufruf state, aber das hat das Verhalten nicht verändert, auch wenn es sauberer ist über. –
Nachdem ich viele kleine Fehler im Code behoben hatte, konnte ich es in Ordnung bringen. Ich habe jedoch nur auf Linux getestet (welches das gstreamer Backend verwendet). Vielleicht möchten Sie es mit einer 'wav'-Datei versuchen, da dieses Format garantiert unterstützt wird. – ekhumoro
Ich habe es später mit einer WAV-Datei versucht, auch nachdem ich einige Anpassungen vorgenommen habe (werde sie unten setzen). Würde es Ihnen etwas ausmachen, hier eine Antwort zu geben, mit den kleinen Anpassungen, die Sie am Code vorgenommen haben? –