File size: 3,377 Bytes
7cbe46d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1628bb3
 
 
 
 
 
 
 
 
 
 
 
7cbe46d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import os
from flask import Flask, render_template, request, jsonify, send_file
import threading
import uuid
from pathlib import Path
from yt_dlp import YoutubeDL
from PIL import Image

app = Flask(__name__, template_folder=os.getcwd())  # Set template_folder to the current directory

downloads = {}

class MusicDownloader:
    def __init__(self):
        self.download_dir = Path("downloads")
        self.download_dir.mkdir(exist_ok=True)

    def download(self, url: str, download_id: str) -> bool:
        downloads[download_id] = {'status': 'downloading', 'progress': '0%'}
        
ydl_opts = {
    'format': 'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
    'outtmpl': str(self.download_dir / '%(title)s.%(ext)s'),
    'writethumbnail': True,
    'cookiefile': 'cookies.txt',  # Path to your cookies file
    'progress_hooks': [lambda d: self._progress_hook(d, download_id)],
}

        try:
            with YoutubeDL(ydl_opts) as ydl:
                info = ydl.extract_info(url, download=True)
                title = info.get('title', 'unknown_title')

                webp_path = self.download_dir / f"{title}.webp"
                if webp_path.exists():
                    self._convert_thumbnail(webp_path)

                downloads[download_id]['status'] = 'completed'
                downloads[download_id]['title'] = title
                return True

        except Exception as e:
            downloads[download_id]['status'] = 'failed'
            downloads[download_id]['error'] = str(e)
            return False

    def _progress_hook(self, d, download_id):
        if d['status'] == 'downloading':
            downloads[download_id]['progress'] = d.get('_percent_str', '0%')

    def _convert_thumbnail(self, thumbnail_path: Path):
        try:
            with Image.open(thumbnail_path) as img:
                jpg_path = thumbnail_path.with_suffix('.jpg')
                img.convert('RGB').save(jpg_path, 'JPEG')
                thumbnail_path.unlink()
        except Exception:
            pass

@app.route('/')
def index():
    return render_template('index.html')  # No need for templates folder, index.html is in the same folder

@app.route('/download', methods=['POST'])
def start_download():
    url = request.json.get('url')
    if not url:
        return jsonify({'error': 'No URL provided'}), 400

    download_id = str(uuid.uuid4())
    downloader = MusicDownloader()

    threading.Thread(target=downloader.download, args=(url, download_id)).start()

    return jsonify({'download_id': download_id})

@app.route('/status/<download_id>')
def get_status(download_id):
    if download_id not in downloads:
        return jsonify({'status': 'not_found'}), 404
    return jsonify(downloads[download_id])

@app.route('/download/<download_id>')
def get_file(download_id):
    if download_id not in downloads or downloads[download_id]['status'] != 'completed':
        return 'File not found', 404

    title = downloads[download_id]['title']
    file_path = os.path.join('downloads', f'{title}.mp3')

    if not os.path.exists(file_path):
        return 'File not found', 404

    return send_file(file_path, as_attachment=True)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7860)  # Port set for Hugging Face Spaces