|
本帖最后由 jtjt68 于 2025-7-14 16:19 编辑
- import os
- import tkinter as tk
- from tkinter import filedialog, scrolledtext, messagebox
- import subprocess
- import threading
- import time
- class M4AToMP3Converter:
- def __init__(self, root):
- self.root = root
- self.root.title("M4A转MP3转换器")
- self.root.geometry("600x450")
- self.root.resizable(False, False)
-
- # 设置中文字体支持
- self.font = ("SimHei", 10)
-
- # 创建源文件夹选择区域
- src_frame = tk.Frame(root, padx=10, pady=5)
- src_frame.pack(fill=tk.X)
-
- tk.Label(src_frame, text="源文件夹:", font=self.font).pack(side=tk.LEFT)
-
- self.src_path = tk.StringVar()
- src_entry = tk.Entry(src_frame, textvariable=self.src_path, width=40, font=self.font)
- src_entry.pack(side=tk.LEFT, padx=5)
-
- tk.Button(src_frame, text="浏览", command=self.browse_src_folder, font=self.font).pack(side=tk.LEFT)
-
- # 创建目标文件夹选择区域
- dest_frame = tk.Frame(root, padx=10, pady=5)
- dest_frame.pack(fill=tk.X)
-
- tk.Label(dest_frame, text="目标文件夹:", font=self.font).pack(side=tk.LEFT)
-
- self.dest_path = tk.StringVar()
- dest_entry = tk.Entry(dest_frame, textvariable=self.dest_path, width=40, font=self.font)
- dest_entry.pack(side=tk.LEFT, padx=5)
-
- tk.Button(dest_frame, text="浏览", command=self.browse_dest_folder, font=self.font).pack(side=tk.LEFT)
-
- # 创建转换按钮
- btn_frame = tk.Frame(root, padx=10, pady=10)
- btn_frame.pack(fill=tk.X)
-
- self.convert_btn = tk.Button(btn_frame, text="开始转换", command=self.start_conversion,
- font=self.font, bg="#4CAF50", fg="white", height=1)
- self.convert_btn.pack(fill=tk.X)
-
- # 创建日志区域
- log_frame = tk.Frame(root, padx=10, pady=5)
- log_frame.pack(fill=tk.BOTH, expand=True)
-
- tk.Label(log_frame, text="转换日志:", font=self.font).pack(anchor=tk.W)
-
- self.log_text = scrolledtext.ScrolledText(log_frame, wrap=tk.WORD, width=70, height=15, font=self.font)
- self.log_text.pack(fill=tk.BOTH, expand=True, pady=5)
-
- # 状态变量
- self.is_converting = False
-
- # 初始化日志
- self.log("欢迎使用M4A转MP3转换器!")
- self.log("请选择源文件夹和目标文件夹,然后点击开始转换按钮。")
-
- def log(self, message):
- """添加日志到日志框"""
- timestamp = time.strftime("%H:%M:%S")
- self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
- self.log_text.see(tk.END)
-
- def browse_src_folder(self):
- """浏览并选择源文件夹"""
- folder = filedialog.askdirectory(title="选择源文件夹")
- if folder:
- self.src_path.set(folder)
- self.log(f"已选择源文件夹: {folder}")
-
- def browse_dest_folder(self):
- """浏览并选择目标文件夹"""
- folder = filedialog.askdirectory(title="选择目标文件夹")
- if folder:
- self.dest_path.set(folder)
- self.log(f"已选择目标文件夹: {folder}")
-
- def start_conversion(self):
- """开始转换过程"""
- if self.is_converting:
- self.log("正在进行转换,请等待当前任务完成...")
- return
-
- src_folder = self.src_path.get()
- dest_folder = self.dest_path.get()
-
- if not src_folder or not dest_folder:
- messagebox.showerror("错误", "请选择源文件夹和目标文件夹!")
- return
-
- if not os.path.exists(src_folder):
- messagebox.showerror("错误", "源文件夹不存在!")
- return
-
- if not os.path.exists(dest_folder):
- try:
- os.makedirs(dest_folder)
- self.log(f"已创建目标文件夹: {dest_folder}")
- except:
- messagebox.showerror("错误", "无法创建目标文件夹!")
- return
-
- # 获取所有m4a文件
- m4a_files = [f for f in os.listdir(src_folder) if f.lower().endswith('.m4a')]
-
- if not m4a_files:
- messagebox.showinfo("信息", "源文件夹中未找到M4A文件!")
- return
-
- self.log(f"找到 {len(m4a_files)} 个M4A文件,开始转换...")
-
- # 禁用按钮
- self.convert_btn.config(state=tk.DISABLED, text="转换中...")
- self.is_converting = True
-
- # 在新线程中执行转换,避免GUI冻结
- threading.Thread(target=self.convert_files, args=(m4a_files, src_folder, dest_folder), daemon=True).start()
-
- def convert_files(self, m4a_files, src_folder, dest_folder):
- """执行文件转换"""
- success_count = 0
- fail_count = 0
-
- for i, filename in enumerate(m4a_files, 1):
- try:
- self.log(f"正在转换文件 ({i}/{len(m4a_files)}): {filename}")
-
- src_file = os.path.join(src_folder, filename)
- mp3_filename = os.path.splitext(filename)[0] + '.mp3'
- dest_file = os.path.join(dest_folder, mp3_filename)
-
- # 使用ffmpeg进行转换
- # -i: 输入文件
- # -vn: 不包含视频
- # -acodec libmp3lame: 使用mp3编码
- # -q:a 2: 音频质量,2是比较好的质量
- # -y: 覆盖已存在的文件
- cmd = [
- 'ffmpeg',
- '-i', src_file,
- '-vn',
- '-acodec', 'libmp3lame',
- '-q:a', '2',
- '-y',
- dest_file
- ]
-
- result = subprocess.run(cmd, capture_output=True, text=True)
-
- if result.returncode != 0:
- self.log(f"转换失败: {filename}")
- self.log(f"错误信息: {result.stderr}")
- fail_count += 1
- else:
- self.log(f"成功转换: {mp3_filename}")
- success_count += 1
-
- except Exception as e:
- self.log(f"处理文件时出错: {filename}")
- self.log(f"错误信息: {str(e)}")
- fail_count += 1
-
- # 转换完成,更新UI
- self.root.after(0, self.conversion_complete, success_count, fail_count)
-
- def conversion_complete(self, success_count, fail_count):
- """转换完成后的处理"""
- total_count = success_count + fail_count
- self.log(f"转换完成!成功: {success_count}, 失败: {fail_count}, 总计: {total_count} 个文件")
-
- # 启用按钮
- self.convert_btn.config(state=tk.NORMAL, text="开始转换")
- self.is_converting = False
-
- # 显示完成消息
- messagebox.showinfo("完成", f"转换完成!\n成功: {success_count}\n失败: {fail_count}\n总计: {total_count} 个文件")
- if __name__ == "__main__":
- root = tk.Tk()
- app = M4AToMP3Converter(root)
- root.mainloop()
复制代码 用AI写了个,能用,要把[color=rgba(0, 0, 0, 0.85)]FFmpeg放在同一文件夹里 |
|