正如 @musicamante 在评论中指出的那样,解决方案是访问 QMediaStreamsControl 但 PyQt5 不会公开它。
相反,PySide2 确实公开了它,解决方案是使用 shiboken2 进行转换:
import os
from PySide2 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets
import shiboken2
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
video_widget = QtMultimediaWidgets.QVideoWidget()
self.player = QtMultimedia.QMediaPlayer(
self, QtMultimedia.QMediaPlayer.VideoSurface
)
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test5.mkv")
self.player.setMedia(
QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file))
)
self.player.setVideoOutput(video_widget)
self.player.play()
self.setCentralWidget(video_widget)
control = self.player.service().requestControl(
"org.qt-project.qt.mediastreamscontrol/5.0"
)
qptr = shiboken2.getCppPointer(control)[0]
self.qcontrol = shiboken2.wrapInstance(qptr, QtMultimedia.QMediaStreamsControl)
self.resize(640, 480)
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu()
group = QtWidgets.QActionGroup(menu)
group.setExclusive(True)
index = 0
for i in range(self.qcontrol.streamCount()):
t = self.qcontrol.streamType(i)
if t == QtMultimedia.QMediaStreamsControl.AudioStream:
action = menu.addAction("Audio-{}".format(index))
action.setCheckable(True)
if self.qcontrol.isActive(i):
action.setChecked(True)
action.setData(i)
menu.addAction(action)
index += 1
action = menu.exec_(self.mapToGlobal(event.pos()))
if action is not None:
i = action.data()
self.qcontrol.setActive(i, True)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
对于 pyqt5,您应该使用 sip 并使用以下代码:
import os
from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets
import sip
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
video_widget = QtMultimediaWidgets.QVideoWidget()
self.player = QtMultimedia.QMediaPlayer(
self, QtMultimedia.QMediaPlayer.VideoSurface
)
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test5.mkv")
self.player.setMedia(
QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file))
)
self.player.setVideoOutput(video_widget)
self.player.play()
self.setCentralWidget(video_widget)
control = self.player.service().requestControl(
"org.qt-project.qt.mediastreamscontrol/5.0"
)
self.qcontrol = sip.cast(control, QtMultimedia.QMediaStreamsControl)
self.resize(640, 480)
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu()
group = QtWidgets.QActionGroup(menu)
group.setExclusive(True)
index = 0
for i in range(self.qcontrol.streamCount()):
t = self.qcontrol.streamType(i)
if t == QtMultimedia.QMediaStreamsControl.AudioStream:
action = menu.addAction("Audio-{}".format(index))
action.setCheckable(True)
if self.qcontrol.isActive(i):
action.setChecked(True)
action.setData(i)
menu.addAction(action)
index += 1
action = menu.exec_(self.mapToGlobal(event.pos()))
if action is not None:
i = action.data()
self.qcontrol.setActive(i, True)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
但正如 QMediaStreamsControl 所指出的那样,它在 PyQt5 中不可用,因此解决方案是公开它,为此您必须:
- 下载PyQt5源代码:https://pypi.python.org/packages/source/P/PyQt5/PyQt5-5.14.2.tar.gz
-
在 PyQt5 源代码的“sip/QtMultimedia”文件夹中创建文件 qmediastreamscontrol.sip。
qmediastreamscontrol.sip
class QMediaStreamsControl : QMediaControl
{
%TypeHeaderCode
#include <qmediastreamscontrol.h>
%End
public:
enum StreamType {
UnknownStream,
VideoStream,
AudioStream,
SubPictureStream,
DataStream
};
virtual ~QMediaStreamsControl();
virtual int streamCount() = 0;
virtual QMediaStreamsControl::StreamType streamType(int streamNumber) = 0;
virtual QVariant metaData(int streamNumber, const QString &key) = 0;
virtual bool isActive(int streamNumber) = 0;
virtual void setActive(int streamNumber, bool state) = 0;
signals:
void streamsChanged();
void activeStreamsChanged();
protected:
%If (Qt_5_6_1 -)
explicit QMediaStreamsControl(QObject *parent /TransferThis/ = 0);
%End
%If (- Qt_5_6_1)
QMediaStreamsControl(QObject *parent /TransferThis/ = 0);
%End
};
Add %Include qmediastreamscontrol.sip
到文件末尾 sip/QtMultimedia/QtMultimediamod.sip
使用修改后的源代码编译并安装 PyQt5。
综上所述: