Skip to content Skip to sidebar Skip to footer

Qmediaplayer. How To Play Video With Multiple Audio?

There is a video file with two audio tracks: Duration: 01:05:09.12, start: 0.000000, bitrate: 2781 kb/s Stream #0:0: Video: mpeg4 (Advanced Simple Profile) (XVID / 0x44495658

Solution 1:

As @musicamante points out in the comments, the solution is to access the QMediaStreamsControl but PyQt5 does not expose it.

Instead PySide2 does expose it and the solution is to cast using shiboken2:

import os

from PySide2 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets

import shiboken2


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

    defcontextMenuEvent(self, event):
        menu = QtWidgets.QMenu()
        group = QtWidgets.QActionGroup(menu)
        group.setExclusive(True)
        index = 0for i inrange(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 isnotNone:
            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_())

In the case of pyqt5 you should use sip with the following code:

import os

from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets

import sip


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

    defcontextMenuEvent(self, event):
        menu = QtWidgets.QMenu()
        group = QtWidgets.QActionGroup(menu)
        group.setExclusive(True)
        index = 0for i inrange(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 isnotNone:
            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_())

But as pointed out by QMediaStreamsControl is not available in PyQt5, so a solution is to expose it and for this you must:

  1. Download PyQt5 source code: https://pypi.python.org/packages/source/P/PyQt5/PyQt5-5.14.2.tar.gz
  2. Create the file qmediastreamscontrol.sip in "sip/QtMultimedia" folder of the PyQt5 source code.

    qmediastreamscontrol.sip

    classQMediaStreamsControl : QMediaControl
    {
    %TypeHeaderCode
    #include<qmediastreamscontrol.h>
    %End
    
    public:
        enumStreamType { 
            UnknownStream, 
            VideoStream, 
            AudioStream, 
            SubPictureStream, 
            DataStream 
        };
    
        virtual ~QMediaStreamsControl();
        virtualintstreamCount()= 0;
        virtual QMediaStreamsControl::StreamType streamType(int streamNumber)= 0;
        virtual QVariant metaData(int streamNumber, const QString &key)= 0;
        virtualboolisActive(int streamNumber)= 0;
        virtualvoidsetActive(int streamNumber, bool state)= 0;
    
    signals:
        voidstreamsChanged();
        voidactiveStreamsChanged();
    
    protected:
    %If (Qt_5_6_1 -)
        explicitQMediaStreamsControl(QObject *parent /TransferThis/ = 0);
    %End
    %If (- Qt_5_6_1)
        QMediaStreamsControl(QObject *parent /TransferThis/ = 0);
    %End
    };
    
  3. Add %Include qmediastreamscontrol.sip to the end of file sip/QtMultimedia/QtMultimediamod.sip

  4. Compile and install PyQt5 using the modified source code.

In conclusion:

  • If you use pyside2 the solution is simple.

  • If you use pyqt5 you will have to modify its source code, compile it and install it. Hopefully with the @musicamante report class QMediaStreamsControl is exposed in future releases of pyqt5

Post a Comment for "Qmediaplayer. How To Play Video With Multiple Audio?"