python编写四画面同时播放swap视频

当代技术让我们能够创建各种有趣和实用的应用程序。在本篇博客中,我们将探索一个基于wxPython和OpenCV的四路视频播放器应用程序。这个应用程序可以同时播放四个视频文件,并将它们显示在一个GUI界面中。

C:\pythoncode\new\smetimeplaymp4.py

准备工作

在开始之前,我们需要安装一些必要的库。确保你已经安装了Python和以下库:

  • wxPython:用于创建图形用户界面。
  • OpenCV:用于视频处理和播放。
  • moviepy:用于视频剪辑。

你可以使用pip来安装这些库。在命令行中运行以下命令:

复制代码
pip install wxPython opencv-python moviepy

安装完成后,我们就可以开始编写代码了。

导入库

首先,让我们导入所需的库:

python 复制代码
import os
import wx
import cv2
from moviepy.editor import VideoFileClip
  • os库用于文件和文件夹操作。
  • wx库用于创建GUI界面。
  • cv2库用于视频处理。
  • moviepy库用于视频剪辑。

创建文件列表窗口

我们将创建一个名为FileListFrame的wx.Frame子类,用于显示文件列表和选择文件夹。

python 复制代码
class FileListFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="选择MP4文件", size=(400, 300))
        self.folder_path = ""  # 添加实例变量来存储文件夹路径

        panel = wx.Panel(self)

        # 创建选择文件夹的按钮
        select_button = wx.Button(panel, label="选择文件夹")
        select_button.Bind(wx.EVT_BUTTON, self.on_select_folder)

        # 创建列表框,用于显示文件列表
        self.list_box = wx.ListBox(panel, style=wx.LB_MULTIPLE | wx.LB_HSCROLL)

        # 创建播放按钮
        play_button = wx.Button(panel, label="播放")
        play_button.Bind(wx.EVT_BUTTON, self.on_play)

        # 设置布局管理器
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(select_button, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        sizer.Add(self.list_box, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        sizer.Add(play_button, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        panel.SetSizer(sizer)

__init__方法中,我们设置了窗口的标题和大小,并初始化了一个实例变量folder_path来存储文件夹路径。

接下来,我们创建一个wx.Panel,并在其中添加了一个选择文件夹的按钮、一个文件列表框和一个播放按钮。按钮的点击事件分别绑定到了on_select_folderon_play方法。

最后,我们使用布局管理器(wx.BoxSizer)来设置控件的布局。

处理选择文件夹事件

我们需要实现on_select_folder方法,以处理选择文件夹的事件。

python 复制代码
def on_select_folder(self, event):
    dialog = wx.DirDialog(self, message="选择文件夹")
    if dialog.ShowModal() == wx.ID_OK:
        self.folder_path = dialog.GetPath()  # 存储选择的文件夹路径
        self.update_file_list(self.folder_path)
    dialog.Destroy()

在该方法中,我们创建了一个文件夹选择对话框(wx.DirDialog)。当对话框显示并用户选择了文件夹后,我们将选定的文件夹路径存储在folder_path实例变量中,并调用update_file_list方法更新文件列表框中显示的文件列表。

最后,我们销毁对话框。

更新文件列表

接下来,我们需要实现update_file_list方法,用于更新文件列表框中显示的文件列表。

python 复制代码
def update_file_list(self, folder_path):
    self.list_box.Clear()
    if folder_path:
        video_files = [f for f in os.listdir(folder_path) if f.endswith(".mp4")]
        for file in video_files:
            self.list_box.Append(file)

在该方法中,我们首先清空文件列表框中的内容,然后检查folder_path是否为空。如果不为空,我们使用os.listdir函数获取文件夹中所有的文件,并筛选出以".mp4"为扩展名的视频文件。然后,我们将这些视频文件添加到文件列表框中显示出来。

处理播放按钮事件

现在,让我们实现on_play方法,以处理播放按钮的点击事件。

python 复制代码
def on_play(self, event):
    selected_files = self.list_box.GetSelections()  # 获取选择的文件索引
    if selected_files:
        video_paths = [os.path.join(self.folder_path, self.list_box.GetString(file_index)) for file_index in selected_files]
        if len(video_paths) == 4:
            player_frame = VideoPlayerFrame(video_paths)
            player_frame.Show()
        else:
            wx.MessageBox("请选择四个视频文件!", "错误", wx.OK | wx.ICON_ERROR)
    else:
        wx.MessageBox("请选择视频文件!", "错误", wx.OK | wx.ICON_ERROR)

在该方法中,我们首先获取文件列表框中选中的文件索引。然后,我们使用这些索引来获取选中的视频文件的路径。

接下来,我们检查选中的视频文件数量是否为4。如果是4个视频文件,我们创建一个VideoPlayerFrame实例,并将视频文件路径作为参数传递给它。最后,我们显示VideoPlayerFrame窗口。

如果选中的视频文件数量不是4,或者没有选择任何视频文件,我们将显示一个错误消息框,提示用户选择正确的视频文件。

创建视频播放器窗口

我们将创建一个名为VideoPlayerFrame的wx.Frame子类,用于显示四路视频播放器的窗口。

python 复制代码
class VideoPlayerFrame(wx.Frame):
    def __init__(self, video_paths):
        super().__init__(None, title="四路视频播放器", size=(800, 600))
        self.video_players = []

        panel = wx.Panel(self)
        grid = wx.GridSizer(rows=2, cols=2, hgap=10, vgap=10)

        for path in video_paths:
            video_player = VideoPlayer(panel, path)
            grid.Add(video_player, proportion=1, flag=wx.EXPAND)
            self.video_players.append(video_player)

        panel.SetSizer(grid)
        self.Bind(wx.EVT_CLOSE, self.on_close)

__init__方法中,我们设置了窗口的标题和大小,并初始化了一个实例变量video_players,用于存储四个视频播放器的实例。

接下来,我们创建一个wx.Panel,并使用网格布局(wx.GridSizer)将四个视频播放器放置在窗口中。对于每个视频文件路径,我们创建一个VideoPlayer实例,并将其添加到网格布局中和video_players列表中。

最后,我们将网格布局设置为面板的布局管理器,并绑定窗口关闭事件到on_close方法。

创建视频播放器

现在,我们将创建一个名为VideoPlayer的wx.Panel子类,用于显示单个视频播放器。

python 复制代码
class VideoPlayer(wx.Panel):
    def __init__(self, parent, video_path):
        super().__init__(parent)

        self.video_path = video_path
        self.video_capture = cv2.VideoCapture(video_path)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)

        self.static_bitmap = wx.StaticBitmap(self)
        self.update_frame()

        self.timer.Start(30)  # 每30毫秒更新一帧

    def update_frame(self):
        ret, frame = self.video_capture.read()
        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            bitmap = wx.Bitmap.FromBuffer(frame.shape[1], frame.shape[0], frame)
            self.static_bitmap.SetBitmap(bitmap)

    def on_timer(self, event):
        self.update_frame()

__init__方法中,我们初始化了一些实例变量,包括视频文件路径、OpenCV的视频捕获对象(cv2.VideoCapture)、定时器(wx.Timer)和一个静态位图控件(wx.StaticBitmap)。

我们在update_frame方法中读取视频的下一帧,并将其转换为RGB格式。然后,我们将帧数据转换为wx.Bitmap对象,并将其设置为静态位图控件的位图。这样可以实现视频的实时播放。

on_timer方法中,我们在定时器事件触发时调用update_frame方法,以更新视频帧。

运行应用程序

现在我们已经完成了所有必要的类和方法,让我们在main函数中实例化FileListFrame窗口,并运行应用程序的主事件循环。

python 复制代码
def main():
    app = wx.App()
    frame = FileListFrame()
    frame.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

main函数中,我们创建了一个wx.App实例,并实例化了FileListFrame窗口。然后,我们显示窗口并启动应用程序的主事件循环。

##完整代码

python 复制代码
import os
import wx
import cv2
from moviepy.editor import VideoFileClip


class FileListFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="选择MP4文件", size=(400, 300))
        self.folder_path = ""  # 添加实例变量来存储文件夹路径

        panel = wx.Panel(self)

        # 创建选择文件夹的按钮
        select_button = wx.Button(panel, label="选择文件夹")
        select_button.Bind(wx.EVT_BUTTON, self.on_select_folder)

        # 创建列表框,用于显示文件列表
        self.list_box = wx.ListBox(panel, style=wx.LB_MULTIPLE | wx.LB_HSCROLL)

        # 创建播放按钮
        play_button = wx.Button(panel, label="播放")
        play_button.Bind(wx.EVT_BUTTON, self.on_play)

        # 设置布局管理器
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(select_button, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        sizer.Add(self.list_box, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        sizer.Add(play_button, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        panel.SetSizer(sizer)

    def on_select_folder(self, event):
        dialog = wx.DirDialog(self, message="选择文件夹")
        if dialog.ShowModal() == wx.ID_OK:
            self.folder_path = dialog.GetPath()  # 存储选择的文件夹路径
            self.update_file_list(self.folder_path)
        dialog.Destroy()

    def update_file_list(self, folder_path):
        self.list_box.Clear()
        if folder_path:
            video_files = [f for f in os.listdir(folder_path) if f.endswith(".mp4")]
            for file in video_files:
                self.list_box.Append(file)

    def on_play(self, event):
        selected_indices = self.list_box.GetSelections()
        if len(selected_indices) != 4:
            wx.MessageBox("请选择四个MP4文件!", "提示", wx.OK | wx.ICON_INFORMATION)
            return

        selected_files = [self.list_box.GetString(index) for index in selected_indices]
        video_paths = [os.path.join(self.folder_path, file) for file in selected_files]  # 使用实例变量

        video_player_frame = VideoPlayerFrame(video_paths)
        video_player_frame.Show()


class VideoPlayerFrame(wx.Frame):
    def __init__(self, video_paths):
        super().__init__(None, title="四路视频播放器", size=(800, 600))

        panel = wx.Panel(self)
        grid = wx.GridSizer(rows=2, cols=2, hgap=5, vgap=5)

        self.video_players = []
        for path in video_paths:
            video_player = VideoPlayer(panel, path)
            self.video_players.append(video_player)
            grid.Add(video_player, 0, wx.EXPAND)

        panel.SetSizer(grid)

        self.Bind(wx.EVT_CLOSE, self.on_close)

    def on_close(self, event):
        for video_player in self.video_players:
            video_player.release()
        event.Skip()


class VideoPlayer(wx.Panel):
    def __init__(self, parent, video_path):
        super().__init__(parent)

        self.video_path = video_path
        self.cap = cv2.VideoCapture(self.video_path)

        self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

        self.video_window = wx.StaticBitmap(self, size=(self.width, self.height))

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.update_frame, self.timer)
        self.timer.Start(30)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.video_window, 0, wx.ALL, 5)
        self.SetSizer(sizer)

    def update_frame(self, event):
        ret, frame = self.cap.read()
        if ret:
            img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            bitmap = wx.Bitmap.FromBuffer(self.width, self.height, img)
            self.video_window.SetBitmap(bitmap)

    def release(self):
        self.cap.release()


if __name__ == '__main__':
    app = wx.App()
    frame = FileListFrame()
    frame.Show()
    app.MainLoop()

总结

通过使用wxPython和OpenCV,我们成功创建了一个四路视频播放器应用程序。该应用程序允许用户选择一个包含四个MP4视频文件的文件夹,并在一个GUI界面中同时播放这四个视频文件。我们使用了wxPython来创建图形用户界面,OpenCV来处理和播放视频,以及moviepy来进行视频剪辑。

相关推荐
郭庆汝2 小时前
pytorch、torchvision与python版本对应关系
人工智能·pytorch·python
思则变5 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络6 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find7 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取8 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector9 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习10 小时前
Python入门Day2
开发语言·python
Vertira10 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉10 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗10 小时前
黑马python(二十四)
开发语言·python