Python+Tkinter制作音頻格式轉換器

????????我們將使用Python的Tkinter庫來構建一個音頻格式轉換器界面。由于音頻轉換需要實際的處理,我們將使用`pydub`庫(需要安裝)來進行音頻格式轉換。同時,我們會使用`ffmpeg`作為后端,因此請確保系統中已安裝ffmpeg并添加到環境變量,或者我們將提供一種方式讓用戶指定ffmpeg路徑。 功能要求:

1. 支持選擇多個音頻文件(批量轉換)或單個文件(單獨轉換)

2. 支持選擇輸出格式(如mp3, wav, flac, aac等)

3. 支持選擇輸出目錄

4. 開始轉換按鈕,顯示轉換進度(由于批量轉換,我們可以用進度條或者日志方式)

5. 轉換過程中顯示轉換狀態(成功/失敗) 界面設計:

????????- 文件選擇:一個按鈕用于添加文件,一個按鈕用于添加文件夾(批量添加),一個列表顯示已選文件。

????????- 輸出格式選擇:下拉菜單(Combobox)列出支持的格式。

????????- 輸出目錄選擇:一個按鈕用于選擇目錄,一個標簽顯示當前選擇的目錄。

????????- 轉換按鈕:開始轉換。

????????- 日志區域:用于顯示轉換進度和結果(可以用Text組件)。

步驟:

1. 導入必要的庫:tkinter, ttk, filedialog, messagebox, 以及pydub(需要安裝:pip install pydub)。

2. 確保ffmpeg可用。如果不可用,可以提示用戶安裝或指定路徑(我們可以在程序初始化時設置pydub的ffmpeg路徑,但為了簡便,我們假設已安裝)。

3. 創建主窗口,設置標題。

4. 創建并布局各個組件。 注意:由于音頻轉換可能耗時,我們使用多線程來避免界面卡死。 我們將創建以下類: - AudioConverterApp: 主應用類,包含UI和事件處理。

具體實現: 首先,我們導入必要的庫:

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import threading
from pygame import mixer
from pydub import AudioSegment

注意:需要用到ffmpeg工具,請提前下載,代碼需要調用該工具進行格式轉換(可設置全局環境變量,這樣可直接調用,也可放入代碼包里面,引用包路徑即可)

#局部引入        
base_dir = os.path.dirname(os.path.abspath(__file__))
ffmpeg_path = os.path.join(base_dir, "ffmpeg", "bin", "ffmpeg.exe")
AudioSegment.converter = ffmpeg_path

編寫主體代碼:

