2017-10-19 179 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)在移動到停止狀態後,位置被設置爲開始文件,這在我的應用程序中不方便。 –