QtMultimedia - QAudioDecoder - Python - 状态改变,但缓冲区从未可用
QtMultimedia - QAudioDecoder - Python - state changes, but buffer never made available
我不想说我花了多长时间才达到这一点,但我真的很难完全理解 PyQt5 以及它与我在 Qt 网站上看到的 C++ 代码的关系,但我想 .. 我明白了,或者......至少我认为我这样做了,直到这完全失败为止。我将从我得到的输出开始,它告诉我我有一个确实存在的文件。我已经尝试过 mp3 和 ogg 版本,以防万一由于某种原因 AudioDecoder 无法解码 MP3,即使 QtMultimedia 的其他部分已经能够播放它(我正在尝试降低级别以便我可以将声像应用于音频和改变 left/right 平衡,一旦我想通了,也许还有其他有趣的事情)。
调试输出:
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.
代码:
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()
已修改代码,尝试使用 WAV,但仍然无法正常工作:
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()
我的更新代码 post 从下面回答,它适用于 mp3 :)
from PyQt5 import QtCore, QtMultimedia, QtWidgets
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
import signal
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(self.error)
self.decoder.stateChanged.connect(self.stateChanged)
self.decoder.positionChanged.connect(self.positionChanged)
self.decoder.bufferAvailableChanged.connect(self.bufferAvailableChanged)
self.decoder.setAudioFormat(self.desiredFormat)
self.decoder.setSourceFilename('D:\python\sounds\30.mp3')
fs = QFileInfo()
print('File exists:' + str(fs.exists('D:\python\sounds\30.mp3')))
#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())
def bufferAvailableChanged(self,available):
print('Available:' + str(available))
def positionChanged(self,position):
print('Position:' + str(position)+'/'+str(self.decoder.duration))
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))
def error(self,err):
print('Decoder error')
print(self.decoder.errorString())
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
byteCount = buffer.byteCount()
print('Bytecount in buffer:' + str(byteCount))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.constData().asstring(byteCount))
else:
self.ba.append(buffer.constData().asstring(byteCount))
self.readamount = self.readamount + 1
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
app = QtWidgets.QApplication([''])
ad = AudioDecoder()
signal.signal(signal.SIGINT,signal.SIG_DFL)
app.exec_()
这是我的(Linux)原始脚本的工作版本:
from PyQt5 import QtWidgets
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)
fs = QFileInfo('test.wav')
self.decoder.setSourceFilename(fs.absoluteFilePath())
print('File exists:' + str(fs.exists()))
#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(self.decoder.bufferAvailable()))
def positionChanged(self):
print(str(self.decoder.position())+'/'+str(self.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()
count = buffer.byteCount()
print('Bytecount in buffer:' + str(count))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.constData().asstring(count))
self.readamount = count
else:
self.ba.append(buffer.constData().asstring(count))
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
app = QtWidgets.QApplication([''])
ad = AudioDecoder()
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# press Ctrl+C to exit
app.exec_()
差异:
--- yours
+++ mine
@@ -1,3 +1,4 @@
+from PyQt5 import QtWidgets
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
@@ -14,9 +15,9 @@
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')))
+ fs = QFileInfo('test.wav')
+ self.decoder.setSourceFilename(fs.absoluteFilePath())
+ print('File exists:' + str(fs.exists()))
#self.connect(decoder,bufferReady(),None,readBuffer())
self.decoder.bufferReady.connect(self.readBuffer)
@@ -34,9 +35,9 @@
self.decoder.start()
print('Init finished, Decoder started?')
def bufferAvailableChanged(self):
- print(str(decoder.available))
+ print(str(self.decoder.bufferAvailable()))
def positionChanged(self):
- print(str(decoder.position())+'/'+str(decoder.duration))
+ print(str(self.decoder.position())+'/'+str(self.decoder.duration()))
def stateChanged(self):
#Confirm state is what we expect
print('Decoder state changed?')
@@ -48,14 +49,23 @@
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
- print('Bytecount in buffer:' + str(buffer.byteCount))
+ count = buffer.byteCount()
+ print('Bytecount in buffer:' + str(count))
if self.readamount == 0:
self.ba = QByteArray()
- self.ba.fromRawData(buffer.data(),buffer.byteCount())
+ self.ba.fromRawData(buffer.constData().asstring(count))
+ self.readamount = count
else:
- self.ba.append(buffer.data(),buffer.byteCount())
+ self.ba.append(buffer.constData().asstring(count))
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
+app = QtWidgets.QApplication([''])
ad = AudioDecoder()
+
+import signal
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+# press Ctrl+C to exit
+
+app.exec_()
输出:
File exists:True
Decoder stopped:True
Init finished, Decoder started?
Decoder state changed?
Decoder stopped?:False
Decoder decoding?:True
True
Decoder ready for reading?
0/196238
Bytecount in buffer:7680
Bytearray size:0
Decoder ready for reading?
40/196238
Bytecount in buffer:7680
Bytearray size:7680
Decoder ready for reading?
80/196238
Bytecount in buffer:7680
Bytearray size:15360
Decoder ready for reading?
120/196238
Bytecount in buffer:7680
Bytearray size:23040
Decoder ready for reading?
False
160/196238
Bytecount in buffer:7680
Bytearray size:30720
...
Bytecount in buffer:7680
Bytearray size:37662720
Decoder ready for reading?
False
196200/196238
Bytecount in buffer:7364
Bytearray size:37670084
Decoding finished, ready to play
Decoder state changed?
Decoder stopped?:True
Decoder decoding?:False
我不想说我花了多长时间才达到这一点,但我真的很难完全理解 PyQt5 以及它与我在 Qt 网站上看到的 C++ 代码的关系,但我想 .. 我明白了,或者......至少我认为我这样做了,直到这完全失败为止。我将从我得到的输出开始,它告诉我我有一个确实存在的文件。我已经尝试过 mp3 和 ogg 版本,以防万一由于某种原因 AudioDecoder 无法解码 MP3,即使 QtMultimedia 的其他部分已经能够播放它(我正在尝试降低级别以便我可以将声像应用于音频和改变 left/right 平衡,一旦我想通了,也许还有其他有趣的事情)。
调试输出:
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.
代码:
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()
已修改代码,尝试使用 WAV,但仍然无法正常工作:
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()
我的更新代码 post 从下面回答,它适用于 mp3 :)
from PyQt5 import QtCore, QtMultimedia, QtWidgets
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
import signal
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(self.error)
self.decoder.stateChanged.connect(self.stateChanged)
self.decoder.positionChanged.connect(self.positionChanged)
self.decoder.bufferAvailableChanged.connect(self.bufferAvailableChanged)
self.decoder.setAudioFormat(self.desiredFormat)
self.decoder.setSourceFilename('D:\python\sounds\30.mp3')
fs = QFileInfo()
print('File exists:' + str(fs.exists('D:\python\sounds\30.mp3')))
#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())
def bufferAvailableChanged(self,available):
print('Available:' + str(available))
def positionChanged(self,position):
print('Position:' + str(position)+'/'+str(self.decoder.duration))
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))
def error(self,err):
print('Decoder error')
print(self.decoder.errorString())
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
byteCount = buffer.byteCount()
print('Bytecount in buffer:' + str(byteCount))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.constData().asstring(byteCount))
else:
self.ba.append(buffer.constData().asstring(byteCount))
self.readamount = self.readamount + 1
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
app = QtWidgets.QApplication([''])
ad = AudioDecoder()
signal.signal(signal.SIGINT,signal.SIG_DFL)
app.exec_()
这是我的(Linux)原始脚本的工作版本:
from PyQt5 import QtWidgets
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)
fs = QFileInfo('test.wav')
self.decoder.setSourceFilename(fs.absoluteFilePath())
print('File exists:' + str(fs.exists()))
#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(self.decoder.bufferAvailable()))
def positionChanged(self):
print(str(self.decoder.position())+'/'+str(self.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()
count = buffer.byteCount()
print('Bytecount in buffer:' + str(count))
if self.readamount == 0:
self.ba = QByteArray()
self.ba.fromRawData(buffer.constData().asstring(count))
self.readamount = count
else:
self.ba.append(buffer.constData().asstring(count))
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
app = QtWidgets.QApplication([''])
ad = AudioDecoder()
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# press Ctrl+C to exit
app.exec_()
差异:
--- yours
+++ mine
@@ -1,3 +1,4 @@
+from PyQt5 import QtWidgets
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
@@ -14,9 +15,9 @@
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')))
+ fs = QFileInfo('test.wav')
+ self.decoder.setSourceFilename(fs.absoluteFilePath())
+ print('File exists:' + str(fs.exists()))
#self.connect(decoder,bufferReady(),None,readBuffer())
self.decoder.bufferReady.connect(self.readBuffer)
@@ -34,9 +35,9 @@
self.decoder.start()
print('Init finished, Decoder started?')
def bufferAvailableChanged(self):
- print(str(decoder.available))
+ print(str(self.decoder.bufferAvailable()))
def positionChanged(self):
- print(str(decoder.position())+'/'+str(decoder.duration))
+ print(str(self.decoder.position())+'/'+str(self.decoder.duration()))
def stateChanged(self):
#Confirm state is what we expect
print('Decoder state changed?')
@@ -48,14 +49,23 @@
def readBuffer(self):
print('Decoder ready for reading?')
buffer = self.decoder.read()
- print('Bytecount in buffer:' + str(buffer.byteCount))
+ count = buffer.byteCount()
+ print('Bytecount in buffer:' + str(count))
if self.readamount == 0:
self.ba = QByteArray()
- self.ba.fromRawData(buffer.data(),buffer.byteCount())
+ self.ba.fromRawData(buffer.constData().asstring(count))
+ self.readamount = count
else:
- self.ba.append(buffer.data(),buffer.byteCount())
+ self.ba.append(buffer.constData().asstring(count))
print('Bytearray size:' + str(self.ba.length()))
def play(self):
print('Decoding finished, ready to play')
+app = QtWidgets.QApplication([''])
ad = AudioDecoder()
+
+import signal
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+# press Ctrl+C to exit
+
+app.exec_()
输出:
File exists:True
Decoder stopped:True
Init finished, Decoder started?
Decoder state changed?
Decoder stopped?:False
Decoder decoding?:True
True
Decoder ready for reading?
0/196238
Bytecount in buffer:7680
Bytearray size:0
Decoder ready for reading?
40/196238
Bytecount in buffer:7680
Bytearray size:7680
Decoder ready for reading?
80/196238
Bytecount in buffer:7680
Bytearray size:15360
Decoder ready for reading?
120/196238
Bytecount in buffer:7680
Bytearray size:23040
Decoder ready for reading?
False
160/196238
Bytecount in buffer:7680
Bytearray size:30720
...
Bytecount in buffer:7680
Bytearray size:37662720
Decoder ready for reading?
False
196200/196238
Bytecount in buffer:7364
Bytearray size:37670084
Decoding finished, ready to play
Decoder state changed?
Decoder stopped?:True
Decoder decoding?:False