Сваляне на MP3 файлове от YouTube

Сваляне на MP3 файлове от YouTube

Този скрипт представлява графичен потребителски интерфейс (GUI) за сваляне на аудио файлове от YouTube и ги конвертира във формат MP3. Скриптът използва библиотеки като tkinter за създаване на GUI и pytube за сваляне и обработка на видео от YouTube.

Инструкции за използване

  1. Въвеждане на URL адрес: Въведете URL адреса на YouTube видеото, от което искате да свалите аудио, в текстовото поле "URL адрес".
  2. Поставяне на URL адрес: Можете да поставите URL адреса, като натиснете бутона "Постави URL". Този бутон ще постави текста от клипборда в полето за URL адрес.
  3. Избор на дестинация: Можете да изберете папка, в която да се запазят свалените аудио файлове. За да изберете дестинация, натиснете бутона "Избери папка" и изберете желаната папка в диалогов прозорец.
  4. Избор на качество на звука: Можете да изберете желаното качество на аудио файла, използвайки падащото меню "Избери качество на звук".
  5. Изтегляне на аудио: След като сте въвели URL адреса, избрали дестинация и качество на звука, натиснете бутона "Изтегли" за да започнете свалянето и конвертирането на аудио файла. След успешно сваляне ще видите съобщение за завършено сваляне.

Забележка

  • Скриптът изисква наличие на Python и библиотеките tkinter и pytube. Уверете се, че сте ги инсталирали преди да използвате скрипта.
  • URL адресите на YouTube видеа трябва да са валидни и да съдържат аудио съдържание, което може да бъде свалено.

Как да започнете

Трябва да започнете със създаване на нов файл с разширение ".py". Отворете любимият си тестов редактор и добавете следният код:

# Author     : Fedya Serafiev
# Version    : 1.3
# License    : MIT
# Copyright  : Fedya Serafiev (2024)
# Contact    : https://urocibg.eu/

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
import yt_dlp
import os
import re
from urllib.parse import urlparse, parse_qs

