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

news2024/12/23 4:33:31

当代技术让我们能够创建各种有趣和实用的应用程序。在本篇博客中,我们将探索一个基于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来进行视频剪辑。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity实现广告滚动播放、循环播放、鼠标切换的效果

效果: 场景结构: 特殊物体:panel下面用排列组件horizent layout group放置多个需要显示的面板,用mask遮罩好。 using System.Collections; using System.Collections.Generic; using DG.Tweening; using UnityEngine; using Unity…

达梦数据库curd的简单使用

目录 添加表空间 删除表空间 添加表空间 create tablespace "test_db" datafile E:\dm_data\DM6.DBF size 32--制定路径 create tablespace “test_db”:创建一个名为test_db的表空间 datafile ‘DM6.DBF’:表示数据文件名为TDM6.DBF&…

胖小酱之听话

首先,我们来看看何为“物质奖励”? 所谓的物质奖励,简单通俗地说就是运用物质上的满足,去调动孩子的积极、主动和创造能力,其中物质奖励的形式一般体现在各种实物的需求方面,比如游戏机、玩具车、手机…

富仕转债上市价格预测

富仕转债 基本信息 转债名称:富仕转债,评级:AA-,发行规模:5.7亿元。 正股名称:四会富仕,今日收盘价:36.29元,转股价格:41.77元。 当前转股价值 转债面值 / 转…

Windows共享文件夹,用户密码访问

Windows共享文件夹,用户密码访问 小白教程,一看就会,一做就成。 1.先创建一个用户 计算机右键----管理----本地用户和组----点击用户进去---右键新建用户 这里以kk为例 2.找到你想共享的文件夹 3.共享-想共享的文件夹---右键---属性---共…

优化Python代理爬虫的应用

当我们在资源受限的环境中使用Python代理爬虫时,我们需要采取一些优化措施,以确保程序的高效性和稳定性。在本文中,我将分享一些关于如何优化Python代理爬虫在资源受限环境下的应用的实用技巧。 首先我们来了解,哪些情况算是资源…

Anolis 8.6 下 Redis 7.2.0 集群搭建和配置

Redis 7.2.0 搭建和集群配置 一.Redis 下载与单机部署1.Redis 下载2.虚拟机配置3.Redis 单机源码安装和测试4.Java 单机连接测试1.Pom 依赖2.配置文件3.启动类4.配置类5.单元测试6.测试结果 二.Redis 集群部署1.主从1.从节点配置2.Java 测试 2.哨兵1.哨兵节点配置2.复制一个哨兵…

tkinter自定义多参数对话框

文章目录 参数对话框自定义参数对话框 参数对话框 tkinter提供了三种参数对话框,用于输出浮点型、整型和字符串,分别是askfloat, askinteger以及askstring,使用方法如下 代码如下 import tkinter as tk from tkinter.simpledialog import *…

使用StreamLold写入 Starrocks报错:Caused by org

问题描述 使用StreamLoad写入Starrocks报错&#xff0c;报这个错误:Caused by: org.apache.http.ProtocolException: Content-Length header already present 代码案例 引入依赖 <!-- Starrocks使用StreamLoad发送Http请求 --><dependency><groupId>or…

三维模型OBJ格式轻量化压缩变形现象分析

三维模型OBJ格式轻量化压缩变形现象分析 三维模型的OBJ格式轻量化压缩是一种常见的处理方法&#xff0c;它可以减小模型文件的体积&#xff0c;提高加载和渲染效率。然而&#xff0c;在进行轻量化压缩过程中&#xff0c;有时会出现模型变形的现象&#xff0c;即压缩后的模型与…

【面试高频题】值得仔细推敲的贪心及其证明

题目描述 这是 LeetCode 上的 「1846. 减小和重新排列数组后的最大元素」 &#xff0c;难度为 「中等」。 Tag : 「贪心」 给你一个正整数数组 arr。 请你对 arr 执行一些操作&#xff08;也可以不进行任何操作&#xff09;&#xff0c;使得数组满足以下条件&#xff1a; arr 中…

Cesium.Entity图片纹理在不同观察角度有不同亮度

Cesium.Entity图片纹理在不同观察角度有不同亮度 测试代码&#xff1a; viewer.entities.add({rectangle: {coordinates: Cesium.Rectangle.fromDegrees(-92.0, 30.0, -76.0, 40.0),material: "../images/rect.png",} }); 测试图片&#xff1a; rect.png 这个图片…

vue 学习笔记 简单实验

1.代码(html) <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"counter">Counter: {{ counter }} </div> <script> const Counter {data() {return {counter: 5}} } Vue.cr…

★80交流驱动器通过rs485接口设置速度(附ascii表)

1抓取的数据及解析 2手册上的通信协议及数据帧说明 说明:双向传输项目 3硬件接线注意事项 用的RSJ45端子&#xff0c;双传项目中&#xff0c;一头用的pin6的水晶头子&#xff08;直流离心机上用过是可以的&#xff09;&#xff0c;另一个用的pin8的水晶头子&#xff0c;这里最…

Linux常用命令——dhcrelay命令

在线Linux命令查询工具 dhcrelay 使用dhcrelay命令可以提供中继DHCP和BOOTP请求 补充说明 dhcrelay命令使用dhcrelay命令可以提供中继DHCP和BOOTP请求&#xff0c;从一个没有DHCP服务器的子网直接连接到其它子网内的一个或多个DHCP服务器。该命令在DHCP中继服务器上使用&am…

【MPLS LDP】安全策略

正在备考华为认证的小伙伴应该知道&#xff0c;除了理论知识外&#xff0c;刷题也相当重要&#xff0c;周工这里有一份HCIAHCIP-Datacom带解析的最新题库 点赞留言 即可领取。 LDP协议 安全策略介绍 LDP MD5验证 MD5称为Message-Digest Algorithm 5&#xff0c;是国际标准摘…

面试题(一)

目录 一.@Transactional 原理和常见的坑 前期准备 事务不生效的几种 Case 原理 源码解读 @Transactional 执行机制 private 导致事务不生效原因 异常不匹配原因 两种 @Transactional Spring @Transactional javax.transaction.Transactional 二.@Autowired 和 @R…

EasyExcel实现文件分批次导入

文章目录 EasyExcel引入依赖表结构项目结构DozerUtils工具类实体类StudentController监听类ServiceServiceImplmapper 启动项目测试测试数据PostMan测试 EasyExcel EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存…

智能交通顶会 IEEE ITSC工作 LimSim:长期交互式多场景交通仿真器(已开源)

交通仿真器是自动驾驶技术发展的重要支撑。交通仿真器可以在虚拟环境中仿真各种交通场景和车辆行驶情况&#xff0c;从而提高测试效率、降低测试风险、提高测试准确性和加速开发周期&#xff0c;是自动驾驶技术验证和优化的重要手段之一。 **LimSim是由上海人工智能实验室智能…

怎么把PDF转成Word?需要注意什么事项?

PDF是一种常见的文档格式&#xff0c;但是与Word文档不同&#xff0c;PDF文件通常不能直接编辑。如果您想编辑PDF文件中的文本&#xff0c;或者想将PDF文件转换为Word文档&#xff0c;下面我们就来看一看把PDF转成Word有哪些方法和注意事项。 PDF转Word工具 有许多将PDF转换为…