class AudioConverterApp:def __init__(self, root):self.root = rootself.root.title("音頻格式轉換器")self.root.geometry("800x800")self.root.resizable(True, True)# 設置應用圖標try:self.root.iconbitmap("audio_icon.ico")except:pass# 創建樣式self.style = ttk.Style()self.style.configure('TFrame', background='#f0f0f0')self.style.configure('Header.TLabel', font=('Arial', 16, 'bold'), background='#4a6baf', foreground='white')self.style.configure('TButton', font=('Arial', 10), padding=5)self.style.map('TButton', background=[('active', '#4a6baf')])self.style.configure('Progress.Horizontal.TProgressbar', thickness=20, background='#4a6baf')# 創建主框架self.main_frame = ttk.Frame(root)self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)# 創建標題self.header_frame = ttk.Frame(self.main_frame)self.header_frame.pack(fill=tk.X, pady=(0, 20))self.title_label = ttk.Label(self.header_frame,text="音頻格式轉換器",style='Header.TLabel',anchor=tk.CENTER)self.title_label.pack(fill=tk.X, ipady=10)# 創建控制面板self.control_frame = ttk.LabelFrame(self.main_frame, text="轉換設置")self.control_frame.pack(fill=tk.X, pady=10)# 輸入文件選擇self.input_frame = ttk.Frame(self.control_frame)self.input_frame.pack(fill=tk.X, padx=10, pady=10)ttk.Label(self.input_frame, text="輸入文件:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))self.input_entry = ttk.Entry(self.input_frame, width=50)self.input_entry.grid(row=0, column=1, sticky=tk.EW, padx=5)self.browse_button = ttk.Button(self.input_frame,text="瀏覽文件...",command=self.browse_files,width=10)self.browse_button.grid(row=0, column=2, padx=(5, 0))# 輸出格式選擇self.format_frame = ttk.Frame(self.control_frame)self.format_frame.pack(fill=tk.X, padx=10, pady=10)ttk.Label(self.format_frame, text="輸出格式:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))self.format_var = tk.StringVar(value="mp3")self.format_combobox = ttk.Combobox(self.format_frame,textvariable=self.format_var,width=8,state="readonly")self.format_combobox['values'] = ('mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a')self.format_combobox.grid(row=0, column=1, sticky=tk.W, padx=5)# 輸出目錄選擇self.output_frame = ttk.Frame(self.control_frame)self.output_frame.pack(fill=tk.X, padx=10, pady=10)ttk.Label(self.output_frame, text="輸出目錄:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))self.output_entry = ttk.Entry(self.output_frame, width=50)self.output_entry.grid(row=0, column=1, sticky=tk.EW, padx=5)self.output_button = ttk.Button(self.output_frame,text="瀏覽目錄...",command=self.browse_output,width=10)self.output_button.grid(row=0, column=2, padx=(5, 0))# 添加批量轉換區域self.batch_frame = ttk.LabelFrame(self.control_frame, text="批量轉換")self.batch_frame.pack(fill=tk.X, padx=10, pady=10)self.batch_button = ttk.Button(self.batch_frame,text="添加文件夾...",command=self.browse_folder,width=15)self.batch_button.pack(side=tk.LEFT, padx=5, pady=5)self.clear_button = ttk.Button(self.batch_frame,text="清空列表",command=self.clear_file_list,width=10)self.clear_button.pack(side=tk.RIGHT, padx=5, pady=5)# 文件列表self.list_frame = ttk.LabelFrame(self.main_frame, text="待轉換文件")self.list_frame.pack(fill=tk.BOTH, expand=True, pady=10)# 創建帶滾動條的文件列表self.scrollbar = ttk.Scrollbar(self.list_frame)self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)self.file_list = tk.Listbox(self.list_frame,yscrollcommand=self.scrollbar.set,selectmode=tk.EXTENDED,height=8)self.file_list.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)self.scrollbar.config(command=self.file_list.yview)# 狀態和進度條self.status_frame = ttk.Frame(self.main_frame)self.status_frame.pack(fill=tk.X, pady=(10, 0))self.progress_var = tk.DoubleVar()self.progress_bar = ttk.Progressbar(self.status_frame,variable=self.progress_var,style='Progress.Horizontal.TProgressbar',mode='determinate',length=500)self.progress_bar.pack(fill=tk.X, pady=5)self.status_var = tk.StringVar(value="就緒")self.status_label = ttk.Label(self.status_frame,textvariable=self.status_var,anchor=tk.W)self.status_label.pack(fill=tk.X)# 控制按鈕self.button_frame = ttk.Frame(self.main_frame)self.button_frame.pack(fill=tk.X, pady=10)self.convert_button = ttk.Button(self.button_frame,text="開始轉換",command=self.start_conversion,width=15)self.convert_button.pack(side=tk.LEFT, padx=5)self.play_button = ttk.Button(self.button_frame,text="播放音頻",command=self.play_audio,width=15,state=tk.DISABLED)self.play_button.pack(side=tk.LEFT, padx=5)self.cancel_button = ttk.Button(self.button_frame,text="取消",command=self.cancel_conversion,width=15)self.cancel_button.pack(side=tk.RIGHT, padx=5)# 初始化變量self.files_to_convert = []self.converting = Falseself.cancel_requested = False# 初始化音頻播放器mixer.init()# 配置網格權重self.input_frame.columnconfigure(1, weight=1)self.output_frame.columnconfigure(1, weight=1)def browse_files(self):files = filedialog.askopenfilenames(title="選擇音頻文件",filetypes=(("音頻文件", "*.mp3 *.wav *.ogg *.flac *.aac *.m4a"),("所有文件", "*.*")))if files:self.files_to_convert.extend(files)self.update_file_list()def browse_folder(self):folder = filedialog.askdirectory(title="選擇包含音頻文件的文件夾")if folder:# 查找文件夾中的音頻文件audio_files = []for root, _, files in os.walk(folder):for file in files:if file.lower().endswith(('.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a')):audio_files.append(os.path.join(root, file))if audio_files:self.files_to_convert.extend(audio_files)self.update_file_list()else:messagebox.showinfo("無音頻文件", "所選文件夾中沒有找到支持的音頻文件")def browse_output(self):folder = filedialog.askdirectory(title="選擇輸出文件夾")if folder:self.output_entry.delete(0, tk.END)self.output_entry.insert(0, folder)def update_file_list(self):self.file_list.delete(0, tk.END)for file in self.files_to_convert:self.file_list.insert(tk.END, os.path.basename(file))def clear_file_list(self):self.files_to_convert = []self.file_list.delete(0, tk.END)def start_conversion(self):if not self.files_to_convert:messagebox.showwarning("無文件", "請先添加要轉換的音頻文件")returnoutput_folder = self.output_entry.get().strip()if not output_folder:messagebox.showwarning("無輸出目錄", "請選擇輸出目錄")returnif not os.path.exists(output_folder):try:os.makedirs(output_folder)except Exception as e:messagebox.showerror("錯誤", f"無法創建輸出目錄: {str(e)}")return# 禁用控制按鈕self.convert_button.config(state=tk.DISABLED)self.browse_button.config(state=tk.DISABLED)self.output_button.config(state=tk.DISABLED)self.batch_button.config(state=tk.DISABLED)self.clear_button.config(state=tk.DISABLED)self.play_button.config(state=tk.DISABLED)# 重置進度條self.progress_var.set(0)self.converting = Trueself.cancel_requested = False# 在后臺線程中運行轉換threading.Thread(target=self.convert_files, args=(output_folder,), daemon=True).start()def convert_files(self, output_folder):total_files = len(self.files_to_convert)success_count = 0failed_files = []for i, file_path in enumerate(self.files_to_convert):if self.cancel_requested:breakself.status_var.set(f"正在轉換: {os.path.basename(file_path)} ({i + 1}/{total_files})")self.progress_var.set(i / total_files * 100)try:#引入ffmpeg工具路徑,非全局變量,如果為全局變量,則下方三行代碼可注掉base_dir = os.path.dirname(os.path.abspath(__file__))ffmpeg_path = os.path.join(base_dir, "ffmpeg", "bin", "ffmpeg.exe")         AudioSegment.converter = ffmpeg_pathsound = AudioSegment.from_file(file_path)output_format = self.format_var.get()output_path = os.path.join(output_folder,os.path.splitext(os.path.basename(file_path))[0] + '.' + output_format)sound.export(output_path, format=output_format)success_count += 1except Exception as e:failed_files.append(os.path.basename(file_path))print(f"轉換失敗: {str(e)}")# 更新進度self.progress_var.set((i + 1) / total_files * 100)# 更新UIself.root.after(0, self.conversion_completed, success_count, total_files, failed_files)def conversion_completed(self, success_count, total_files, failed_files):self.converting = Falseself.progress_var.set(100)# 啟用按鈕self.convert_button.config(state=tk.NORMAL)self.browse_button.config(state=tk.NORMAL)self.output_button.config(state=tk.NORMAL)self.batch_button.config(state=tk.NORMAL)self.clear_button.config(state=tk.NORMAL)self.play_button.config(state=tk.NORMAL)# 顯示結果if success_count == total_files:self.status_var.set(f"轉換完成! 成功轉換 {success_count} 個文件")messagebox.showinfo("完成", f"成功轉換 {success_count} 個文件")else:self.status_var.set(f"轉換完成! 成功: {success_count}, 失敗: {total_files - success_count}")if failed_files:failed_list = "\n".join(failed_files)messagebox.showwarning("部分完成",f"成功轉換 {success_count} 個文件\n失敗 {len(failed_files)} 個文件:\n{failed_list}")def cancel_conversion(self):if self.converting:self.cancel_requested = Trueself.status_var.set("正在取消轉換...")else:self.root.destroy()def play_audio(self):if not self.files_to_convert:messagebox.showwarning("無文件", "沒有可播放的音頻文件")return# 獲取選中的文件selected_indices = self.file_list.curselection()if not selected_indices:messagebox.showwarning("未選擇", "請先選擇一個音頻文件")returnselected_index = selected_indices[0]if 0 <= selected_index < len(self.files_to_convert):file_path = self.files_to_convert[selected_index]try:# 停止當前播放if mixer.music.get_busy():mixer.music.stop()# 加載并播放音頻mixer.music.load(file_path)mixer.music.play()self.status_var.set(f"正在播放: {os.path.basename(file_path)}")except Exception as e:messagebox.showerror("播放錯誤", f"無法播放音頻文件: {str(e)}")if __name__ == "__main__":root = tk.Tk()app = AudioConverterApp(root)root.mainloop()

