Python3.12自制GUI工具

背景

利用空闲时间写了个GUI工具,实现ts文件转换成mp4文件。

开发环境

python3.12

PyCharm 2024.3.4(Community Edition)

ffmpeg version 2024-01-04-git-33698ef891-essentials_build

完成功能:

1. GUI调用ffmpeg -i input.ts -acodec copy -vcodec copy -f output.mp4命令完成选定ts文件的转换

待添加功能:

1. 利用ffmpeg转换yuv文件

效果图

GUI代码实现
import logging
from tkinter import Tk, Text
from tkinter import filedialog, messagebox, Menu
from tkinter import DISABLED
import os
import re
from pathlib import Path

class GUITools(object):
    def __init__(self):
        logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s %(levelname)s - %(message)s')
        self._logger = logging.getLogger(__name__)
        self._convert_list = []

    def add_log_hander(self, handler):
        self._logger.addHandler(handler)

    def open_file(self):
        filename = filedialog.askopenfilename()
        if filename:
            self._logger.info("open file {}".format(filename))

    def save_file(self):
        filename = filedialog.asksaveasfilename()
        if filename:
            self._logger.info("save file {}".format(filename))

    @classmethod
    def show_about(cls):
        messagebox.showinfo("About", "This is the About Dialog")

    def convert(self):
        file_name = filedialog.askopenfilename()
        if file_name is None:
            self._logger.error("file not found")
            return

        if file_name.endswith('.mp4'):
            self._logger.warning("mp4 no need to convert")
        elif file_name.endswith('.ts'):
            self._logger.info("begin convert ts to mp4")
            self._convert_list.append(file_name)
            self._convert_list = list(set(self._convert_list))
            self._run_ffmpeg_with_output(file_name)
        else:
            self._logger.error("file type not supported")

    def _process_chinese_filename(self, filename):
        pattern = re.compile(r'[\u4e00-\u9fff]')
        if not bool(pattern.search(filename)):
            self._logger.info("not found chinese")
        else:
            self._logger.info("found chinese")

    def _run_ffmpeg_with_output(self, file_name):
        new_file_name = Path(file_name).with_suffix('.mp4')
        if os.path.isfile(new_file_name):
            self._logger.warning("{} already exist, no need convert".format(new_file_name))
            return
        self._process_chinese_filename(file_name)
        cmd = 'ffmpeg -i {} -acodec copy -vcodec copy -f mp4 {}'.format(file_name, new_file_name)
        with os.popen(cmd, "r") as f:
            for line in f.readlines():
                self._logger.info(line)
        self._convert_list.append(file_name)
        self._convert_list = list(set(self._convert_list))

    def delete_ts(self):
        for f in self._convert_list:
            if f.endswith('.ts') and os.path.isfile(f):
                self._logger.info('remove {}'.format(f))
                os.remove(f)

    def log(self, level, msg):
        if level == logging.INFO:
            self._logger.info(msg)
        elif level == logging.WARNING:
            self._logger.warning(msg)
        elif level == logging.ERROR:
            self._logger.error(msg)
        elif level == logging.DEBUG:
            self._logger.debug(msg)
        elif level == logging.CRITICAL:
            self._logger.critical(msg)


class TextBoxHandler(logging.Handler):
    def __init__(self, textbox):
        logging.Handler.__init__(self)
        self.text_box = textbox

    def emit(self, record):
        msg = self.format(record)
        self.text_box.insert("end", msg + '\n')

    def clear_log(self):
        print('clear log ...')
        self.text_box.delete("0.0", "end")

class App(object):
    def __init__(self, gui_tool):
        self._main_win = Tk()
        self._textbox_handler = None
        self._gui_tool = gui_tool
        self._main_win.title("GUI Menu")
        self._main_win.resizable(width=False, height=False)
        self._main_win.geometry("640x480")

        text_box = Text(self._main_win)
        text_box.pack()
        self._textbox_handler = TextBoxHandler(text_box)
        self._gui_tool.add_log_hander(self._textbox_handler)

        menu_bar = Menu(self._main_win)
        file_menu = Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="Open", command=self._gui_tool.open_file, accelerator="Ctrl+O")
        file_menu.add_command(label="Save", command=self._gui_tool.save_file, accelerator="Ctrl+S")
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self._main_win.destroy, accelerator="Ctrl+Q")
        menu_bar.add_cascade(label="File", menu=file_menu)

        edit_menu = Menu(menu_bar, tearoff=0)
        edit_menu.add_command(label="Undo", command=lambda: print("Undo ..."), state=DISABLED)
        edit_menu.add_separator()
        edit_menu.add_command(label="Copy", command=lambda: print("Copy ..."))
        edit_menu.add_command(label="Paste", command=lambda: print("Paste ..."))
        menu_bar.add_cascade(label="Edit", menu=edit_menu)

        convert_menu = Menu(menu_bar, tearoff=0)
        convert_menu.add_command(label="Convert TS to MP4", command=self._gui_tool.convert)
        menu_bar.add_cascade(label="Convert", menu=convert_menu)

        tool_menu = Menu(menu_bar, tearoff=0)
        tool_menu.add_command(label="Clear Log", command=self._textbox_handler.clear_log)
        tool_menu.add_command(label="Delete TS", command=self._gui_tool.delete_ts)
        menu_bar.add_cascade(label='Tool', menu=tool_menu)

        help_menu = Menu(menu_bar, tearoff=0)
        help_menu.add_command(label="Help", command=lambda: print("Help Documents"))
        help_menu.add_command(label="About", command=GUITools.show_about, accelerator="Ctrl+A")
        menu_bar.add_cascade(label="Help", menu=help_menu)

        self._main_win.bind("<Control-o>", lambda event: self._gui_tool.open_file())
        self._main_win.bind("<Control-s>", lambda event: self._gui_tool.save_file())
        self._main_win.bind("<Control-q>", lambda event: self._main_win.destroy())
        self._main_win.bind("<Control-a>", lambda event: GUITools.show_about())

        self._main_win.config(menu=menu_bar)

    def run(self):
        self._main_win.mainloop()

def main():
    tools = GUITools()

    app = App(tools)
    app.run()

if __name__ == '__main__':
    main()
posted @ 2025-04-20 23:15  lansling09  阅读(33)  评论(0)    收藏  举报