ffpyplayer icon indicating copy to clipboard operation
ffpyplayer copied to clipboard

MediaPlayer Sound Still Coming From Speaker After player.set_mute(True)

Open slalomchip opened this issue 5 years ago • 6 comments
trafficstars

I wrote a script in Python 3.8 on a Windows 10 platform that uses MediaPlayer to play a video in a PyQt5 QLabel. I can toggle pause by pressing the "P" key on the keyboard but I cannot toggle mute when pressing the "M" key.

When pressing the "M" key, the player.get_mute() return changes from False to True to False just as I expect it to, but sound keeps coming out of the speaker regardless if player.get_mute() == True

Here is a minimal script that exhibits this behavior.

from PyQt5.QtWidgets import QLabel, QMainWindow, QApplication, QWidget
from PyQt5.QtWidgets import QShortcut
from PyQt5.QtGui import QPixmap, QImage, QKeySequence
from PyQt5.QtCore import QTimer, Qt
import os, sys
from ffpyplayer.player.player import MediaPlayer

class VideoCap(QMainWindow):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Mute Test")        
        self.central_widget = QWidget()               
        self.setCentralWidget(self.central_widget)
        self.central_widget.setGeometry(10,50,960,720)
        self.player = MediaPlayer('test.mp4')
        self.setGeometry(25,50,960,720)
        self.vidWindow = QLabel(self.central_widget)
        self.vidWindow.setGeometry(0,0,960,720)
        self.muteKey = QShortcut(QKeySequence(Qt.Key_M), self)
        self.muteKey.activated.connect(self.toggleMute)
        self.pauseKey = QShortcut(QKeySequence(Qt.Key_P), self)
        self.pauseKey.activated.connect(self.togglePause)
        self.show()
        self.start()
        
    def nextFrameSlot(self):        
        try:
            frame, val = self.player.get_frame()
            if val != 'eof':
                img, t = frame
                data = img.to_bytearray()[0]
                width, height = img.get_size()
                qimage = QImage(data, width, height, QImage.Format_RGB888)
                pix = QPixmap.fromImage(qimage)
                pix = pix.scaled(self.vidWindow.width(), self.vidWindow.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
                self.vidWindow.setPixmap(pix)
        except:
            pass
        
    def toggleMute(self):
        isMuted = self.player.get_mute()
        print('Muted = ', isMuted)
        if isMuted == True:
            self.player.set_mute(False)
            print('Should now be unmuted')
        else:
            self.player.set_mute(True)
            print('Should now be muted')

    def togglePause(self):
        isPaused = self.player.get_pause()
        print('Paused = ', isPaused)
        if isPaused == True:
            self.player.set_pause(False)
            print('Should now be playing')
        else:
            self.player.set_pause(True)
            print('Should now be paused')

    def start(self): # Control the timer for calling nextframeslot
        frame_rate = 30.0
        rate = int(1000.0 / frame_rate)
        self.timer = QTimer()
        self.timer.setTimerType(Qt.PreciseTimer)
        self.timer.timeout.connect(self.nextFrameSlot)
        self.timer.start(rate)
        
    def closeEvent(self, event):
        event.ignore()
        self.player.close_player()
        os._exit(0)
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = VideoCap()
    app.exec()

slalomchip avatar Jul 30 '20 22:07 slalomchip

Please note that when I pasted in the code block above, I couldn't get the import lines nor the if __name__ == __main__ in the code block. Also, the underscores in if __name__ == __main__ got stripped out. Weird.

slalomchip avatar Jul 31 '20 23:07 slalomchip

I'm not sure what the issue is. But can you try not checking get_mute and instead unconditionally set mute to true and see if it works? Also, try setting the volume to zero and back to 1 if that doesn't work!?

matham avatar Aug 01 '20 00:08 matham

I changed the toggleMute() method to ` def toggleMute(self):

    self.player.set_mute(True)`

and it still did not mute.

Then I tried your suggestion to setting the volume to 0 and 1 with this code: ` def toggleMute(self):

    playerVolume = self.player.get_volume()

    print('Volume = ', playerVolume)

    if playerVolume == 0.0:

        self.player.set_volume(1.0)

        print('Should now be unmuted')

    else:

        self.player.set_volume(0.0)

        print('Should now be muted')`

and IT WORKED!

I'll just go with setting volume instead of setting mute. Thanks for the suggestion!

slalomchip avatar Aug 01 '20 00:08 slalomchip

Also, please close the issue if you believe the issue is unique to me. Otherwise, it might be something you still want to investigate. Either way s fine with me - I have a solution. Thanks again!

slalomchip avatar Aug 01 '20 00:08 slalomchip

I'll leave it open as it's a bug in ffpyplayer and I'll fix it at some point. But basically, https://github.com/matham/ffpyplayer/blob/master/ffpyplayer/player/core.pyx#L1543 needs to check if it's muted, but it doesn't for sdl2.

matham avatar Aug 01 '20 01:08 matham

I had the same issue, on Windows10, just using ffpyplayer and opencv in a fairly basic script. Works just using the set volume thing; can save/restore the previous volume easy enough also, so not a major issue.

#class or global variable
prevVolume = 1

# in control loop
if player.get_volume() > 0:
    prevVolume = player.get_volume()
    player.set_volume(0)
else:
    player.set_volume(prevVolume)

k8962c avatar Sep 08 '22 15:09 k8962c