UI界面效果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89855.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89855.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89855.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Haproxy算法精簡化理解及企業級高功能實戰

文章目錄4. Haproxy的算法4.1 靜態算法4.1.1 static-rr&#xff1a;基于權重的輪詢調度1. 示例&#xff1a;4.1.2 first1. 示例2. 測試效果&#xff1a;4.2 動態算法4.2.1 roundrobin1. 示例2. 動態調整權重4.2.2 leastconn1. 示例4.3 其他算法4.3.1 source1. 示例2. 測試4.3.2…

git fork的項目遠端標準協作流程 倉庫設置[設置成upstream]

這是一個在開源協作中非常常見的配置。 簡單來說&#xff0c;upstream 在這里指的是你 Fork 來的那個原始的、官方的倉庫。 下面我們來詳細解釋一下這個 git remote -v 輸出的含義&#xff1a; 1. 兩條“遙控器” (Remotes) 你的 git 配置了兩個遠程倉庫的地址&#xff0c;就像…

[FFmpeg] 輸入輸出訪問 | 管道系統 | AVIOContext 與 URLProtocol | 門面模式

鏈接&#xff1a;https://trac.ffmpeg.org/ docs&#xff1a;FFmpeg FFmpeg 是一個強大的多媒體框架&#xff0c;旨在處理媒體處理的各個階段。 它就像一個數字媒體工廠&#xff0c;包含以下部門&#xff1a;打包/解包&#xff08;容器處理&#xff09;、 轉譯/壓縮&#xff…

