1

How can we change the audio track of a video which has multiple audio tracks? For example, I have a .mkv file of a movie that has audios of Hindi and English. But when I play it with GNOME Video player it will play the Hindi language as default. Gnome Video has option for changing audio track. When it comes to QML how can we specify in which language video needs to be played. I am using QML QtMultimedia Video Component.

This is what like it will be

Video {
    id: video
    width : 800
    height : 600
    source: "video.mkv"
    language: "English"

    MouseArea {
        anchors.fill: parent
        onClicked: {
            video.play()
        }
    }

    focus: true
    Keys.onSpacePressed: video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play()
    Keys.onLeftPressed: video.seek(video.position - 5000)
    Keys.onRightPressed: video.seek(video.position + 5000)
}
  • sorry not avi it's mkv edited the question and link is here [link](https://drive.google.com/file/d/12X-EBf0rAtLXuGsdw-rF0fGRztrjYtnh/view) – Newtron Malayalam Apr 27 '20 at 03:15

1 Answers1

1

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
        }
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241