-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathudio-flask-webservice.py
154 lines (128 loc) · 4.97 KB
/
udio-flask-webservice.py
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import os
import uuid
import logging
import threading
import time
from flask import Flask, request, send_file, render_template_string, jsonify
import requests
import eyed3
import magic
from io import BytesIO
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)
TEMP_DIR = ".temp"
DELETE_DELAY = 300 # 5 minutes in seconds
os.makedirs(TEMP_DIR, exist_ok=True)
# Queue to store files for deletion
delete_queue = []
def delayed_delete():
while True:
current_time = time.time()
files_to_delete = [f for f in delete_queue if current_time - f['time'] > DELETE_DELAY]
for file_info in files_to_delete:
try:
os.remove(file_info['path'])
logging.info(f"Deleted temporary file: {file_info['path']}")
delete_queue.remove(file_info)
except Exception as e:
logging.error(f"Error deleting file {file_info['path']}: {e}")
time.sleep(60) # Check every minute
# Start the background deletion task
threading.Thread(target=delayed_delete, daemon=True).start()
def generate_uuid(url):
return uuid.uuid3(uuid.NAMESPACE_URL, url)
@app.route('/', methods=['POST'])
def index():
return render_template_string('''
<!DOCTYPE html>
<html>
<head>
<title>MP3 Metadata Editor</title>
</head>
<body>
<h1>MP3 Metadata Editor</h1>
<form action="/edit_metadata" method="post">
<input type="text" name="mp3_url" placeholder="Enter MP3 URL" required /><br/>
<input type="text" name="image_url" placeholder="Enter Cover Image URL" required /><br/>
<input type="text" name="title" placeholder="Enter title" /><br/>
<input type="text" name="artist" placeholder="Enter artist" /><br/>
<input type="text" name="album" placeholder="Enter album" /><br/>
<input type="text" name="genre" placeholder="Enter genre" /><br/>
<input type="text" name="year" placeholder="Enter year" /><br/>
<input type="submit" value="Edit Metadata">
</form>
</body>
</html>
''')
@app.route('/api/download_ext', methods=['POST', 'GET'])
def download_ext():
if request.is_json:
data = request.json
elif request.method == 'POST':
data = request.form
else:
data = request.args
mp3_url = data.get('mp3_url')
image_url = data.get('image_url')
if not mp3_url or not image_url:
return jsonify({"error": "Both MP3 and image URLs are required"}), 400
try:
# Download MP3 file
mp3_response = requests.get(mp3_url)
mp3_response.raise_for_status()
mp3_data = BytesIO(mp3_response.content)
# Download image file
img_response = requests.get(image_url)
img_response.raise_for_status()
img_data = img_response.content
# Detect the mime-type of the cover image
mime = magic.Magic(mime=True)
mime_type = mime.from_buffer(img_data)
# Create a temporary file to save the MP3
temp_mp3 = os.path.join(TEMP_DIR, f"temp_{generate_uuid(mp3_url)}.mp3")
with open(temp_mp3, 'wb') as f:
f.write(mp3_data.getvalue())
# Load MP3 file with eyed3
audio = eyed3.load(temp_mp3)
if audio.tag is None:
audio.initTag()
# Add cover art
audio.tag.images.set(eyed3.id3.frames.ImageFrame.FRONT_COVER, img_data, mime_type, u'Cover')
# Add other metadata
title = data.get('title', '')
artist = data.get('artist', '')
if title:
audio.tag.title = title
if artist:
audio.tag.artist = artist
if data.get('album'):
audio.tag.album = data.get('album')
if data.get('genre'):
audio.tag.genre = data.get('genre')
if data.get('year'):
audio.tag.year = int(data.get('year'))
if data.get('canonical'):
audio.tag.audio_file_url = data.get('canonical')
if data.get('lyrics'):
audio.tag.lyrics.set(data.get('lyrics'))
# Save the changes
audio.tag.save()
# Construct the filename
if artist and title:
filename = f"{artist} - {title}.mp3"
elif title:
filename = f"{title}.mp3"
else:
filename = f"temp_{generate_uuid(mp3_url)}.mp3"
# Queue the file for deletion
delete_queue.append({'path': temp_mp3, 'time': time.time()})
# Send the modified file back to the user
return send_file(temp_mp3, as_attachment=True, download_name=filename)
except requests.RequestException as e:
logging.error(f"Error downloading files: {e}")
return jsonify({"error": f"Error downloading files: {str(e)}"}), 500
except Exception as e:
logging.error(f"Unexpected error: {e}")
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)