微服務的編程測評系統2

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄前言工程創建創建ck-oj創建oj-modules創建具體微服務oj-system推送碼云管理員登錄邏輯分析docker安裝mysqldocker客戶端docker desktop安裝安裝mysqlmysql-plus和數據…

AR智能巡檢:電力運維的數字化變革

在電力行業快速發展的當下&#xff0c;傳統運維方式已難以滿足現代電網對高效、安全的需求。近年來&#xff0c;增強現實&#xff08;AR www.teamhelper.cn &#xff09;技術的興起為電力巡檢帶來了全新的解決方案。通過實時數據可視化、遠程協作和智能分析&#xff0c;AR技術…

NeRF和3DGS原理詳細

NeRF和3DGS一、傳統三維表征方法1.1 顯示表征1.2 隱式表征二、NeRF&#xff08;Nerual Radiance Field&#xff09;2.1 NeRF場景表示2.2 NeRF訓練流程2.3 NeRF體渲染2.4 NeRF位置編碼2.5 NeRF體素分層采樣&#xff08;Volume Hierarchical Sampling&#xff09;2.6 NeRF網絡結構…

035_ClaudeCode_MCP_介紹

035_ClaudeCode_MCP_介紹 摘要 Model Context Protocol&#xff08;MCP&#xff09;是一個開放的標準化協議&#xff0c;專為大型語言模型提供上下文數據而設計。作為Claude Code生態系統的重要組成部分&#xff0c;MCP如同"AI應用程序的USB-C端口"&#xff0c;提供…

Python 程序無法找到 Oracle 的 64 位客戶端庫 (libclntsh.so)

數據庫錯誤: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help 這個錯誤表明 Python 程序無法找到…

Kubernetes常用命令總結

文章目錄Kubernetes常用命令總結1. 集群管理命令kubectl cluster-infokubectl get nodeskubectl describe node <node-name>kubectl top nodes2. Pod相關命令kubectl get podskubectl get pods -o widekubectl describe pod <pod-name>kubectl logs <pod-name&g…

roboflow使用教程

如何利用roboflow標注自己的訓練集、調用開源數據集 官網&#xff1a;Roboflow: Computer vision tools for developers and enterprises&#xff08;國內代理進不去&#xff09; 先注冊登陸進去 訓練自己的數據集 點擊“New Project”,名字按照自己的需求來 我不想寫了&am…

