QMediaPlayer.如何播放带有多个音频的视频



有一个带有两个音轨的视频文件:

Duration: 01:05:09.12, start: 0.000000, bitrate: 2781 kb/s
Stream #0:0: Video: mpeg4 (Advanced Simple Profile) (XVID / 0x44495658), yuv420p, 720x400 [SAR 1:1 DAR 9:5], 1998 kb/s, 25 fps, 25 tbr, 25 tbn, 25 tbc
Stream #0:1: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), fltp, 384 kb/s
Stream #0:2: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), fltp, 384 kb/s

用这个代码播放:

self.player = QMediaPlayer()
self.player.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))
self.player.play()

播放视频和第一首音轨。Н如何切换到第二个音轨?

@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中不可用,因此解决方案是公开它,为此您必须:

  1. 下载PyQt5源代码:https://pypi.python.org/packages/source/P/PyQt5/PyQt5-5.14.2.tar.gz
  2. 在PyQt5源代码的"sip/QtMultedia"文件夹中创建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
    };
    
  3. %Include qmediastreamscontrol.sip添加到sip/QtMultimedia/QtMultimeediamod.sip 文件的末尾

  4. 使用修改后的源代码编译并安装PyQt5。

结论:

  • 如果使用pyside2,解决方案很简单。

  • 如果你使用pyqt5,你将不得不修改它的源代码,编译并安装它。希望通过@musicamante报告类QMediaStreamsControl在pyqt5 的未来版本中公开

最新更新