| import gradio as gr, glob, os, auditok, zipfile, requests, json, traceback, tempfile, random |
| from moviepy.editor import * |
| from pydub import AudioSegment |
|
|
| def split_wav_or_mp3_file(audiofileuploader, mindur2, maxdur2, name_for_split_files2, strict): |
| if audiofileuploader == None: |
| raise gr.Error("Audio file cannot be empty!") |
| if mindur2 == maxdur2: |
| raise gr.Error(f"Cannot split mindur={mindur2} and maxdur={maxdur2}, min and max are the same number.") |
| elif mindur2 > maxdur2: |
| raise gr.Error(f"Cannot split mindur={mindur2} and maxdur={maxdur2}, mindur is higher than maxdur.") |
| elif name_for_split_files2 == None: |
| raise gr.Error("Split files name cannot be empty!") |
| else: |
| audio_path = audiofileuploader |
| audio_regions = auditok.split( |
| audio_path, |
| min_dur=mindur2, |
| max_dur=maxdur2, |
| max_silence=0.3, |
| energy_threshold=45, |
| strict_min_dur=True if strict == True else False |
| ) |
| os.remove(audio_path) |
| for i, r in enumerate(audio_regions): |
| filename = r.save(f"{name_for_split_files2}-{i+1}.wav") |
| for f in sorted(glob.glob("*.wav")): |
| audio_files = glob.glob("*.wav") |
| zip_file_name2 = "audio_files.zip" |
| with zipfile.ZipFile(zip_file_name2, "w") as zip_file: |
| for audio_file in audio_files: |
| zip_file.write(audio_file, os.path.basename(audio_file)) |
| for file2 in glob.glob("*.wav"): |
| os.remove(file2) |
| return f"File split successfully!\nCheck below for zipped files.\nAmount created: {len(audio_files)}", zip_file_name2 |
|
|
| def mp4_to_wav_or_mp3(mp4fileuploader, file_format, random_filename): |
| if mp4fileuploader == None: |
| raise gr.Error("Input cannot be empty!") |
| else: |
| try: |
| if file_format == "wav": |
| videoinput = AudioFileClip(mp4fileuploader) |
| output_filename = "convertedaudio.wav" if not random_filename else f"convertedaudio_{random.randint(1000, 9999)}.wav" |
| videoinput.write_audiofile(output_filename) |
| videoinput.close() |
| elif file_format == "mp3": |
| videoinput = AudioFileClip(mp4fileuploader) |
| output_filename = "convertedaudio.mp3" if not random_filename else f"convertedaudio_{random.randint(1000, 9999)}.mp3" |
| videoinput.write_audiofile(output_filename) |
| videoinput.close() |
| os.remove(mp4fileuploader) |
| return "Converted mp4 file successfully!", output_filename |
| except: |
| raise gr.Error(traceback.format_exc()) |
| |
| def remove_audio_file_from_directory(): |
| for r in glob.glob("*.wav"): |
| os.remove(r) |
| for w in glob.glob("*.mp3"): |
| os.remove(w) |
| for y in glob.glob("convertedaudio.mp3"): |
| os.remove(y) |
| for a in glob.glob("convertedaudio.wav"): |
| os.remove(a) |
| return gr.Info("File removed.") |
|
|
| def mvsep_api_request(mvsep_key, audio_file, sep_dropdown): |
| if mvsep_key == "": |
| return gr.Warning("You must have an MVSEP API key for this to work!") |
| if audio_file == None: |
| return gr.Warning("Please select an audio file!") |
| if sep_dropdown == "-------------------------------------------------------------------------------------------------": |
| return gr.Warning("This option is not a model!") |
| url = "https://mvsep.com/api/separation/create" |
| files = { |
| "audiofile": open(audio_file, 'rb') |
| } |
| data = { |
| "api_token": mvsep_key, |
| "sep_type": sep_dropdown |
| } |
| r = requests.post(url, files=files, data=data) |
| json_format = r.json() |
| hash_val = json_format['data']['hash'] |
| return f"Request sent successfully! Your hash is: {hash_val}\n\nUse the 'Get Status' tab to check the status of your request." |
|
|
| def mvsep_check_request(hash_textbox): |
| try: |
| url = "https://mvsep.com/api/separation/get" |
| params = { |
| "hash": hash_textbox |
| } |
| r = requests.get(url, params=params) |
| rjson = r.json() |
| success = rjson['success'] |
| status = rjson['status'] |
| return f"Was successful? {str(success)}.\nStatus: {status}." |
| except requests.exceptions.JSONDecodeError: |
| return gr.Info("Status not available or request not sent.") |
|
|
| def mvsep_download_separated_audio(hash_textbox): |
| try: |
| url = "https://mvsep.com/api/separation/get" |
| params = { |
| "hash": hash_textbox |
| } |
| r = requests.get(url, params=params) |
| rjson = r.json() |
| status = rjson['status'] |
| files = rjson.get('data', {}).get('files', []) |
| urls = [file['url'] for file in files] |
| if status == "waiting" or status == "processing": |
| return gr.Info("Job not finished yet, so nothing to download for now.") |
| return json.dumps(urls, indent=4) |
| except requests.exceptions.JSONDecodeError: |
| return gr.Info("Nothing to download yet. Check back later.") |
|
|
| def split_by_dur(file_upload, dur_to_cut): |
| if file_upload == None: |
| raise gr.Error("Audio file cannot be empty!") |
| try: |
| audio = AudioSegment.from_file(file_upload) |
| trimmed_audio = audio[:dur_to_cut] |
| ms_to_min = round((dur_to_cut/(1000*60))%60, 1) |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file: |
| trimmed_audio.export(temp_file.name, format="mp3") |
| return f"Trimmed to {ms_to_min} minutes successfully.", temp_file.name |
| except Exception as e: |
| return gr.Error(traceback.format_exc()) |
|
|
| def zip_to_many(zip_upload): |
| temp_dir = "temp_audio_files" |
| os.makedirs(temp_dir, exist_ok=True) |
| with zipfile.ZipFile(zip_upload, 'r') as zip_ref: |
| zip_ref.extractall(temp_dir) |
| audio_files = [os.path.join(temp_dir, f) for f in os.listdir(temp_dir) if f.endswith(('.mp3', '.wav', '.ogg'))] |
| combined_audio = AudioSegment.empty() |
| for audio_file in audio_files: |
| audio = AudioSegment.from_file(audio_file) |
| combined_audio += audio |
| output_path = "combined_audio.mp3" |
| combined_audio.export(output_path, format="mp3") |
| for audio_file in audio_files: |
| os.remove(audio_file) |
| os.rmdir(temp_dir) |
| return "Done.", output_path |
|
|
| def bulk_split_zip_files(zip_upload, mindur2, maxdur2, name_for_split_files2, strict): |
| if zip_upload is None: |
| raise gr.Error("Zip file cannot be empty!") |
| if mindur2 == maxdur2: |
| raise gr.Error(f"Cannot split mindur={mindur2} and maxdur={maxdur2}, min and max are the same number.") |
| elif mindur2 > maxdur2: |
| raise gr.Error(f"Cannot split mindur={mindur2} and maxdur={maxdur2}, mindur is higher than maxdur.") |
| elif name_for_split_files2 is None or name_for_split_files2 == "": |
| raise gr.Error("Split files name cannot be empty!") |
|
|
| temp_dir = "bulk_zip_temp" |
| os.makedirs(temp_dir, exist_ok=True) |
|
|
| with zipfile.ZipFile(zip_upload, "r") as zip_ref: |
| zip_ref.extractall(temp_dir) |
|
|
| split_files = [] |
|
|
| for fname in os.listdir(temp_dir): |
| if not fname.lower().endswith((".wav", ".mp3")): |
| continue |
|
|
| audio_path = os.path.join(temp_dir, fname) |
| audio_regions = auditok.split( |
| audio_path, |
| min_dur=mindur2, |
| max_dur=maxdur2, |
| max_silence=0.3, |
| energy_threshold=45, |
| strict_min_dur=True if strict else False |
| ) |
|
|
| base = os.path.splitext(os.path.basename(audio_path))[0] |
| for i, r in enumerate(audio_regions): |
| out_name = f"{name_for_split_files2}-{base}-{i+1}.wav" |
| filename = r.save(out_name) |
| split_files.append(filename) |
|
|
| if not split_files: |
| for root, dirs, files in os.walk(temp_dir, topdown=False): |
| for f in files: |
| os.remove(os.path.join(root, f)) |
| for d in dirs: |
| os.rmdir(os.path.join(root, d)) |
| os.rmdir(temp_dir) |
| raise gr.Error("No audio segments were created from the provided ZIP.") |
|
|
| zip_file_name = "bulk_split_audio_files.zip" |
| with zipfile.ZipFile(zip_file_name, "w") as zip_file: |
| for fpath in split_files: |
| zip_file.write(fpath, os.path.basename(fpath)) |
|
|
| for fpath in split_files: |
| if os.path.exists(fpath): |
| os.remove(fpath) |
|
|
| for root, dirs, files in os.walk(temp_dir, topdown=False): |
| for f in files: |
| os.remove(os.path.join(root, f)) |
| for d in dirs: |
| os.rmdir(os.path.join(root, d)) |
| os.rmdir(temp_dir) |
|
|
| os.remove(zip_upload) |
|
|
| return f"File split successfully from ZIP! Amount created: {len(split_files)}", zip_file_name |
|
|
| with gr.Blocks(theme='ParityError/Interstellar', title="Global Dataset Maker") as app: |
| gr.HTML( |
| "<h1> Welcome to the Cafeteria (formally GDMGS)!</h1>" |
| ) |
| gr.HTML( |
| "<h2> Currently, no yt functions are working right now, so they have been deleted. Please use this tool to split an audio file, convert an mp4 file to mp3 or wav, or use mvsep." |
| ) |
| gr.Markdown("## Duplicate this space if you want to make your own changes!") |
| gr.HTML( |
| """<p style="margin:5px auto;display: flex;justify-content: left;"> |
| <a href="https://huggingface.co/spaces/Kryptone/GDMGS?duplicate=true"><img src="https://huggingface.co/datasets/huggingface/badges/resolve/main/duplicate-this-space-md-dark.svg" alt="Duplicate this Space"></a> |
| </p>""" |
| ) |
| gr.Markdown( |
| "This Space will create a dataset for you and use MVSEP to isolate vocals, all automatically. **Please be warned that due to not having a GPU on this Space, some steps might take longer to complete.**" |
| ) |
| gr.HTML( |
| "<h2> This Space's storage is ephemeral, meaning all audio files are visible to you only. I do not have access to any of this, nor would I do anything with it anyway. </h2>" |
| ) |
| with gr.Tabs(): |
| with gr.TabItem("Misc tools"): |
| with gr.Tab("File splitter"): |
| gr.Markdown("If you would rather split a single WAV or mp3 audio file, use this method instead.") |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| audiofileuploader = gr.File(file_count='single', file_types=[".wav", ".mp3"], label="WAV or mp3 file") |
| mindur2 = gr.Number(label="Min duration", minimum=1, maximum=10, value=1) |
| maxdur2 = gr.Number(label="Max duration", minimum=1, maximum=10, value=5) |
| name_for_split_files2 = gr.Textbox(label="Name for split files") |
| strict = gr.Checkbox(False, label="Enable strict duration?", info="Use this option if you want to minimize the '(audio_file) is less than 0.76 seconds' warning on Colab. Keep in mind that this only applies for min duration, max is ignored.") |
| audiofileuploadbtn = gr.Button("Split", variant='primary') |
| audiofileuploadbtn.click( |
| split_wav_or_mp3_file, |
| [audiofileuploader, mindur2, maxdur2, name_for_split_files2, strict], |
| [gr.Text(label="Output"), gr.File(label="Zipped files")] |
| ) |
| with gr.Tab("Bulk file splitter from ZIP"): |
| gr.Markdown("Upload a ZIP containing multiple audio files, and each of them will be split.") |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| zip_file_bulk = gr.File(file_count='single', file_types=[".zip"], label="Zip file") |
| mindur_bulk = gr.Number(label="Min duration", minimum=1, maximum=10, value=1) |
| maxdur_bulk = gr.Number(label="Max duration", minimum=1, maximum=10, value=5) |
| name_for_split_audio_files_bulk = gr.Textbox(label="Name prefix for split files") |
| strict_bulk = gr.Checkbox(False, label="Enable strict?", info="Same behavior for single file uploading") |
| bulk_split_btn = gr.Button("Bulk split", variant='primary') |
| bulk_split_btn.click( |
| bulk_split_zip_files, |
| [zip_file_bulk, mindur_bulk, maxdur_bulk, name_for_split_audio_files_bulk, strict_bulk], |
| [gr.Text(label="Output"), gr.File(label="Zipped split files")] |
| ) |
|
|
| with gr.Tab("Split audio file by duration"): |
| gr.Markdown("If you have an audio file thats too long for MVSEP (or any other use cases), use this section to split the audio by duration.") |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| file_upload = gr.File(file_count='single', file_types=[".wav", ".mp3"], label="WAV or MP3 file") |
| dur_to_cut = gr.Number(label="Duration to split audio (in ms). Cannot be larger than the duration of the audio file.", precision=0) |
| begin = gr.Button("Split at given duration", variant='primary') |
| begin.click( |
| split_by_dur, |
| [file_upload, dur_to_cut], |
| [gr.Text(label="Output"), gr.File(label="Trimmed audio")] |
| ) |
| with gr.Tab("MP4 to mp3/wav converter"): |
| gr.Markdown("If you have an mp4 file, you can convert it to mp3 or wav here. Only click the 'Remove file' button when done.") |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| mp4fileuploader = gr.File(file_count='single', file_types=[".mp4"], label="mp4 file") |
| file_format = gr.Radio(["wav", "mp3"], value="mp3", label="Convert mp4 file to:") |
| random_filename = gr.Checkbox(False, label="Use random filename?") |
| convert_btn = gr.Button("Convert", variant='primary') |
| remove_file_btn = gr.Button("Remove file from directory", variant='secondary') |
| convert_btn.click( |
| mp4_to_wav_or_mp3, |
| [mp4fileuploader, file_format, random_filename], |
| [gr.Text(label="Output"), gr.File(label="Converted audio file")] |
| ) |
| remove_file_btn.click( |
| remove_audio_file_from_directory, |
| None, |
| None |
| ) |
| with gr.Tab("MVSEP"): |
| gr.Markdown("Use MVSEP to isolate audio.\n\n**You will be required to input your API key, but it will not be saved ever, I don't use anything saved here for bad intentions, nor would I have access to it regardless.**") |
| with gr.Tab("Send Request via audio file"): |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| mvsep_key = gr.Textbox(placeholder="Enter your MVSEP API key.", label="API key") |
| audio_file = gr.File(file_count='single', file_types=[".mp3"], label="Audio file") |
| sep_dropdown = gr.Dropdown( |
| ["0 - spleeter (vocals, music)", |
| "1 - spleeter (vocals, drums, bass, other)", |
| "2 - spleeter (vocals, drums, bass, piano, other)", |
| "3 - unmix XL (vocals, drums, bass, other)", |
| "4 - unmix HQ (vocals, drums, bass, other)", |
| "5 - unmix SD (vocals, drums, bass, other)", |
| "6 - unmix SE (vocals, music)", |
| "7 - MDX A (vocals, drums, bass, other)", |
| "8 - MDX B (vocals, drums, bass, other)", |
| "9 - UVR HQ (vocals, music)", |
| "10 - Demucs3 Model A (vocals, drums, bass, other)", |
| "11 - Demucs3 Model B (vocals, drums, bass, other)", |
| "12 - MDX-B Karaoke (lead/back vocals)", |
| "13 - Demucs2 (vocals, drums, bass, other)", |
| "14 - Zero Shot (Query Based) (LQ)", |
| "15 - Danna sep (vocals, drums, bass, other)", |
| "16 - Byte Dance (vocals, drums, bass, other)", |
| "17 - UVRv5 Demucs (vocals, music)", |
| "18 - MVSep DNR (music, sfx, speech)", |
| "19 - MVSep Vocal Model (vocals, music)", |
| "20 - Demucs4 HT (vocals, drums, bass, other)", |
| "--------------------------------------------------------------------------------------------------", |
| "22 - FoxJoy Reverb Removal (other)", |
| "23 - MDX B (vocals, instrumental)", |
| "24 - MVSep Demucs4HT DNR (dialog, sfx, music)", |
| "25 - MDX23C (vocals, instrumental)", |
| "26 - Ensemble (vocals, instrumental) [PREMIUM ONLY]", |
| "27 - Demucs4 Vocals 2023 (vocals, instrumental)", |
| "28 - Ensemble (vocals, instrumental, bass, drums, other) [PREMIUM ONLY]", |
| "29 - MVSep Piano (piano, other)", |
| "30 - Ensemble All-In (vocals, bass, drums, piano, guitar, lead/back vocals, other) [PREMIUM ONLY]", |
| "31 - MVSep Guitar (guitar, other)", |
| "-------------------------------------------------------------------------------------------------", |
| "33 - Vit Large 23 (vocals, instrum)", |
| "34 - MVSep Crowd removal (crowd, other)", |
| "35 - MVSep MelBand Roformer (vocals, instrum)", |
| "36 - BandIt Plus (speech, music, effects)", |
| "37 - DrumSep (kick, snare, cymbals, toms)", |
| "38 - LarsNet (kick, snare, cymbals, toms, hihat)", |
| "39 - Whisper (extract text from audio)", |
| "40 - BS Roformer (vocals, instrumental)", |
| "41 - MVSep Bass (bass, other)", |
| "42 - MVSep MultiSpeaker (MDX23C)", |
| "43 - MVSEP Multichannel BS (vocals, inst)", |
| "44 - MVSep Drums (drums, other)", |
| "45 - Bandit v2 (speech, music, effects)", |
| "46 - SCNet (vocals, instrumental)", |
| "47 - DeNoise by aufr33", |
| "48 - Melband Roformer (vocals, intrumental)", |
| "49 - MelBand Karaoke by viperx and aufr33 (lead/back vocals)", |
| "50 - Aspiration (by Sucial)", |
| "51 - Apollo Enhancers (by JusperLee and Lew)", |
| "52 - MVSep Strings (strings, other)", |
| "53 - Medley Vox (multi-singer separation)", |
| "54 - MVSep Wind (wind, other)", |
| "55 - Phantom Centre extraction (by wesleyr36)", |
| "56 - MVSep DnR v3 (speech, music, sfx)", |
| "57 - MVSep Male/Female separation", |
| "58 - MVSep Organ (organ, other)", |
| "59 - AudioSR (Super Resolution)", |
| "60 - FlashSR (Super Resolution)", |
| "61 - MVSep Saxophone (saxophone, other)", |
| "62 - Stable Audio Open Gen", |
| "63 - BS Roformer SW (vocals, bass, drums, guitar, piano, other)", |
| "64 - Parakeet (extract text from audio)", |
| "65 - MVSep Violin (violin, other)", |
| "66 - MVSep Acoustic Guitar (acoustic-guitar, other)", |
| "67 - MVSep Flute (flute, other)" |
| ], |
| max_choices=1, |
| value="63 - BS Roformer SW (vocals, bass, drums, guitar, piano, other)", |
| label="Model type:", |
| interactive=True, |
| type='index' |
| ) |
| send_req = gr.Button("Send request", variant='primary') |
| send_req.click( |
| mvsep_api_request, |
| [mvsep_key, audio_file, sep_dropdown], |
| [gr.Text(label="Output")] |
| ) |
| with gr.Tab("Get status of request"): |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| hash_textbox = gr.Textbox(label="Hash") |
| check_status = gr.Button("Check status", variant='primary') |
| download = gr.Button("Download separated audio", variant='secondary') |
| check_status.click( |
| mvsep_check_request, |
| [hash_textbox], |
| [gr.Text(label="Status")] |
| ) |
| download.click( |
| mvsep_download_separated_audio, |
| [hash_textbox], |
| [gr.Text(label="Link(s)")] |
| ) |
| with gr.Tab("Convert many audio files to one file"): |
| gr.Markdown("Upload a ZIP full of many audio files and this will attempt to convert it to one long audio file. **Will not work if there are folders inside the zip.**") |
| with gr.Row(): |
| with gr.Column(): |
| with gr.Row(): |
| zip_upload = gr.File(file_count='single', file_types=[".zip"], label="Zip file") |
| combine_btn = gr.Button("Combine", variant='primary') |
| combine_btn.click( |
| zip_to_many, |
| [zip_upload], |
| [gr.Text(label="Status"), gr.File(label="Combined file")] |
| ) |
|
|
| with gr.TabItem("Changelog"): |
| gr.Markdown("v1.5 - Added new tool - Bulk split audio files from a zip.") |
| gr.Markdown("v1.4 - Added more MVSep and changed default model.") |
| gr.Markdown("v1.3 - Added more MVSep models.") |
| gr.Markdown("v1.2 - Added an option (in mp4 to mp3/wav converter) to have the output file be a random filename.") |
| |
| app.launch() |