import os import re import shutil import requests import gradio as gr from mutagen.mp3 import MP3 from mutagen.flac import FLAC from mutagen.id3 import TIT2, TPE1, TALB def insert_metadata(file_path: str, title, artist, album): print(f"The file was successfully downloaded and saved to {file_path}") try: if file_path.endswith(".flac"): audio = FLAC(file_path) audio["TITLE"] = title audio["ARTIST"] = artist audio["ALBUM"] = album else: audio = MP3(file_path) try: audio.add_tags() except Exception as e: print(e) audio.tags.add(TIT2(encoding=3, text=title)) audio.tags.add(TPE1(encoding=3, text=artist)) audio.tags.add(TALB(encoding=3, text=album)) audio.save() print(f"Metadata was successfully inserted into {file_path}") except Exception as e: print(f"An error occurred while processing {file_path}: {e}") def download_file(id, quality, url, title, artist, album, cache="./__pycache__"): if os.path.exists(cache): shutil.rmtree(cache) os.makedirs(cache) format = "mp3" if " MP3" in quality else "flac" local_filename = f"{cache}/{id}.{format}" response = requests.get(url, stream=True) if response.status_code == 200: with open(local_filename, "wb") as file: for chunk in response.iter_content(chunk_size=8192): file.write(chunk) insert_metadata(local_filename, title, artist, album) return local_filename else: print(f"Download Failure, status code: {response.status_code}") return url def extract_fst_url(text): url_pattern = r'(https?://[^\s"]+)' match = re.search(url_pattern, text) if match: return match.group(1) else: return None def get_real_url(short_url): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" } try: response = requests.get( short_url, headers=headers, allow_redirects=True, timeout=10, ) return response.url except requests.exceptions.RequestException as e: print(f"Error: {e}") return None def parse_id(url: str): if not url: return None if url.isdigit(): return int(url) url = extract_fst_url(url) if not url: return None if url.startswith("http://163cn.tv/"): url = get_real_url(url) match = re.search(r"id=(\d+)", url) if match: return int(match.group(1)) else: return None def infer(url: str, level: str): song_id = parse_id(url) if not song_id or not level: return ( None, "Please input valid url or id and select a sound quality level!", None, None, None, None, None, None, ) try: response = requests.get( os.getenv("api"), params={"id": song_id, "type": "json", "level": level}, ) if response.status_code == 200: data = response.json()["data"] return ( download_file( data["id"], data["format"], data["url"], data["name"], data["artist"], data["album"], ), data["name"], data["pic"], data["artist"], data["album"], data["format"], data["size"], data["lyric"], ) except Exception as e: return ( None, f"{e}", None, None, None, None, None, None, ) if __name__ == "__main__": gr.Interface( fn=infer, inputs=[ gr.Textbox( label="Please input music163 song ID or URL", placeholder="https://music.163.com/#/song?id=", ), gr.Dropdown( choices=[ "standard", "exhigh", "lossless", "hires", "sky", "jyeffect", "jymaster", ], value="lossless", label="Sound Quality", ), ], outputs=[ gr.Audio(label="Song", show_download_button=True), gr.Textbox(label="Title", show_copy_button=True), gr.Image(label="Cover", show_download_button=True), gr.Textbox(label="Artist", show_copy_button=True), gr.Textbox(label="Album", show_copy_button=True), gr.Textbox(label="Quality", show_copy_button=True), gr.Textbox(label="Size", show_copy_button=True), gr.TextArea(label="Lyrics", show_copy_button=True), ], title="Parse Music163 Songs without Loss", description="This site does not provide any audio and video storage services, but only to provide the most basic resolution services", flagging_mode="never", ).launch()