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

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

准备工作

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

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

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

pip install wxPython opencv-python moviepy

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

导入库

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

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

创建文件列表窗口

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

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方法,以处理选择文件夹的事件。

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方法,用于更新文件列表框中显示的文件列表。

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方法,以处理播放按钮的点击事件。

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子类,用于显示四路视频播放器的窗口。

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子类,用于显示单个视频播放器。

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窗口,并运行应用程序的主事件循环。

def main():
    app = wx.App()
    frame = FileListFrame()
    frame.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

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

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来进行视频剪辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/93401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023最新任务悬赏平台源码uniapp+Thinkphp新款悬赏任务地推拉新充场游戏试玩源码众人帮威客兼职任务帮任务发布分销机

新款悬赏任务地推拉新充场游戏试玩源码众人帮威客兼职任务帮任务发布分销机制 后端是:thinkphpFastAdmin 前端是:uniapp 1.优化首页推荐店铺模块如有则会显示此模块没有则隐藏。 2修复首页公告,更改首页公告逻辑。(后台添加有公…

redis 6个节点(3主3从),始终一个节点不能启动

redis节点,始终有一个节点不能启动起来 1.修改了配置文件 protected-mode no,重启 修改了配置文件 protected-mode no,重启redis问题依然存在 2、查看/var/log/message的redis日志 Aug 21 07:40:33 redisMaster kernel: Out of memory: K…

Jumpserver堡垒机管理(安装和相关操作)-------从小白到大神之路之学习运维第89天

第四阶段 时 间:2023年8月28日 参加人:全班人员 内 容: Jumpserver堡垒机管理 目录 一、堡垒机简介 (一)运维常见背黑锅场景 (二)背黑锅的主要原因 (三)解决背黑…

SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第三天)动态SQL

动态SQL—SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录(第三天)Mybatis的动态SQL操作 昨天我们深入学习了Mybatis的核心对象SqlSessionFactoryBuilder,掌握MyBatis核心配置文件以及元素的使用,也掌握My…

4-1-netty

非阻塞io 服务端就一个线程,可以处理无数个连接 收到所有的连接都放到集合channelList里面 selector是有事件集合的 对server来说优先关注连接事件 遍历连接事件

小研究 - Java虚拟机性能及关键技术分析

利用specJVM98和Java Grande Forum Benchmark suite Benchmark集合对SJVM、IntelORP,Kaffe3种Java虚拟机进行系统测试。在对测试结果进行系统分析的基础上,比较了不同JVM实现对性能的影响和JVM中关键模块对JVM性能的影响,并提出了提高JVM性能的一些展望。…

Leetcode 2651.计算列车到站时间

给你一个正整数 arrivalTime 表示列车正点到站的时间(单位:小时),另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意,该问题中的时间采用 24 小时制。 示例 1: 输入&…

什么样的人适合开抖店?最后一个条件必须满足!抖店开通门槛如下

我是王路飞。 作为现在热门的电商项目,抖店显然已经取代直播带货,成为了普通人在抖音卖货的新渠道,毕竟做账号和开直播对普通人来说,门槛太高了。 那么,在抖音开店,是谁都可以开吗?开店有什么…

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(上)

温故知新 📚第一章 前言📗背景📗目的📗总体方向 📚第二章 基本环境信息📗机器信息📗软件信息📗部署用户kubernetes 📚第三章 Kubernetes各组件部署📗安装kube…

基于MATLAB/Simulink的三相并网逆变器dq阻抗建模及扫频仿真

目录 整体系统介绍理论模型MATLAB实现 基于Simulink的阻抗扫频仿真整体思路注意事项流程框图 其他 本文主要介绍三相并网逆变器dq阻抗建模的相关知识,和大家分享一下怎么使用MATLAB/Simulink来进行理论模型的搭建以及如何通过扫频获取阻抗模型,一方面是给…

分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测

分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测 目录 分类预测 | MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SSA-CNN-SVM基于麻雀算法优化卷积支持向量机分类预测…

k8s的学习篇1

一 k8s的概念 1.1 k8s k8s是一个轻量级的,用于管理容器化应用和服务的平台。通过k8s能够进行应用的自动化部署和扩容缩容。 1.2 k8s核心部分 1.prod: 最小的部署单元;一组容器的集合;共享网络;生命周期是短暂的; …

hive-列转行

转成 select customer_code,product_type from temp.temp_xx LATERAL VIEW explode(SPLIT(product_types,,)) table_tmp AS product_type where customer_code K100515182

数据结构(Java实现)-优先级队列(堆)

队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队 列在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。 这种数据结构就…

Seaborn绘制热力图的子图

Seaborn绘制热力图的子图 提示:如何绘制三张子图 绘制的时候,会出现如下问题 (1)如何绘制1*3的子图 (2)三个显示条,如何只显示最后一个 提示:下面就展示详细步骤 Seaborn绘制热力…

权限提升-手工-系统权限提升

权限提升基础信息 1、具体有哪些权限需要我们了解掌握的? 后台权限,网站权限,数据库权限,接口权限,系统权限,域控权限等 2、以上常见权限获取方法简要归类说明? 后台权限:SQL注入,数…

8.28day48

198. 打家劫舍 - 力扣(LeetCode) 知识点:动规五部 1.dp数组的含义:dp数组表示打劫改房间的最大收益 2.递推公式:打劫i家:从后往前推 我们如果打劫第i家 那么第i-1家绝对不可能背打劫 所以:dp…

【100天精通python】Day46:python网络编程基础与入门

目录 专栏导读 1 网络编程的基础 2. 基本概念和协议 2.1 计算机网络基础 2.2 网络协议、IP地址、端口号 2.3 常见网络协议 3. 套接字编程 3.1 套接字的基本概念 3.2 套接字的基本操作 3.3 套接字通信模型和方法:send、recv 3.3.1 TCP通信模型 3.3.2 U…

Linux系统编程:线程互斥

目录 一. 与线程互斥相关的概念 二. 线程安全问题 2.1 多个执行流访问临界区资源引发线程安全问题 2.2 可重入函数和线程安全的关系 三. 互斥锁 mutex 3.1 互斥锁功能 3.2 互斥锁的使用 3.3 互斥锁的实现原理 四. 死锁问题 四. 总结 一. 与线程互斥相关的概念 临界…

9.oracle中sign函数

在Oracle/PLSQL中, sign 函数返回一个数字的正负标志. 语法如下&#xff1a;sign( number ) number 要测试标志的数字. If number < 0, then sign returns -1. If number 0, then sign returns 0. If number > 0, then sign returns 1. 应用于: Oracle 8i, Oracle …