Basically this question is identical to the one in this post so I will ignore the explanations (To fully understand the answer you have to read the explanation of my other answer first) and only provide the code.
Considering the above, it is necessary to access the mediaplayer but unfortunately the item Video does not allow it, so VideoOuput + MediaPlayer must be used
PyQt5:
from PyQt5 import QtCore, QtGui, QtQml, QtMultimedia
import sip
class PlayerHelper(QtCore.QObject):
qmlplayerChanged = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.qml_player = None
@QtCore.pyqtProperty(QtCore.QObject, notify=qmlplayerChanged)
def qmlplayer(self):
return self.qmlplayer
@qmlplayer.setter
def qmlplayer(self, player):
self.qml_player = player
self.qmlplayerChanged.emit()
@staticmethod
def get_stream_control(qmlplayer):
mediaObject = qmlplayer.property("mediaObject")
player = sip.cast(mediaObject, QtMultimedia.QMediaPlayer)
control = player.service().requestControl(
"org.qt-project.qt.mediastreamscontrol/5.0"
)
return sip.cast(control, QtMultimedia.QMediaStreamsControl)
@QtCore.pyqtSlot(result=int)
def audioCount(self):
if not self.qml_player:
return -1
stream_control = self.get_stream_control(self.qml_player)
count = 0
for i in range(stream_control.streamCount()):
if (
stream_control.streamType(i)
== QtMultimedia.QMediaStreamsControl.AudioStream
):
count += 1
return count
@QtCore.pyqtSlot(int)
def setAudioActive(self, index):
if not self.qml_player:
return
stream_control = self.get_stream_control(self.qml_player)
count = 0
for i in range(stream_control.streamCount()):
if (
stream_control.streamType(i)
== QtMultimedia.QMediaStreamsControl.AudioStream
):
if index == count:
stream_control.setActive(i, True)
return
count += 1
@QtCore.pyqtSlot(result=int)
def audioActive(self):
if not self.qml_player:
return -1
stream_control = self.get_stream_control(self.qml_player)
count = 0
for i in range(stream_control.streamCount()):
if (
stream_control.streamType(i)
== QtMultimedia.QMediaStreamsControl.AudioStream
):
if stream_control.isActive(i):
return count
count += 1
return -1
if __name__ == "__main__":
import os
import sys
app = QtGui.QGuiApplication(sys.argv)
QtQml.qmlRegisterType(PlayerHelper, "AudioHelper", 1, 0, "PlayerHelper")
engine = QtQml.QQmlApplicationEngine()
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(file))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
main.qml
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtMultimedia 5.14
import AudioHelper 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
MediaPlayer {
id: player
source: "video.mkv"
}
PlayerHelper{
id: playerhelper
qmlplayer: player
}
VideoOutput {
id: videoOutput
source: player
anchors.fill: parent
focus: true
Keys.onSpacePressed: player.playbackState == MediaPlayer.PlayingState ? player.pause() : player.play()
Keys.onLeftPressed: player.seek(player.position - 5000)
Keys.onRightPressed: player.seek(player.position + 5000)
MouseArea{
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.LeftButton){
player.play()
}
else{
var count = playerhelper.audioCount()
var index = playerhelper.audioActive()
while(context_menu.count){
var it = context_menu.takeItem(0)
it.destroy()
}
for(var i = 0; i < count; ++i){
var item = Qt.createQmlObject('import QtQuick 2.13; import QtQuick.Controls 2.13; MenuItem {}', context_menu)
item.text = "Audio " + i;
item.checkable = true
item.checked = i == index
var f = function(it, i){
it.triggered.connect(function (){
playerhelper.setAudioActive(i)
}
)}
f(item, i)
context_menu.addItem(item)
}
context_menu.popup(mouseX, mouseY)
}
}
}
Menu {
id: context_menu
}
}
}