| import sys |
|
|
| sys.path.append("..") |
| import os |
| import shutil |
|
|
| now_dir = os.getcwd() |
| import soundfile as sf |
| import librosa |
| from lib.tools import audioEffects |
| from assets.i18n.i18n import I18nAuto |
|
|
| i18n = I18nAuto() |
| import gradio as gr |
| import tabs.resources as resources |
| import numpy as np |
| from scipy.signal import resample |
|
|
| def save_to_wav2(dropbox): |
| file_path = dropbox.name |
| target_path = os.path.join("assets","audios", os.path.basename(file_path)) |
|
|
| if os.path.exists(target_path): |
| os.remove(target_path) |
| print("Replacing old dropdown file...") |
|
|
| shutil.move(file_path, target_path) |
| return target_path |
|
|
|
|
| audio_root = "assets/audios" |
| audio_others_root = "assets/audios/audio-others" |
| sup_audioext = { |
| "wav", |
| "mp3", |
| "flac", |
| "ogg", |
| "opus", |
| "m4a", |
| "mp4", |
| "aac", |
| "alac", |
| "wma", |
| "aiff", |
| "webm", |
| "ac3", |
| } |
| audio_paths = [ |
| os.path.join(root, name) |
| for root, _, files in os.walk(audio_root, topdown=False) |
| for name in files |
| if name.endswith(tuple(sup_audioext)) and root == audio_root |
| ] |
|
|
| audio_others_paths = [ |
| os.path.join(root, name) |
| for root, _, files in os.walk(audio_others_root, topdown=False) |
| for name in files |
| if name.endswith(tuple(sup_audioext)) and root == audio_others_root |
| ] |
|
|
|
|
| def change_choices3(): |
| audio_paths = [ |
| os.path.join(root, name) |
| for root, _, files in os.walk(audio_root, topdown=False) |
| for name in files |
| if name.endswith(tuple(sup_audioext)) and root == audio_root |
| ] |
| audio_others_paths = [ |
| os.path.join(root, name) |
| for root, _, files in os.walk(audio_others_root, topdown=False) |
| for name in files |
| if name.endswith(tuple(sup_audioext)) and root == audio_others_root |
| ] |
|
|
| return ( |
| {"choices": sorted(audio_others_paths), "__type__": "update"}, |
| {"choices": sorted(audio_paths), "__type__": "update"}, |
| ) |
|
|
|
|
| def generate_output_path(output_folder, base_name, extension): |
| index = 1 |
| while True: |
| output_path = os.path.join(output_folder, f"{base_name}_{index}.{extension}") |
| if not os.path.exists(output_path): |
| return output_path |
| index += 1 |
|
|
| from pydub import AudioSegment |
| from pydub.silence import detect_nonsilent |
| import glob |
| import re |
| def combine_and_save_audios( |
| audio1_path, audio2_path, output_path, volume_factor_audio1, volume_factor_audio2 |
| ): |
| audio1 = AudioSegment.from_file(audio1_path) |
| audio2 = AudioSegment.from_file(audio2_path) |
| |
| |
| if len(audio1) > len(audio2): |
| |
| diff_duration_seconds = (len(audio1) - len(audio2)) / 1000.0 |
| print(f"diff_duration_seconds: {diff_duration_seconds} seconds") |
| |
| silence = AudioSegment.silent(duration=int(diff_duration_seconds)) |
|
|
| |
| audio2 = audio2 + silence |
| else: |
| |
| diff_duration_seconds = (len(audio2) - len(audio1)) / 1000.0 |
| print(f"diff_duration_seconds: {diff_duration_seconds} seconds") |
| |
| silence = AudioSegment.silent(duration=int(diff_duration_seconds)) |
|
|
| |
| audio1 = audio1 + silence |
|
|
| |
| if volume_factor_audio1 != 1.0: |
| audio1 *= volume_factor_audio1 |
| if volume_factor_audio2 != 1.0: |
| audio2 *= volume_factor_audio2 |
|
|
| |
| combined_audio = audio1.overlay(audio2) |
|
|
| |
| combined_audio.export(output_path, format="wav") |
|
|
|
|
| def audio_combined( |
| audio1_path, |
| audio2_path, |
| volume_factor_audio1=1.0, |
| volume_factor_audio2=1.0, |
| reverb_enabled=False, |
| compressor_enabled=False, |
| noise_gate_enabled=False, |
| ): |
| output_folder = os.path.join(now_dir,"assets", "audios", "audio-outputs") |
| os.makedirs(output_folder, exist_ok=True) |
|
|
| |
| base_name = "combined_audio" |
| extension = "wav" |
| output_path = generate_output_path(output_folder, base_name, extension) |
| print(reverb_enabled) |
| print(compressor_enabled) |
| print(noise_gate_enabled) |
|
|
| if reverb_enabled or compressor_enabled or noise_gate_enabled: |
| |
| base_name = "effect_audio" |
| output_path = generate_output_path(output_folder, base_name, extension) |
| processed_audio_path = audioEffects.process_audio( |
| audio2_path, |
| output_path, |
| reverb_enabled, |
| compressor_enabled, |
| noise_gate_enabled, |
| ) |
| base_name = "combined_audio" |
| output_path = generate_output_path(output_folder, base_name, extension) |
| |
| combine_and_save_audios( |
| audio1_path, |
| processed_audio_path, |
| output_path, |
| volume_factor_audio1, |
| volume_factor_audio2, |
| ) |
|
|
| return i18n("Conversion complete!"), output_path |
| else: |
| base_name = "combined_audio" |
| output_path = generate_output_path(output_folder, base_name, extension) |
| |
| combine_and_save_audios( |
| audio1_path, |
| audio2_path, |
| output_path, |
| volume_factor_audio1, |
| volume_factor_audio2, |
| ) |
|
|
| return i18n("Conversion complete!"), output_path |
|
|
| def process_audio(file_path): |
| try: |
| |
| song = AudioSegment.from_file(file_path) |
|
|
| print(f"Ignore the warning if you saw any...") |
|
|
| |
| silence_thresh = -70 |
| min_silence_len = 750 |
|
|
| |
| nonsilent_parts = detect_nonsilent(song, min_silence_len=min_silence_len, silence_thresh=silence_thresh) |
|
|
| |
| file_dir = os.path.dirname(file_path) |
| file_name = os.path.basename(file_path).split('.')[0] |
| new_dir_path = os.path.join(file_dir, file_name) |
| os.makedirs(new_dir_path, exist_ok=True) |
|
|
| |
| timestamps_file = os.path.join(file_dir, f"{file_name}_timestamps.txt") |
| if os.path.isfile(timestamps_file): |
| os.remove(timestamps_file) |
|
|
| |
| segment_count = 0 |
| for i, (start_i, end_i) in enumerate(nonsilent_parts): |
| chunk = song[start_i:end_i] |
| chunk_file_path = os.path.join(new_dir_path, f"chunk{i}.wav") |
| chunk.export(chunk_file_path, format="wav") |
|
|
| print(f"Segment {i} created!") |
| segment_count += 1 |
| |
| |
| with open(timestamps_file, "a", encoding="utf-8") as f: |
| f.write(f"{chunk_file_path} starts at {start_i} ms\n") |
| |
| print(f"Total segments created: {segment_count}") |
| print(f"Split all chunks for {file_path} successfully!") |
|
|
| return "Finish", new_dir_path |
|
|
| except Exception as e: |
| print(f"An error occurred: {e}") |
| return "Error", None |
|
|
|
|
| def merge_audio(timestamps_file): |
| try: |
| |
| prefix = os.path.basename(timestamps_file).replace('_timestamps.txt', '') |
| timestamps_dir = os.path.dirname(timestamps_file) |
| print(timestamps_dir) |
| print(prefix) |
|
|
| |
| with open(timestamps_file, "r", encoding="utf-8") as f: |
| lines = f.readlines() |
|
|
| |
| audio_segments = [] |
| last_end_time = 0 |
|
|
| print(f"Processing file: {timestamps_file}") |
|
|
| for line in lines: |
| |
| match = re.search(r"(chunk\d+.wav) starts at (\d+) ms", line) |
| if match: |
| filename, start_time = match.groups() |
| start_time = int(start_time) |
|
|
| |
| chunk_file = os.path.join(timestamps_dir, prefix, filename) |
|
|
| |
| silence_duration = max(start_time - last_end_time, 0) |
| silence = AudioSegment.silent(duration=silence_duration) |
| audio_segments.append(silence) |
|
|
| |
| audio = AudioSegment.from_wav(chunk_file) |
| audio_segments.append(audio) |
|
|
| |
| last_end_time = start_time + len(audio) |
|
|
| print(f"Processed chunk: {chunk_file}") |
|
|
| |
| merged_filename = f"{prefix}_merged.wav" |
| merged_audio = sum(audio_segments) |
| merged_audio.export(os.path.join(timestamps_dir, "audio-outputs", merged_filename), format="wav") |
|
|
| print(f"Exported merged file: {merged_filename}\n") |
|
|
| except Exception as e: |
| print(f"An error occurred: {e}") |
|
|
|
|
|
|
|
|
| def merge_audios(): |
| gr.Markdown( |
| value="## " + i18n("Merge your generated audios with the instrumental") |
| ) |
| with gr.Row(): |
| with gr.Column(): |
| dropbox = gr.File(label=i18n("Drag your audio here:")) |
| gr.Markdown(value=i18n("### Instrumental settings:")) |
| input_audio1 = gr.Dropdown( |
| label=i18n("Choose your instrumental:"), |
| choices=sorted(audio_others_paths), |
| value="", |
| interactive=True, |
| ) |
| input_audio1_scale = gr.Slider( |
| minimum=0, |
| maximum=10, |
| label=i18n("Volume of the instrumental audio:"), |
| value=1.00, |
| interactive=True, |
| ) |
| gr.Markdown(value=i18n("### Audio settings:")) |
| input_audio3 = gr.Dropdown( |
| label=i18n("Select the generated audio"), |
| choices=sorted(audio_paths), |
| value="", |
| interactive=True, |
| ) |
| with gr.Row(): |
| input_audio3_scale = gr.Slider( |
| minimum=0, |
| maximum=10, |
| label=i18n("Volume of the generated audio:"), |
| value=1.00, |
| interactive=True, |
| ) |
|
|
| gr.Markdown(value=i18n("### Add the effects:")) |
| reverb_ = gr.Checkbox( |
| label=i18n("Reverb"), |
| value=False, |
| interactive=True, |
| ) |
| compressor_ = gr.Checkbox( |
| label=i18n("Compressor"), |
| value=False, |
| interactive=True, |
| ) |
| noise_gate_ = gr.Checkbox( |
| label=i18n("Noise Gate"), |
| value=False, |
| interactive=True, |
| ) |
| with gr.Row(): |
| butnone = gr.Button(i18n("Merge"), variant="primary").style( |
| full_width=True |
| ) |
| refresh_button = gr.Button( |
| i18n("Refresh"), variant="primary" |
| ).style(full_width=True) |
|
|
| vc_output1 = gr.Textbox(label=i18n("Output information:")) |
| vc_output2 = gr.Audio( |
| label=i18n( |
| "Export audio (click on the three dots in the lower right corner to download)" |
| ), |
| type="filepath", |
| ) |
|
|
| dropbox.upload( |
| fn=save_to_wav2, inputs=[dropbox], outputs=[input_audio1] |
| ) |
|
|
| refresh_button.click( |
| fn=lambda: change_choices3(), |
| inputs=[], |
| outputs=[input_audio1, input_audio3], |
| ) |
|
|
| butnone.click( |
| fn=audio_combined, |
| inputs=[ |
| input_audio1, |
| input_audio3, |
| input_audio1_scale, |
| input_audio3_scale, |
| reverb_, |
| compressor_, |
| noise_gate_, |
| ], |
| outputs=[vc_output1, vc_output2], |
| ) |
|
|