2017-10-19 135 views
1

我有一个QBuffer在一个临时的wav文件的RAM,我想让用户从任何时候都可以听到它所需的次数。但是,它只允许播放一次,并且不允许重播。如果我从文件播放音频(QUrl.fromLocalFile),它可以播放它。有什么不同?如何解决它?PyQt5:QMediaPlayer无法播放来自QBuffer的音频

1)要播放从RAM中的wav文件我用下面的代码:

data = b"" 
    with open(fname, "rb") as file: 
     data = file.read() 
    buf = QBuffer() 
    buf.setData(data) #For debugging. Real buffer is filled differently. 
    buf.open(QIODevice.ReadOnly); 

    self.mediaPlayer=QMediaPlayer(self) 
    self.mediaPlayer.setMedia(QMediaContent(),buf) 

然后,如果我叫self.mediaplayer.play(),它将文件播放到结束。但是,对self.mediaplayer.play()的所有后续呼叫均不起作用。这不是我想要的。

2)如果我初始化从文件中媒体播放器,有:

self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile("/home/me/myTestApp/test.wav"))) 

它工作正常 - 如果我叫play()后,先前的重放结束,QMediaPlayer只是重复播放。

回答

1

A QBuffer是一个io设备 - 一旦您阅读了它,您需要重新设置其位置以便再次阅读。因此,在你的代码,你需要做这样的事情:

... 
    self._buffer = buf 
    self.mediaPlayer=QMediaPlayer(self) 
    self.mediaPlayer.setMedia(QMediaContent(), self._buffer) 

def play(self): 
    self._buffer.seek(0) 
    self.mediaPlayer.play() 

编辑

一些实际测试后,我发现它是只需要保持到缓冲器的参考,以重放音频。下面的脚本是一个完整的例子,适用于我(在Linux上,使用GStreamer后端):

import sys 
from PyQt5 import QtCore, QtWidgets, QtMultimedia 

class Window(QtWidgets.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     self.buttonOpen = QtWidgets.QPushButton('Open', self) 
     self.buttonOpen.clicked.connect(self.handleOpen) 
     self.buttonPlay = QtWidgets.QPushButton('Play', self) 
     self.buttonPlay.clicked.connect(self.handlePlay) 
     layout = QtWidgets.QHBoxLayout(self) 
     layout.addWidget(self.buttonOpen) 
     layout.addWidget(self.buttonPlay) 
     self.mediaPlayer = QtMultimedia.QMediaPlayer(self) 
     self._buffer = QtCore.QBuffer() 

    def handlePlay(self): 
     if self.buttonPlay.text() == 'Play': 
      self.buttonPlay.setText('Stop') 
      # self._buffer.seek(0) 
      self.mediaPlayer.play() 
     else: 
      self.buttonPlay.setText('Play') 
      self.mediaPlayer.stop() 

    def handleOpen(self): 
     path, ok = QtWidgets.QFileDialog.getOpenFileName(
      self, filter='WAV Files (*.wav)') 
     if ok: 
      self._buffer.close() 
      with open(path, 'rb') as stream: 
       self._buffer.setData(stream.read()) 
      if self._buffer.open(QtCore.QIODevice.ReadOnly): 
       self.mediaPlayer.setMedia(
        QtMultimedia.QMediaContent(), self._buffer) 

if __name__ == '__main__': 

    app = QtWidgets.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(600, 100, 200, 50) 
    window.show() 
    sys.exit(app.exec_()) 
+0

不,它不工作。 而实际上,我认为你的解释是错误的,因为如果你重播一个文件,QMediaPlayer的实现也必须寻求文件的启动。 –

+0

@ al.zatv。是的,我承认我没有测试任何东西,而且主要只是一种预感。无论如何,我已经为我的答案添加了一个充分有效的示例。你能测试它吗? – ekhumoro

+0

是的,它正在工作。我改变了解决方案的一点点:我在构造函数中读取它,并将其重新设置为对QMediaPlayer.stateChanged信号的响应,如果状态设置为0(停止状态)。它允许我使用“播放”按钮在音频中间和完全停止之后暂停后继续播放。 \t DEF onStateChanged(个体): \t \t如果self.mediaPlayer.state()== 0: \t \t \t self.mediaPlayer.setMedia(QMediaContent(),self.wavBuf) 有一些问题,该解决方案:a)感觉像是黑客; b)在移动到停止状态后,位置被设置为开始文件,这在我的应用程序中不方便。 –