首页 > 解决方案 > 如何使用 Python 和 PyQt5 制作 VLC 缩放视频以填充窗口?

问题描述

所以我在 MacOS 上为 VLC 使用 python 绑定模块,使用 PyQt5 来渲染窗口。

当我使用 VLC GUI 时,它完全符合您在扩展窗口时所期望的功能,缩放视频以适应窗口,即使视频的分辨率低于窗口也是如此。

使用 python-vlc 模块,没有那么多。即使它是用--autoscale选项实例化的。

在全屏模式下,视频仅占窗口左下角屏幕的 1/4 左右。在非全屏模式下,视频只有在手动调整窗口大小后才会缩放到窗口,然后最终恢复为非缩放。

我的目标是让视频窗口保留原始视频的纵横比并拉伸以填充屏幕,并在必要时进行裁剪。

我错过了什么选项或神秘方法?该文档似乎不存在。或者这实际上是我缺少的 pyqt 选项?

原谅冗长的代码摘录。vlc 和 pyqt 实例化有很多特殊之处,我看不到另一种方法可以向您展示我在做什么。

"""
This module contains a bare-bones VLC player class to play videos.
Adapted  from an example by Saveliy Yusufov, Columbia University, sy2685@columbia.edu
"""

import os
import sys
import platform

from PyQt5 import QtWidgets, QtGui, QtCore
import vlc

class Player(QtWidgets.QMainWindow):
    """Stripped-down PyQt5-based media player class
    """

    def __init__(self, master=None):
        QtWidgets.QMainWindow.__init__(self, master)

        self.media_files = [
            "data/Tv Static Noise HD 720p.mp4",
            "data/070_SHARP_Titles_Flower_Titles.mp4",
            "data/072_SHARP_Footage_Shantyboat_Flyby_Titles.mp4",
            "data/1900 Victorian Time Machine - Parade with Brass Bands (Speed Corrected w_ Sound).mp4"
        ]
        self.current_index = 0

        # PyQy prep stuff
        #
        # set fullscreen mode (we could do this after the object, but let's do this early)
        #
        # in fullscreen mode, videos show up in the bottom left corner
        self.showFullScreen()
        #
        # in this window, videos are scaled only when window is manually resized
        #self.resize(680, 420)
        #
        self.init_ui()

        # VLC prep stuff
        #
        # VLC Options
        vlc_options = [
            "--embedded-video",
            "--no-audio",
            "--autoscale",
            "--fullscreen",
            "--video-on-top",
            "--no-video-title-show",
            "--random",
            "--verbose -1",
            "--canvas-aspect 3:4",
            "--no-canvas-padd"
        ]
        # Create a basic vlc instance
        self.instance = vlc.Instance(" ".join(vlc_options))
        # later used to store media object, for now blank
        self.media = None
        # Create an empty vlc media player
        self.player = self.instance.media_player_new()
        # self.mediaplayer = vlc.MediaPlayer()
        # Set to fullscreen
        #self.player.set_fullscreen(True)
        #
        # The media player has to be 'connected' to the QFrame (otherwise the
        # video would be displayed in it's own window). This is platform
        # specific, so we must give the ID of the QFrame (or similar object) to
        # vlc. Different platforms have different functions for this
        if platform.system() == "Linux":  # for Linux using the X Server
            self.player.set_xwindow(int(self.videoframe.winId()))
        elif platform.system() == "Windows":  # for Windows
            self.player.set_hwnd(int(self.videoframe.winId()))
        elif platform.system() == "Darwin":  # for MacOS
            self.player.set_nsobject(int(self.videoframe.winId()))

        # load media
        self.open_file(self.media_files[self.current_index])

        # create a timer to refresh video
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(5000)
        self.timer.timeout.connect(self.next_video)

        self.timer.start()

    def init_ui(self):
        """Set up the user interface
        """
        if platform.system() == "Darwin":  # for MacOS
            self.videoframe = QtWidgets.QMacCocoaViewContainer(0)
        else:
            self.videoframe = QtWidgets.QFrame()
        # set videoframe color
        self.palette = self.videoframe.palette()
        self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0))
        self.videoframe.setPalette(self.palette)
        self.videoframe.setAutoFillBackground(True)
        self.setCentralWidget(self.videoframe)

    def open_file(self, filename):
        """Open a media file in a MediaPlayer
        """
        if not filename:
            return
        # getOpenFileName returns a tuple, so use only the actual file name
        self.media = self.instance.media_new(filename)
        # Put the media in the media player
        self.player.set_media(self.media)
        # Parse the metadata of the file
        self.media.parse()
        # Start playing the video as soon as it loads
        self.player.play()

    def next_video(self):
        self.current_index += 1
        if self.current_index >= len(self.media_files):
            self.current_index = 0
        self.open_file(self.media_files[self.current_index])
        return


def main():
    """Entry point for our simple vlc player
    """
    app = QtWidgets.QApplication(sys.argv)

    player = Player()
    player.show()

    # _ = Client("localhost", 10000, data_queue)
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

理想情况下,我想制作一个从不调整大小以填充窗口/屏幕的全屏播放器。

如果您可以对 pyqt 代码进行调整以消除对 vboxlayout 的需求,则可以加分。编辑:固定。谢谢@alec

这是我在播放视频时看到的内容:

视频显示在左下角

标签: pythonpyqt5vlc

解决方案


推荐阅读