wav変換ツール『黒律標』 ソースコード

以下は『黒律標』のソースコード全文です:

 
        import os
        import tkinter as tk
        from tkinter import filedialog, messagebox, scrolledtext
        from pydub import AudioSegment
        import glob
        
        SUPPORTED_EXTENSIONS = (".mp3", ".m4a", ".aac", ".ogg", ".flac", ".wma")
        
        save_folder = None
        selected_files = []
        
        def log_status(message):
            status_text.config(state="normal")
            status_text.insert(tk.END, message + "\n")
            status_text.see(tk.END)
            status_text.config(state="disabled")
        
        def convert_to_wav(file_path, output_dir):
            ext = os.path.splitext(file_path)[1].lower()
            if ext == ".wav":
                return f"スキップ: すでにWAV形式 - {os.path.basename(file_path)}"
        
            try:
                audio = AudioSegment.from_file(file_path, format=ext.replace('.', ''))
                base_name = os.path.splitext(os.path.basename(file_path))[0]
                output_path = os.path.join(output_dir, f"{base_name}-converted.wav")
        
                counter = 1
                while os.path.exists(output_path):
                    output_path = os.path.join(output_dir, f"{base_name}-converted({counter}).wav")
                    counter += 1
        
                audio.export(output_path, format="wav")
                return f"成功: {os.path.basename(output_path)} に変換"
            except Exception as e:
                return f"失敗: {os.path.basename(file_path)} - {e}"
        
        def execute_conversion():
            if not selected_files:
                messagebox.showwarning("警告", "変換対象のファイルまたはフォルダが選択されていません。")
                return
        
            output_dir = save_folder or os.path.dirname(selected_files[0])
            for file_path in selected_files:
                result = convert_to_wav(file_path, output_dir)
                log_status(result)
        
            messagebox.showinfo("変換完了", "変換処理が完了しました。詳細はステータスをご確認ください。")
        
        def choose_file():
            global selected_files
            filetypes = [("音声ファイル", "*.mp3 *.m4a *.aac *.ogg *.flac *.wma *.MP3 *.M4A *.AAC *.OGG *.FLAC *.WMA")]
            file_path = filedialog.askopenfilename(title="ファイルを選択", filetypes=filetypes)
            if file_path:
                selected_files = [file_path]
                label_selection.config(text=f"ファイル選択: {os.path.basename(file_path)}")
                log_status(f"ファイルを選択: {file_path}")
        
        def choose_folder():
            global selected_files
            folder_path = filedialog.askdirectory(title="フォルダを選択")
            if folder_path:
                label_selection.config(text=f"フォルダ選択: {folder_path}")
                log_status(f"フォルダを選択: {folder_path}")
                audio_files = []
                for ext in SUPPORTED_EXTENSIONS:
                    audio_files.extend(glob.glob(os.path.join(folder_path, f"*{ext}")))
                    audio_files.extend(glob.glob(os.path.join(folder_path, f"*{ext.upper()}")))
                selected_files = audio_files
                if not audio_files:
                    messagebox.showwarning("警告", "対応する音声ファイルが見つかりませんでした。")
                    selected_files = []
        
        def choose_save_folder():
            global save_folder
            folder = filedialog.askdirectory(title="保存先フォルダを選択")
            if folder:
                save_folder = folder
                label_save.config(text=f"保存先: {save_folder}")
                log_status(f"保存先フォルダを指定: {save_folder}")
        
        def on_close():
            root.quit()
            root.destroy()
        
        # GUIセットアップ
        root = tk.Tk()
        root.title("wav変換 - 黒律標")
        root.geometry("500x440")
        root.protocol("WM_DELETE_WINDOW", on_close)
        
        tk.Label(root, text="処理対象を選んでください", font=("Arial", 12)).pack(pady=5)
        tk.Button(root, text="ファイルを選択", width=25, command=choose_file).pack(pady=3)
        tk.Button(root, text="フォルダを選択", width=25, command=choose_folder).pack(pady=3)
        tk.Button(root, text="保存先を指定", width=25, command=choose_save_folder).pack(pady=3)
        
        label_selection = tk.Label(root, text="ファイルまたはフォルダ未選択", fg="blue")
        label_selection.pack(pady=3)
        
        label_save = tk.Label(root, text="保存先: 未指定(元フォルダに保存)", fg="green")
        label_save.pack(pady=3)
        
        tk.Button(root, text="変換を実行", width=25, height=2, bg="#004488", fg="white", font=("Arial", 10, "bold"),
                  command=execute_conversion).pack(pady=10)
        
        tk.Label(root, text="ステータス", font=("Arial", 10, "bold")).pack(pady=5)
        status_text = scrolledtext.ScrolledText(root, width=60, height=10, state="disabled")
        status_text.pack(padx=10, pady=5)
        
        root.mainloop()