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 并播放视频