Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x QtMultimedia-QAudioDecoder-Python-state发生了变化,但缓冲区始终不可用 我不喜欢说我花了这么多时间才达到这一点,但我真的完全理解PYQT5,它是如何与C++代码有关的,我在QT网站上看到了,但是我想…我明白了,或者。。。至少我认为我做到了,直到这完全失败。我将从我得到的输出开始,它告诉我我有一个真正存在的文件。我尝试了mp3和ogg版本,以防由于某种原因,音频解码器无法解码mp3,即使QT多媒体的其他部分已经能够播放它(我正在尝试降低音量,以便我可以对音频应用平移,并改变左/右平衡,一旦我弄明白了,可能还有其他有趣的事情)_Python 3.x_Qt5_Pyqt5_Qtmultimedia - Fatal编程技术网

Python 3.x QtMultimedia-QAudioDecoder-Python-state发生了变化,但缓冲区始终不可用 我不喜欢说我花了这么多时间才达到这一点,但我真的完全理解PYQT5,它是如何与C++代码有关的,我在QT网站上看到了,但是我想…我明白了,或者。。。至少我认为我做到了,直到这完全失败。我将从我得到的输出开始,它告诉我我有一个真正存在的文件。我尝试了mp3和ogg版本,以防由于某种原因,音频解码器无法解码mp3,即使QT多媒体的其他部分已经能够播放它(我正在尝试降低音量,以便我可以对音频应用平移,并改变左/右平衡,一旦我弄明白了,可能还有其他有趣的事情)

Python 3.x QtMultimedia-QAudioDecoder-Python-state发生了变化,但缓冲区始终不可用 我不喜欢说我花了这么多时间才达到这一点,但我真的完全理解PYQT5,它是如何与C++代码有关的,我在QT网站上看到了,但是我想…我明白了,或者。。。至少我认为我做到了,直到这完全失败。我将从我得到的输出开始,它告诉我我有一个真正存在的文件。我尝试了mp3和ogg版本,以防由于某种原因,音频解码器无法解码mp3,即使QT多媒体的其他部分已经能够播放它(我正在尝试降低音量,以便我可以对音频应用平移,并改变左/右平衡,一旦我弄明白了,可能还有其他有趣的事情),python-3.x,qt5,pyqt5,qtmultimedia,Python 3.x,Qt5,Pyqt5,Qtmultimedia,调试输出: 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 expecte

调试输出:

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.
修改代码,尝试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()
我的更新代码从下面给出了答案,它与mp3兼容:)

以下是您原始脚本的我的(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_()
差异:

输出:

文件存在:True
解码器停止:真
初始化完成,解码器启动?
解码器状态改变了吗?
解码器停止?:错误
解码器解码?:真
真的
解码器准备好阅读了吗?
0/196238
缓冲区中的字节数:7680
字节数组大小:0
解码器准备好阅读了吗?
40/196238
缓冲区中的字节数:7680
字节数组大小:7680
解码器准备好阅读了吗?
80/196238
缓冲区中的字节数:7680
按阵列大小:15360
解码器准备好阅读了吗?
120/196238
缓冲区中的字节数:7680
按阵列大小:23040
解码器准备好阅读了吗?
假的
160/196238
缓冲区中的字节数:7680
按阵列大小:30720
...
缓冲区中的字节数:7680
按阵列大小:37662720
解码器准备好阅读了吗?
假的
196200/196238
缓冲区中的字节数:7364
按阵列大小:37670084
解码完成,准备播放
解码器状态改变了吗?
解码器停止?:真
解码器解码?:错误

*我注意到上面代码中缺少了一些东西,没有任何东西会导致我得到的结果,但是会导致意外行为的东西。例如,我在阅读后忘记了更新readamount,我注意到如果我在函数调用中放入state,我可以避免在连接的python插槽中调用decoder.state,但这并没有改变行为,即使它比上面更干净。在修复代码中的许多小错误后,我能够让它正常工作。不过,我只在linux(使用gstreamer后端)上进行了测试。您可能希望尝试使用
wav
文件,因为该格式保证受支持。稍后,我确实尝试了使用wav文件,也尝试了一些调整(将放在下面)。你介意在这里给出一个答案,并对代码做一些小的调整吗?我怀疑我遗漏了一些基本的东西,你看到我没有,因为否则这只是linux和windows的问题,但我不知道为什么会这样。我会看看我是否可以得到一个虚拟机设置来测试它。我已经添加了一个答案。我想这可能帮不了什么忙,但你永远也不知道……好吧,我得读一点书来理解你所做的一些不同之处,但我基本上明白了问题所在。一切没有进展的原因似乎与我没有你的qtwidts.QApplication对象和执行这一事实有关,我想人们可能会称之为“应用程序循环”。我看到一些python库需要它,而有些不需要,我不知道为什么它们需要它,但我想我现在明白了。除非主应用程序循环对象正在运行,否则所有这些信号/插槽都不一定会发生。谢谢你的回答,这非常有帮助。我知道我需要更加关注所有这些不同库的整个应用程序循环。一旦我补充说我开始出现错误,你的其他更改就会完美地插入以修复这些错误。如果我从别处的阅读中回忆起,signal.signal行的目的是允许我仍然能够使用ctrl+C终止应用程序循环?@MatthewSwaringen。啊-我确实对缺少应用程序对象感到好奇,但我只是假设您的示例是更完整脚本的一部分。信号槽框架与事件框架是分开的,因此它通常不需要运行事件循环。不过,计时器和线程是一些重要的例外,因为它们需要异步。我猜多媒体类可能会广泛使用计时器和线程。PS:是的,
signal.signal
对于测试没有gui的应用程序来说非常方便。如果没有一个窗口可以关闭,事件循环将永远坐在那里旋转。还没有什么复杂的事情,只是一次学习一个片段。我只需要确保我不会意外地扔掉那些我不完全理解为什么我需要它们的碎片。。。因为也许我需要它们,只是不知道为什么。感谢您解释为什么可能需要事件循环。异步性是我最终想要的东西,因为我的目标是同时播放多个曲目。
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_()
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_()