IDEA中使用Tomcat兩種方式

Catalogue1 集成本地Tomcat2 Tomcat Maven插件&#xff08;推薦&#xff09;1 集成本地Tomcat 將本地Tomcat集成到Idea中&#xff0c;然后進行項目部署即可 點擊編輯配置 點擊加號 添加local的Tomcat 配置Application Server 可以修改一下Name 至此&#xff0c;配置完成 …

服務器上的文件復制到本地 Windows 系統

在 Windows 上通過 SSH 連接到 Linux 服務器后&#xff0c;如果需要將服務器上的文件復制到本地 Windows 系統&#xff0c;可以使用以下幾種方法&#xff1a;方法 1&#xff1a;使用 scp&#xff08;Secure Copy&#xff09;命令 scp&#xff08;基于 SSH 的安全復制&#xff0…

大語言模型置信度增強實戰指南

LLM怎么簡單增強置信度 在大語言模型(LLM)的應用中,“置信度增強”核心目標是提升模型輸出的可靠性(減少錯誤/幻覺) 并讓模型更清晰地表達自身的不確定性(避免“一本正經地胡說”)。常用方式可分為“輸出優化”“知識補充”“校準調整”三大類, 一、基于“推理過程優…

NLP:人名分類器案例分享

本文目錄&#xff1a;一、案例介紹&#xff08;一&#xff09;關于人名分類&#xff08;二&#xff09;人名分類數據預覽二、案例步驟&#xff08;一&#xff09;導入工具包&#xff08;二&#xff09;數據預處理1. 獲取常用的字符數量2. 國家名種類數和個數3.讀數據到內存4.構…

3分鐘實戰!用DeepSeek+墨刀AI生成智能對話APP原型圖

如今&#xff0c;AI生成原型圖已經逐漸成為產品經理的一項常用輔助技能&#xff0c;不僅能加快設計進程&#xff0c;還能顯著提升前期溝通效率。最近我嘗試將大語言模型工具與AI原型工具結合測試&#xff0c;目標是看看是否能生成更高質量的原型頁面。直到我使用DeepSeek墨刀AI…

CentOS網絡配置與LAMP環境搭建指南

一、CentOS配置網絡1、查看網卡名稱ifconfig2、找到網卡對應配置文件網卡存放路徑 &#xff1a;/etc/sysconfig/network-scriptscd /etc/sysconfig/network-scripts3、修改網卡對應配置文件使用 vi/vim 打開文件&#xff0c;查看以下內容vim ifcfg-ens33將ONBOOTno 改為 ONBOOT…

TinyMCE 富文本編輯器在 vue2 中的使用 @tinymce/tinymce-vue

TinyMCE是一款功能強大、高度可定制的富文本編輯器。官方文檔 TinyMCE DOCS tinymce-vue包的版本4及更高版本支持Vue.js 3。但不支持Vue.js 2.x。對于Vue.js 2。X應用程序&#xff0c;使用tinymce-vue版本3。 安裝TinyMCE和Vue集成包 npm install tinymce/tinymce-vue3 tiny…

LP-MSPM0G3507學習--04GPIO控制

關鍵函數&#xff1a; DL_GPIO_readPins(GPIO_Regs* gpio, uint32_t pins):同時讀一組端口DL_GPIO_writePins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;同時寫一組端口DL_GPIO_setPins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;對指定某組端口的某管腳置高DL_GPIO_cle…

LVS(Linux virtual server)-實現四層負載均衡

一、簡介LVS:Linux Virtual Server&#xff0c;負載調度器&#xff0c;內核集成&#xff0c;章文嵩&#xff0c;阿里的四層SLB(Server LoadBalance)是基 于LVSkeepalived實現LVS 官網: http://www.linuxvirtualserver.org/二、LVS運行原理2.1LVS 的集群結構2.2lvs相關概念RS&am…

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐 CNI&#xff08;Container Network Interface&#xff09;是 Kubernetes 網絡層的核心組件&#xff0c;不同 CNI 插件實現了容器間網絡通信、多租戶隔離、流量限速等功能。然而在大規模集群或高并發業務場景下&#xff0c;CNI 插…