![]() |
বানানোর পর দেখতে যেমন হলো |
গতরাতে একটা ফাইল ডাউনলোড করতে চাইলাম, বেশি বড়! না, মাত্র ১০ জিবি, ব্রাউজারেই ডাউনলোড করা যাচ্ছে কিন্তু সমস্যা হল, কম্পিউটার স্লিপ মোডে গেলে ডাউনলোড বন্ধ হয়ে যায়, আবার অন করলে শুরু থেকে ডাউনলোড হয়। চিন্তা করলাম কী করা যায়, লিংক নিয়ে টার্মিনালে কমান্ড দিলাম। শুরু হল, এটাতেও সেইম সমস্যা, খুঁজে পেলাম ক্যাফেইন, যেটা দিলে ডাউনলোড হওয়া পর্যন্ত কম্পিউটার জেগে থাকে।
ডাউনলোড হওয়ার পর মনে হলো নিজের জন্য একটি ডাউনলোডার হলে মন্দ কি?
কাজ শুরু করলাম, সাথে ছিল পাইথন, শেষে যা দাঁড়ালো নিজেই অবাক হলাম-
ডাউনলোড হওয়ার পর মনে হলো নিজের জন্য একটি ডাউনলোডার হলে মন্দ কি?
কাজ শুরু করলাম, সাথে ছিল পাইথন, শেষে যা দাঁড়ালো নিজেই অবাক হলাম-
চাইলে আপনিও ব্যবহার করতে পারেন, নিচের কোডটি একটা ফাইল (file name.py) তৈরি করে পাইথনে রান করলেই হবে-
(সংবিধিবদ্ধ সতর্কীকরণ-
১। আমার উবুন্টুতে এটা কাজ করেছে, উইন্ডোজে কাজ করবে কিনা তা পরীক্ষা করা হয়নি- আপনি পরীক্ষা করলে আমাকে ফলাফল জানাবেন
২। ও হ্যাঁ আপনার সিস্টেমে অবশ্যই python3 (না থাকলে- Ubuntu: sudo apt install python3 ), tkinter (GUI এর জন্য- না থাকলে Ubuntu: sudo apt install python3-tk ) এবং aria2c (ডাউনলোড করার জন্য না থাকলে- Ubuntu: sudo apt install aria2 ) থাকতে হবে। না থাকলে ডাউনলোড করে নিতে হবে)
তাহলে শুরু করা যাক- (কপি বাটনে ক্লিক করে কোডটি কপি করে নিতে পারবেন)
import tkinter as tk from tkinter import filedialog, messagebox, simpledialog, ttk import subprocess import os import time import threading class Aria2Downloader: def __init__(self, root): self.root = root root.title("FDM-musfiq (Threaded with Progress & Close Confirm)") root.geometry("700x600") # URL input tk.Label(root, text="Download URLs (one per line):").pack() self.url_text = tk.Text(root, height=5, width=85) self.url_text.pack(pady=5) # Folder select tk.Label(root, text="Download Folder:").pack() self.folder_var = tk.StringVar() folder_frame = tk.Frame(root) folder_frame.pack() self.folder_entry = tk.Entry(folder_frame, textvariable=self.folder_var, width=60) self.folder_entry.pack(side=tk.LEFT, padx=(10, 5)) tk.Button(folder_frame, text="Browse", command=self.browse_folder).pack(side=tk.LEFT) # Buttons button_frame = tk.Frame(root) button_frame.pack(pady=10) tk.Button(button_frame, text="Start Download", command=self.start_download).pack(side=tk.LEFT, padx=10) tk.Button(button_frame, text="Pause All", command=self.pause_all).pack(side=tk.LEFT, padx=10) tk.Button(button_frame, text="Resume All", command=self.resume_all).pack(side=tk.LEFT, padx=10) tk.Button(button_frame, text="Copy Status", command=self.copy_status).pack(side=tk.LEFT, padx=10) # Progress bar tk.Label(root, text="Progress:").pack() self.progress = ttk.Progressbar(root, orient="horizontal", length=600, mode="determinate") self.progress.pack(pady=5) self.progress_label = tk.Label(root, text="Idle") self.progress_label.pack() # Status area tk.Label(root, text="Status:").pack() self.status = tk.Text(root, height=12, width=85) self.status.pack() # Download history file self.history_file = os.path.expanduser("~/aria2_download_history.txt") # Thread control self.download_thread = None # Handle window close event self.root.protocol("WM_DELETE_WINDOW", self.on_closing) def browse_folder(self): folder = filedialog.askdirectory() if folder: self.folder_var.set(folder) def copy_status(self): self.root.clipboard_clear() text = self.status.get("1.0", tk.END) self.root.clipboard_append(text) messagebox.showinfo("Copied", "Status text copied to clipboard.") def start_download(self): if self.download_thread and self.download_thread.is_alive(): messagebox.showwarning("Warning", "Download is already in progress.") return urls = self.url_text.get("1.0", tk.END).strip().splitlines() folder = self.folder_var.get().strip() if not urls or not folder: messagebox.showerror("Error", "Please enter URLs and select a folder.") return self.files = [] for url in urls: suggested_name = url.split("/")[-1] filename = simpledialog.askstring("File Name", f"Enter file name for:\n{url}", initialvalue=suggested_name) if not filename: self.status.insert(tk.END, f"Skipped: {url}\n") self.files.append((url, filename)) self.download_thread = threading.Thread(target=self.download_all, daemon=True) self.download_thread.start() def download_all(self): total = len(self.files) self.progress["maximum"] = total self.progress["value"] = 0 for idx, (url, filename) in enumerate(self.files, start=1): if not filename: self.progress["value"] = idx self.root.update() continue folder = self.folder_var.get().strip() def append_status(text): self.status.insert(tk.END, text) self.status.see(tk.END) append_status(f"\nDownloading: {filename}\n") self.progress_label.config(text=f"Downloading {filename}...") self.root.update() try: if "youtube.com" in url or "youtu.be" in url: # ইউটিউব লিঙ্ক হলে yt-dlp ব্যবহার output_path = os.path.join(folder, filename) if not os.path.splitext(output_path)[1]: output_path += ".mp4" command = [ "yt-dlp", "-f", "bestvideo+bestaudio", "-o", output_path, url ] else: # অন্য লিঙ্ক হলে aria2c ব্যবহার command = [ "aria2c", "--max-connection-per-server=16", "--split=16", "--min-split-size=1M", "--continue", "--header=User-Agent: Mozilla/5.0", "--referer=https://pixeldrain.com", "-d", folder, "-o", filename, url ] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) with open(self.history_file, "a") as hist: hist.write(f"{time.ctime()} - {filename} from {url}\n") for line in process.stdout: append_status(line) self.root.update() stderr = process.stderr.read() if stderr: append_status("\n[Error Output]:\n" + stderr) process.wait() if process.returncode == 0: self.progress_label.config(text=f"Completed: {filename}") else: self.progress_label.config(text=f"Error downloading {filename}") except Exception as e: append_status(f"Exception: {e}\n") self.progress_label.config(text="Error") self.progress["value"] = idx self.root.update() self.progress_label.config(text="All downloads completed.") def pause_all(self): os.system("pkill -STOP aria2c") os.system("pkill -STOP yt-dlp") self.status.insert(tk.END, "All downloads paused.\n") self.status.see(tk.END) self.progress_label.config(text="Paused") def resume_all(self): os.system("pkill -CONT aria2c") os.system("pkill -CONT yt-dlp") self.status.insert(tk.END, "All downloads resumed.\n") self.status.see(tk.END) self.progress_label.config(text="Resumed") def on_closing(self): if self.download_thread and self.download_thread.is_alive(): if not messagebox.askokcancel("Quit", "Download is still in progress. Are you sure you want to quit?"): return self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = Aria2Downloader(root) root.mainloop()
বাদবাকি সাজানো গোছানোর কাজ নিজেই করে নিতে পারবেন।
শুভ প্রোগ্রামিং।