class YouTubeDownloader:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("YouTube MP3 Downloader")
        self.root.geometry("600x400")
        self.root.resizable(True, True)
        
        
        # Добавяне на икона
        try:
            self.root.iconbitmap("icon.ico")  # Уверете се, че файлът "icon.ico" е в същата папка
        except Exception as e:
            print(f"Неуспешно зареждане на икона: {e}")
        
        
        # Задаване на базови цветове за интерфейса
        self.root.configure(bg='#f0f0f0')
        
        # Създаване на главна рамка с фон
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # URL секция
        self.create_url_section()
        
        # Дестинация секция
        self.create_destination_section()
        
        # Прогрес секция
        self.create_progress_section()
        
        # Бутони за действие
        self.create_action_buttons()
        
        # Статус
        self.status_label = ttk.Label(self.main_frame, 
                                    text="Готов за сваляне",
                                    font=('Helvetica', 10))
        self.status_label.pack(pady=5)

    def create_url_section(self):
        url_frame = ttk.LabelFrame(self.main_frame, text="URL адрес", padding="5")
        url_frame.pack(fill=tk.X, pady=5)
        
        self.url_entry = ttk.Entry(url_frame, width=50)
        self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        paste_button = tk.Button(url_frame, 
                               text="Постави URL",
                               command=self.paste_url,
                               bg='#2196F3',
                               fg='white',
                               relief=tk.RAISED,
                               borderwidth=1,
                               cursor='hand2')  # Добавен курсор тип "ръка"
        paste_button.pack(side=tk.RIGHT, padx=5)

    def create_destination_section(self):
        dest_frame = ttk.LabelFrame(self.main_frame, text="Дестинация", padding="5")
        dest_frame.pack(fill=tk.X, pady=5)
        
        self.destination_var = tk.StringVar(value=os.getcwd())
        self.destination_entry = ttk.Entry(dest_frame, textvariable=self.destination_var)
        self.destination_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        dest_button = tk.Button(dest_frame, 
                              text="Избери папка",
                              command=self.choose_destination,
                              bg='#FF9800',
                              fg='white',
                              relief=tk.RAISED,
                              borderwidth=1,
                              cursor='hand2')  # Добавен курсор тип "ръка"
        dest_button.pack(side=tk.RIGHT, padx=5)

    def create_progress_section(self):
        progress_frame = ttk.Frame(self.main_frame)
        progress_frame.pack(fill=tk.X, pady=10)
        
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(
            progress_frame,
            variable=self.progress_var,
            maximum=100,
            mode='determinate',
            length=300
        )
        self.progress_bar.pack(fill=tk.X)

    def create_action_buttons(self):
        button_frame = ttk.Frame(self.main_frame)
        button_frame.pack(fill=tk.X, pady=5)
        
        # Бутон за сваляне
        download_button = tk.Button(
            button_frame,
            text="Изтегли",
            command=self.start_download,
            bg='#4CAF50',
            fg='white',
            relief=tk.RAISED,
            borderwidth=1,
            width=15,
            cursor='hand2',  # Добавен курсор тип "ръка"
            font=('Helvetica', 10, 'bold')
        )
        download_button.pack(side=tk.LEFT, padx=5)
        
        # Бутон за отказ
        cancel_button = tk.Button(
            button_frame,
            text="Отказ",
            command=self.cancel_download,
            bg='#f44336',
            fg='white',
            relief=tk.RAISED,
            borderwidth=1,
            width=15,
            cursor='hand2',  # Добавен курсор тип "ръка"
            font=('Helvetica', 10)
        )
        cancel_button.pack(side=tk.LEFT, padx=5)

        # Добавяме hover ефекти
        for button in (download_button, cancel_button):
            button.bind('<Enter>', lambda e, b=button: self.on_hover(e, b))
            button.bind('<Leave>', lambda e, b=button: self.on_leave(e, b))

    def on_hover(self, event, button):
        """Ефект при hover върху бутон"""
        if button['bg'] == '#4CAF50':  # Зелен бутон
            button.configure(bg='#45a049')
        elif button['bg'] == '#f44336':  # Червен бутон
            button.configure(bg='#da190b')
        elif button['bg'] == '#2196F3':  # Син бутон
            button.configure(bg='#1976D2')
        elif button['bg'] == '#FF9800':  # Оранжев бутон
            button.configure(bg='#F57C00')

    def on_leave(self, event, button):
        """Възстановяване на оригиналния цвят"""
        if button['bg'] in ['#45a049']:  # Зелен бутон
            button.configure(bg='#4CAF50')
        elif button['bg'] in ['#da190b']:  # Червен бутон
            button.configure(bg='#f44336')
        elif button['bg'] in ['#1976D2']:  # Син бутон
            button.configure(bg='#2196F3')
        elif button['bg'] in ['#F57C00']:  # Оранжев бутон
            button.configure(bg='#FF9800')

    def paste_url(self):
        try:
            clipboard_text = self.root.clipboard_get()
            self.url_entry.delete(0, tk.END)
            self.url_entry.insert(0, clipboard_text)
        except tk.TclError:
            messagebox.showwarning("Предупреждение", "Няма текст в клипборда")

    def choose_destination(self):
        chosen_folder = filedialog.askdirectory()
        if chosen_folder:
            self.destination_var.set(chosen_folder)

    def validate_youtube_url(self, url):
        if not url:
            return False
            
        patterns = [
            r'^https?:\/\/(?:www\.)?youtube\.com\/watch\?v=[\w-]+',
            r'^https?:\/\/(?:www\.)?youtu\.be\/[\w-]+',
            r'^https?:\/\/(?:www\.)?youtube\.com\/playlist\?list=[\w-]+'
        ]
        
        return any(re.match(pattern, url) for pattern in patterns)

    def progress_hook(self, d):
        if d['status'] == 'downloading':
            try:
                progress = (d['downloaded_bytes'] / d['total_bytes']) * 100
                self.progress_var.set(progress)
                self.status_label.config(text=f"Сваляне: {progress:.1f}%")
                self.root.update()
            except:
                pass
        elif d['status'] == 'finished':
            self.status_label.config(text="Конвертиране в MP3...")
            self.root.update()

    def start_download(self):
        url = self.url_entry.get().strip()
        
        if not self.validate_youtube_url(url):
            messagebox.showerror("Грешка", "Невалиден YouTube URL адрес")
            return
            
        destination = self.destination_var.get()
        if not os.path.exists(destination):
            messagebox.showerror("Грешка", "Невалидна дестинация")
            return

        self.progress_var.set(0)
        self.status_label.config(text="Започва сваляне...")
        
        ydl_opts = {
            'format': 'bestaudio/best',
            'postprocessors': [{
                'key': 'FFmpegExtractAudio',
                'preferredcodec': 'mp3',
                'preferredquality': '192',
            }],
            'outtmpl': os.path.join(destination, '%(title)s.%(ext)s'),
            'progress_hooks': [self.progress_hook],
            'no_warnings': True,
            'quiet': True
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])
            
            self.progress_var.set(100)
            self.status_label.config(text="Готово!")
            messagebox.showinfo("Успех", "Файлът беше успешно свален и конвертиран в MP3 формат.")
        except Exception as e:
            self.status_label.config(text="Грешка при сваляне")
            messagebox.showerror("Грешка", f"Грешка при свалянето: {str(e)}")
        finally:
            self.progress_var.set(0)

    def cancel_download(self):
        self.status_label.config(text="Свалянето е отказано")
        self.progress_var.set(0)

    def run(self):
        # Центриране на прозореца на екрана
        window_width = 600
        window_height = 400
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        center_x = int(screen_width/2 - window_width/2)
        center_y = int(screen_height/2 - window_height/2)
        self.root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
        
        self.root.mainloop()

if __name__ == "__main__":
    app = YouTubeDownloader()
    app.run()

Запазете файла и му дайте име, примерно youtube-downloader.py

Стартиране на скрипта

За да стартирате скрипта, просто кликнете два пъти върху файла youtube-downloader.py

Този скрипт предоставя удобен начин за сваляне и конвертиране на аудио от YouTube и може да бъде полезен за всички, които искат да създават собствени музикални колекции.

Федя Серафиев

Федя Серафиев

Федя Серафиев e собственик на уебсайта urocibg.eu. Той намира удовлетворение в това да помага на хората да решават и най-сложните технически проблеми. Сегашната му цел е да пише лесни за следване статии, така че подобни проблеми изобщо да не възникват.

Благодарим ви за прочитането на статията! Ако намерихте информацията за полезна, можете да дарите посредством бутоните по-долу: