which_online_video_win/jp_win.py
2024-05-12 21:44:07 +09:00

384 lines
16 KiB
Python

import tkinter as tk
import customtkinter
import os
from PIL import Image
from winotify import Notification, audio
from yt_dlp import YoutubeDL
import pyperclip
import threading
from tkinter import messagebox
import sys
version = "0.1"
builddate = "2023/9/14"
lib_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "lib")
cpurl = pyperclip.paste()
thm_conf = os.path.isfile("./lib/thm.png")
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self.title("which_online_video")
self.iconbitmap(r".\lib\logo.ico")
self.geometry("640x360")
self.resizable(height=False, width=False)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
self.logo_icon = customtkinter.CTkImage(Image.open(
os.path.join(lib_path, "logo32.png")), size=(32, 32))
self.info_icon = customtkinter.CTkImage(Image.open(
os.path.join(lib_path, "info32.png")), size=(32, 32))
if thm_conf:
pass
else:
thm_dummy = Image.new("L", (640, 360))
thm_dummy.save("./lib/thm.png")
self.thm_preview = customtkinter.CTkImage(Image.open(
os.path.join(lib_path, "thm.png")), size=(160, 90))
self.title_font = customtkinter.CTkFont(
family="meiryo", size=16, weight="bold")
self.info_font = customtkinter.CTkFont(family="meiryo", size=14)
self.ui_font = customtkinter.CTkFont(family="meiryo", size=12)
self.button_font = customtkinter.CTkFont(
family="meiryo", size=14, weight="bold")
self.frame = customtkinter.CTkFrame(self, corner_radius=0)
self.frame.grid(row=0, column=0, sticky="nsew")
self.frame.grid_rowconfigure(4, weight=1)
self.dl_frame_button = customtkinter.CTkButton(self.frame, width=32, height=36, border_spacing=4, image=self.logo_icon,
text="", fg_color="transparent", hover_color=("gray70", "gray30"), command=self.frame_select_dl)
self.dl_frame_button.grid(row=0, column=0, sticky="ew")
self.info_button = customtkinter.CTkButton(self.frame, width=32, height=36, border_spacing=4, image=self.info_icon,
text="", fg_color="transparent", hover_color=("gray70", "gray30"), command=self.app_info)
self.info_button.grid(row=1, column=0, sticky="ew")
# dl_frame
self.dl_frame = customtkinter.CTkFrame(self, fg_color="transparent")
self.dl_frame.grid(row=0, column=1)
self.dl_frame.grid_rowconfigure(0, weight=1)
self.dl_frame.grid_columnconfigure(0, weight=1)
self.dl_info_frame = customtkinter.CTkFrame(
self.dl_frame, fg_color="transparent")
self.dl_info_frame.grid(row=0, column=0, padx=2, pady=2)
self.dl_info_frame.grid_columnconfigure(0, weight=2)
self.dl_info_frame.grid_columnconfigure(1, weight=1)
self.dl_info_label_frame = customtkinter.CTkFrame(
self.dl_info_frame, fg_color="transparent")
self.dl_info_label_frame.grid(row=0, column=0, padx=8, pady=0)
self.dl_video_title = customtkinter.CTkLabel(
self.dl_info_label_frame, text="URLを入力してください...", width=360, font=self.title_font, wraplength=360, anchor=tk.W)
self.dl_video_title.grid(row=0, column=0, padx=2, pady=4)
self.dl_creator_title = customtkinter.CTkLabel(
self.dl_info_label_frame, text="クリップボードの内容が自動的にコピーされています。", width=360, font=self.info_font, wraplength=360, anchor=tk.W)
self.dl_creator_title.grid(row=1, column=0, padx=2, pady=4)
self.dl_video_thm = customtkinter.CTkLabel(
self.dl_info_frame, image=self.thm_preview, text="", anchor=tk.NE)
self.dl_video_thm.grid(row=0, column=1, padx=8, pady=0)
self.dl_input_frame = customtkinter.CTkFrame(
self.dl_frame, fg_color="transparent")
self.dl_input_frame.grid(row=1, column=0, padx=16, pady=2)
self.dl_input_frame.grid_rowconfigure(0, weight=1)
self.dl_input_frame.grid_columnconfigure(0, weight=1)
self.dl_url_textbox = customtkinter.CTkEntry(
self.dl_input_frame, placeholder_text="URLを入力", width=428, font=self.ui_font)
self.dl_url_textbox.grid(row=0, column=0, padx=8, pady=8)
self.dl_url_textbox.insert(0, cpurl)
self.dl_path_textbox = customtkinter.CTkEntry(
self.dl_input_frame, placeholder_text="保存先を入力...", width=428, font=self.ui_font)
self.dl_path_textbox.grid(row=1, column=0, padx=8, pady=8)
self.dl_path_paste_button = customtkinter.CTkButton(
self.dl_input_frame, text="URLを貼り付け", command=self.dl_path_paste, font=self.button_font)
self.dl_path_paste_button.grid(row=0, column=1, padx=8, pady=8)
self.dl_path_button = customtkinter.CTkButton(
self.dl_input_frame, text="保存先を選択", command=self.dl_path_select, font=self.button_font)
self.dl_path_button.grid(row=1, column=1, padx=8, pady=8)
self.pathtxt_open = open('./lib/path.txt', 'r', encoding='UTF-8')
self.dl_path_textbox.insert(0, self.pathtxt_open.read().rstrip('\n'))
self.pathtxt_open.close()
self.dl_control_frame = customtkinter.CTkFrame(
self.dl_frame, fg_color="transparent")
self.dl_control_frame.grid(row=2, column=0, padx=16, pady=6)
self.dl_control_frame.grid_rowconfigure(0, weight=1)
self.dl_control_frame.grid_columnconfigure(0, weight=1)
self.dl_cookie_switch = customtkinter.CTkSwitch(
self.dl_control_frame, text="Cookieの取得", font=self.ui_font)
self.dl_cookie_switch.grid(row=0, column=0, padx=4, pady=6)
self.dl_quality_text = customtkinter.CTkLabel(
self.dl_control_frame, text="Cookie取得元", font=self.ui_font)
self.dl_quality_text.grid(row=0, column=1, padx=2, pady=6)
self.dl_cookie_select = customtkinter.CTkComboBox(self.dl_control_frame, width=140, values=[
"firefox", "chrome", "edge", "vivaldi", "opera", "chromium", "safari"], font=self.ui_font, dropdown_font=self.ui_font)
self.dl_cookie_select.grid(row=0, column=2, padx=4, pady=6)
self.dl_audio_switch = customtkinter.CTkSwitch(
self.dl_control_frame, text="音声を出力", width=120, font=self.ui_font)
self.dl_audio_switch.grid(row=1, column=1, padx=4, pady=6)
self.dl_video_switch = customtkinter.CTkSwitch(
self.dl_control_frame, text="動画を出力", width=120, font=self.ui_font)
self.dl_video_switch.grid(row=1, column=0, padx=4, pady=6)
self.dl_video_switch.select()
self.dl_special_dir_switch = customtkinter.CTkSwitch(
self.dl_control_frame, text="SpeDir", width=120, font=self.ui_font)
self.dl_special_dir_switch.grid(row=2, column=0, padx=4, pady=6)
self.dl_acodec_select = customtkinter.CTkComboBox(self.dl_control_frame, width=140, values=[
"bestaudio", "opus", "vorbis", "aac", "mp3"], font=self.ui_font, dropdown_font=self.ui_font)
self.dl_acodec_select.grid(row=1, column=2, padx=4, pady=6)
self.dl_start_button = customtkinter.CTkButton(
self.dl_control_frame, text="ダウンロード", command=self.dl_start_thread, font=self.button_font)
self.dl_start_button.grid(row=2, column=3, padx=4, pady=6)
self.select_frame_name("dl_frame")
def select_frame_name(self, name):
self.dl_frame_button.configure(
fg_color=("gray75", "gray25") if name == "dl_frame" else "transparent")
if name == "dl_frame":
self.dl_frame.grid(row=0, column=1, sticky="nsew")
else:
self.dl_frame.grid_forget()
def frame_select_dl(self):
self.select_frame_name("dl_frame")
def dl_path_select(self):
dl_path = tk.filedialog.askdirectory(
title="保存場所を選択...", initialdir="%HOMEPATH%/Videos")
self.dl_path_textbox.delete(0, tk.END)
self.dl_path_textbox.insert(0, dl_path)
pathtxt = open('./lib/path.txt', 'w', encoding='UTF-8')
pathtxt.write(dl_path)
pathtxt.close()
def dl_path_paste(self):
cpurl = pyperclip.paste()
self.dl_url_textbox.delete(0, tk.END)
self.dl_url_textbox.insert(0, cpurl)
# ダウンロード
def dl_start_thread(self):
dl_thread = threading.Thread(target=self.dl_start)
dl_thread.start()
def dl_start(self):
if self.dl_video_switch.get() == 0 and self.dl_audio_switch.get() == 0:
messagebox.showerror("ダウンロードエラー", "動画、音声のどちらをダウンロードするかを選択してください。")
sys.exit()
if self.dl_url_textbox.get() == "":
messagebox.showerror(
"ダウンロードエラー", "URLが入力されていません。\n有効なURLを入力してから、もう一度お試しください。")
sys.exit()
if self.dl_cookie_switch.get() == 1:
cookie_warning = Notification(
app_id="which_online_video",
title="Cookieの取得は実装されていません",
msg="Cookieの取得はされず、そのまま動画をダウンロードします。",
icon=lib_path + r"\info64.png"
)
cookie_warning.set_audio(audio.Default, loop=False)
cookie_warning.show()
self.dl_start_button.configure(
text="ダウンロード中...", state="disabled", fg_color="gray")
if self.dl_video_switch.get() == 1:
dl_option = {
"outtmpl": self.dl_path_textbox.get() + r"\%(title)s.%(ext)s",
"format": "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4",
"vcodec": "h264",
"updatetime": "now"
}
if self.dl_special_dir_switch.get() == 1:
dl_option["outtmpl"] = self.dl_path_textbox.get(
) + r'\video\source\%(title)s.%(ext)s'
if thm_conf:
os.remove("./lib/thm.png")
dlp = YoutubeDL(dl_option)
video_info = dlp.extract_info(
self.dl_url_textbox.get(), download=False)
dlp_thm = YoutubeDL({"outtmpl": "./lib/thm.png"})
video_thm = video_info.get("thumbnail", "")
video_title = video_info.get("title", "タイトルなし")
video_uploader = video_info.get("uploader", "タイトルなし")
dlp_thm.download([video_thm])
self.thm_preview = customtkinter.CTkImage(Image.open(
os.path.join(lib_path, "thm.png")), size=(160, 90))
self.dl_video_thm.configure(image=self.thm_preview)
self.dl_video_title.configure(text=video_title)
self.dl_creator_title.configure(text=video_uploader)
dling_winotify_notificaiton = Notification(
app_id="which_online_video",
title="ダウンロード中...",
msg=f"{video_title}",
icon=lib_path + r"\thm.png"
)
dling_winotify_notificaiton.set_audio(audio.Default, loop=False)
dling_winotify_notificaiton.show()
dlp.download([self.dl_url_textbox.get()])
if self.dl_audio_switch.get() == 0:
dl_winotify_notificaiton = Notification(
app_id="which_online_video",
title="動画のダウンロードが完了しました。",
msg=f"{video_title}",
icon=lib_path + r"\thm.png"
)
dl_winotify_notificaiton.add_actions(
label="ファイルを開く",
launch=self.dl_path_textbox.get() + fr"\{video_title}.mp4"
)
dl_winotify_notificaiton.add_actions(
label="保存先を開く",
launch=self.dl_path_textbox.get()
)
dl_winotify_notificaiton.set_audio(audio.Reminder, loop=False)
dl_winotify_notificaiton.show()
dl_option.clear()
self.dl_start_button.configure(
text="ダウンロード", state="normal", fg_color="#3b8ed0")
else:
dl_option.clear()
if self.dl_audio_switch.get() == 1:
self.dl_audio_start()
def dl_audio_start(self):
dl_audio_option = {
'outtmpl': self.dl_path_textbox.get() + r'\%(title)s.%(ext)s',
'format': 'bestaudio[ext=m4a]'
}
if self.dl_acodec_select.get() == "opus" or self.dl_acodec_select.get() == "vorbis":
dl_audio_option['format'] = 'ogg'
elif self.dl_acodec_select.get() == "aac":
dl_audio_option['format'] = 'm4a'
elif self.dl_acodec_select.get() == "mp3":
dl_audio_option['format'] = 'bestaudio[ext=mp3]'
if self.dl_special_dir_switch.get() == 1:
dl_audio_option["outtmpl"] = self.dl_path_textbox.get(
) + r'\audio\source\%(title)s.%(ext)s'
dlp_audio = YoutubeDL(dl_audio_option)
video_info = dlp_audio.extract_info(
self.dl_url_textbox.get(), download=False)
video_title = video_info.get("title", "タイトルなし")
dlp_audio.download([self.dl_url_textbox.get()])
self.dl_start_button.configure(
text="ダウンロード", state="normal", fg_color="#3b8ed0")
if self.dl_video_switch.get() == 1 and self.dl_audio_switch.get() == 1:
dl_winotify_notificaiton = Notification(
app_id="which_online_video",
title="動画と音声のダウンロードが完了しました。",
msg=f"{video_title}",
icon=lib_path + r"\thm.png"
)
else:
dl_winotify_notificaiton = Notification(
app_id="which_online_video",
title="音声のダウンロードが完了しました。",
msg=f"{video_title}",
icon=lib_path + r"\thm.png"
)
if self.dl_special_dir_switch.get() == 1:
if self.dl_video_switch.get() == 1:
dl_winotify_notificaiton.add_actions(
label="動画ファイルを開く",
launch=self.dl_path_textbox.get(
) + fr"\video\source\{video_title}.mp4"
)
dl_winotify_notificaiton.add_actions(
label="音声ファイルを開く",
launch=self.dl_path_textbox.get(
) + fr"\audio\source\{video_title}.m4a"
)
dl_winotify_notificaiton.add_actions(
label="保存先を開く",
launch=self.dl_path_textbox.get()
)
else:
if self.dl_video_switch.get() == 1:
dl_winotify_notificaiton.add_actions(
label="動画ファイルを開く",
launch=self.dl_path_textbox.get() + fr"\{video_title}.mp4"
)
dl_winotify_notificaiton.add_actions(
label="音声ファイルを開く",
launch="'" + self.dl_path_textbox.get() +
fr"\{video_title}.m4a'"
)
dl_winotify_notificaiton.add_actions(
label="保存先を開く",
launch=self.dl_path_textbox.get()
)
dl_winotify_notificaiton.set_audio(audio.Reminder, loop=False)
dl_winotify_notificaiton.show()
dl_audio_option.clear()
def app_info(self):
print(version)
info_notification = Notification(
app_id="which_online_video",
title="バージョン情報",
msg=f"which_online_video バージョン {version} \nビルド日時 {builddate}",
icon=lib_path + r"\logo.png"
)
info_notification.show()
if __name__ == "__main__":
app = App()
app.mainloop()