PyQt5:QMediaPlayer 无法从 QBuffer 重放音频

Posted

技术标签:

【中文标题】PyQt5:QMediaPlayer 无法从 QBuffer 重放音频【英文标题】:PyQt5 : QMediaPlayer can't replay audio from QBuffer 【发布时间】:2017-10-19 19:29:42 【问题描述】:

我在 RAM 中有一个带有临时 wav 文件的 QBuffer,我想让用户在任何时候都可以随意收听它。但是,它只允许播放一次,并且不允许重播。如果我从文件 (QUrl.fromLocalFile) 播放音频,它可以重播它。有什么不同?如何解决?

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】:

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_())

【讨论】:

不,它不起作用。而且,实际上,我认为您的解释是错误的,因为如果您重播文件,QMediaPlayer 的实现也必须寻求文件的开头。 @al.zatv。是的,我承认我没有测试任何东西,这主要只是一种预感。无论如何,我在我的答案中添加了一个完整的示例。你能测试一下吗? 是的,它正在工作。我稍微改变一下你的解决方案:我在构造函数中读取它,并将其重新设置为对 QMediaPlayer.stateChanged 信号的响应,如果状态设置为 0(停止状态)。它允许我在音频中间暂停后和句号后使用“播放”按钮继续。 def onStateChanged(self): if self.mediaPlayer.state()==0: self.mediaPlayer.setMedia(QMediaContent(), self.wavBuf) 这个解决方案有一些问题: b)移动到停止状态后,位置设置为文件的开头,这在我的应用程序中不方便。

以上是关于PyQt5:QMediaPlayer 无法从 QBuffer 重放音频的主要内容,如果未能解决你的问题,请参考以下文章

基于pyqt5的QMediaPlayer实现视频播放器(拨动进度条,音量,更换播放模式,加入多个播放文件)

PyQt5 - 在新窗口中打开 QMediaplayer 并播放视频

PyQt5 QMediaPlayer播放不了视频

解决PyQt5 QMediaPlayer播放mp3后占用的问题

无法从其他线程播放 QMediaPlayer

尝试使用 QMediaPlayer 添加声音事件