Spaces:
Build error
Build error
""" | |
This module contains the code for the "One-click generation" tab. | |
""" | |
from typings.extra import RunPipelineHarnessArgs | |
from functools import partial | |
import gradio as gr | |
from backend.generate_song_cover import run_pipeline | |
from frontend.common import ( | |
PROGRESS_BAR, | |
EventArgs, | |
exception_harness, | |
setup_consecutive_event_listeners_with_toggled_interactivity, | |
show_hop_slider, | |
toggle_visible_component, | |
update_cached_input_songs, | |
update_output_audio, | |
update_song_cover_name, | |
update_value, | |
) | |
def _run_pipeline_harness(*args: *RunPipelineHarnessArgs) -> tuple[str | None, ...]: | |
""" | |
Run the song cover generation pipeline in a harness | |
which displays a progress bar, re-raises exceptions as Gradio errors, | |
and returns the output of the pipeline. | |
If the pipeline outputs only a single path, | |
then that output is extended with a None value for each intermediate audio file. | |
Parameters | |
---------- | |
*args : *RunPipelineHarnessArgs | |
Arguments to forward to the pipeline. | |
Returns | |
------- | |
tuple[str | None, ...] | |
The output of the pipeline, potentially extended with None values. | |
""" | |
res = exception_harness(run_pipeline)(*args, progress_bar=PROGRESS_BAR) | |
if isinstance(res, tuple): | |
return res | |
else: | |
return (None,) * 11 + (res,) | |
def _toggle_intermediate_files_accordion( | |
visible: bool, | |
) -> list[gr.Accordion | gr.Audio]: | |
""" | |
Toggle the visibility of intermediate audio file accordions | |
and their associated audio components. | |
Parameters | |
---------- | |
visible : bool | |
Visibility status of the accordions and audio components. | |
Returns | |
------- | |
list[gr.Accordion | gr.Audio] | |
The accordions and audio components with updated visibility. | |
""" | |
audio_components = [gr.Audio(value=None) for _ in range(11)] | |
accordions = [gr.Accordion(open=False) for _ in range(7)] | |
return [gr.Accordion(visible=visible, open=False)] + accordions + audio_components | |
def render( | |
generate_buttons: list[gr.Button], | |
song_dir_dropdowns: list[gr.Dropdown], | |
cached_input_songs_dropdown_1click: gr.Dropdown, | |
cached_input_songs_dropdown_multi: gr.Dropdown, | |
rvc_model: gr.Dropdown, | |
intermediate_audio_to_delete: gr.Dropdown, | |
output_audio_to_delete: gr.Dropdown, | |
) -> None: | |
""" | |
Render "One-click generation" tab. | |
Parameters | |
---------- | |
generate_buttons : list[gr.Button] | |
Buttons used for audio generation in the | |
"One-click generation" tab and the "Multi-step generation" tab. | |
song_dir_dropdowns : list[gr.Dropdown] | |
Dropdowns for selecting song directories in the | |
"Multi-step generation" tab. | |
cached_input_songs_dropdown_1click : gr.Dropdown | |
Dropdown for selecting cached input songs in the | |
"One-click generation" tab | |
cached_input_songs_dropdown_multi : gr.Dropdown | |
Dropdown for selecting cached input songs in the | |
"Multi-step generation" tab | |
rvc_model : gr.Dropdown | |
Dropdown for selecting RVC model in the | |
"One-click generation" tab. | |
intermediate_audio_to_delete : gr.Dropdown | |
Dropdown for selecting intermediate audio files to delete in the | |
"Manage audio" tab. | |
output_audio_to_delete : gr.Dropdown | |
Dropdown for selecting output audio files to delete in the | |
"Manage audio" tab. | |
""" | |
with gr.Tab("One-click generation"): | |
( | |
_, | |
_, | |
_, | |
_, | |
_, | |
_, | |
_, | |
_, | |
generate_btn, | |
) = generate_buttons | |
with gr.Accordion("Main options"): | |
with gr.Row(): | |
with gr.Column(): | |
song_input_type_dropdown = gr.Dropdown( | |
["YouTube link/local path", "Local file", "Cached song"], | |
value="YouTube link/local path", | |
label="Song input type", | |
type="index", | |
) | |
song_input = gr.Textbox( | |
label="Song input", | |
info=( | |
"Link to a song on YouTube or the full path of a local" | |
" audio file." | |
), | |
) | |
local_file = gr.Audio( | |
label="Song input", type="filepath", visible=False | |
) | |
cached_input_songs_dropdown_1click.render() | |
song_input_type_dropdown.input( | |
partial(toggle_visible_component, 3), | |
inputs=song_input_type_dropdown, | |
outputs=[ | |
song_input, | |
local_file, | |
cached_input_songs_dropdown_1click, | |
], | |
show_progress="hidden", | |
) | |
local_file.change( | |
update_value, | |
inputs=local_file, | |
outputs=song_input, | |
show_progress="hidden", | |
) | |
cached_input_songs_dropdown_1click.input( | |
update_value, | |
inputs=cached_input_songs_dropdown_1click, | |
outputs=song_input, | |
show_progress="hidden", | |
) | |
with gr.Column(): | |
rvc_model.render() | |
with gr.Column(): | |
pitch_change_vocals = gr.Slider( | |
-3, | |
3, | |
value=0, | |
step=1, | |
label="Pitch shift of vocals", | |
info=( | |
"Shift pitch of converted vocals. Measured in octaves." | |
" Generally, use 1 for male-to-female conversions and -1" | |
" for vice-versa." | |
), | |
) | |
pitch_change_all = gr.Slider( | |
-12, | |
12, | |
value=0, | |
step=1, | |
label="Overall pitch shift", | |
info=( | |
"Shift pitch of converted vocals, backup vocals and" | |
" instrumentals. Measured in semi-tones. Altering this" | |
" slightly reduces sound quality." | |
), | |
) | |
with gr.Accordion("Vocal conversion options", open=False): | |
with gr.Row(): | |
index_rate = gr.Slider( | |
0, | |
1, | |
value=0.5, | |
label="Index rate", | |
info=( | |
"Controls how much of the accent in the voice model to keep in" | |
" the converted vocals" | |
), | |
) | |
filter_radius = gr.Slider( | |
0, | |
7, | |
value=3, | |
step=1, | |
label="Filter radius", | |
info=( | |
"If >=3: apply median filtering to the harvested pitch results." | |
" Can reduce breathiness" | |
), | |
) | |
rms_mix_rate = gr.Slider( | |
0, | |
1, | |
value=0.25, | |
label="RMS mix rate", | |
info=( | |
"Control how much to mimic the loudness (0) of the input vocals" | |
" or a fixed loudness (1)" | |
), | |
) | |
protect = gr.Slider( | |
0, | |
0.5, | |
value=0.33, | |
label="Protect rate", | |
info=( | |
"Protect voiceless consonants and breath sounds. Set to 0.5 to" | |
" disable." | |
), | |
) | |
with gr.Column(): | |
f0_method = gr.Dropdown( | |
["rmvpe", "mangio-crepe"], | |
value="rmvpe", | |
label="Pitch detection algorithm", | |
info=( | |
"Best option is rmvpe (clarity in vocals), then" | |
" mangio-crepe (smoother vocals)" | |
), | |
) | |
crepe_hop_length = gr.Slider( | |
32, | |
320, | |
value=128, | |
step=1, | |
visible=False, | |
label="Crepe hop length", | |
info=( | |
"Lower values leads to longer conversions and higher risk" | |
" of voice cracks, but better pitch accuracy." | |
), | |
) | |
f0_method.change( | |
show_hop_slider, | |
inputs=f0_method, | |
outputs=crepe_hop_length, | |
show_progress="hidden", | |
) | |
with gr.Accordion("Audio mixing options", open=False): | |
gr.Markdown("") | |
gr.Markdown("### Reverb control on converted vocals") | |
with gr.Row(): | |
reverb_rm_size = gr.Slider( | |
0, | |
1, | |
value=0.15, | |
label="Room size", | |
info="The larger the room, the longer the reverb time", | |
) | |
reverb_wet = gr.Slider( | |
0, | |
1, | |
value=0.2, | |
label="Wetness level", | |
info="Loudness level of converted vocals with reverb", | |
) | |
reverb_dry = gr.Slider( | |
0, | |
1, | |
value=0.8, | |
label="Dryness level", | |
info="Loudness level of converted vocals without reverb", | |
) | |
reverb_damping = gr.Slider( | |
0, | |
1, | |
value=0.7, | |
label="Damping level", | |
info="Absorption of high frequencies in the reverb", | |
) | |
gr.Markdown("") | |
gr.Markdown("### Volume controls (dB)") | |
with gr.Row(): | |
main_gain = gr.Slider(-20, 20, value=0, step=1, label="Main vocals") | |
inst_gain = gr.Slider(-20, 20, value=0, step=1, label="Instrumentals") | |
backup_gain = gr.Slider(-20, 20, value=0, step=1, label="Backup vocals") | |
with gr.Accordion("Audio output options", open=False): | |
with gr.Row(): | |
output_name = gr.Textbox( | |
label="Output file name", | |
info=( | |
"If no name is provided, a suitable name will be generated" | |
" automatically." | |
), | |
placeholder="Ultimate RVC song cover", | |
) | |
output_sr = gr.Dropdown( | |
choices=[16000, 44100, 48000, 96000, 192000], | |
value=44100, | |
label="Output sample rate", | |
) | |
output_format = gr.Dropdown( | |
["mp3", "wav", "flac", "aac", "m4a", "ogg"], | |
value="mp3", | |
label="Output file format", | |
) | |
with gr.Row(): | |
show_intermediate_files = gr.Checkbox( | |
label="Show intermediate audio files", | |
value=False, | |
info=( | |
"Show generated intermediate audio files when song cover" | |
" generation completes. Leave unchecked to optimize" | |
" performance." | |
), | |
) | |
rvc_model.change( | |
partial(update_song_cover_name, None, update_placeholder=True), | |
inputs=[cached_input_songs_dropdown_1click, rvc_model], | |
outputs=output_name, | |
show_progress="hidden", | |
) | |
cached_input_songs_dropdown_1click.change( | |
partial(update_song_cover_name, None, update_placeholder=True), | |
inputs=[cached_input_songs_dropdown_1click, rvc_model], | |
outputs=output_name, | |
show_progress="hidden", | |
) | |
intermediate_audio_accordions = [ | |
gr.Accordion(label, open=False, render=False) | |
for label in [ | |
"Step 0: song retrieval", | |
"Step 1: vocals/instrumentals separation", | |
"Step 2: main vocals/ backup vocals separation", | |
"Step 3: main vocals cleanup", | |
"Step 4: conversion of main vocals", | |
"Step 5: post-processing of converted vocals", | |
"Step 6: pitch shift of background tracks", | |
] | |
] | |
( | |
song_retrieval_accordion, | |
vocals_separation_accordion, | |
main_vocals_separation_accordion, | |
vocal_cleanup_accordion, | |
vocal_conversion_accordion, | |
vocals_postprocessing_accordion, | |
pitch_shift_accordion, | |
) = intermediate_audio_accordions | |
( | |
original_track, | |
vocals_track, | |
instrumentals_track, | |
main_vocals_track, | |
backup_vocals_track, | |
main_vocals_dereverbed_track, | |
main_vocals_reverb_track, | |
converted_vocals_track, | |
postprocessed_vocals_track, | |
instrumentals_shifted_track, | |
backup_vocals_shifted_track, | |
) = [ | |
gr.Audio(label=label, type="filepath", interactive=False, render=False) | |
for label in [ | |
"Input song", | |
"Vocals", | |
"Instrumentals", | |
"Main vocals", | |
"Backup vocals", | |
"De-reverbed main vocals", | |
"Main vocals reverb", | |
"Converted vocals", | |
"Post-processed vocals", | |
"Pitch-shifted instrumentals", | |
"Pitch-shifted backup vocals", | |
] | |
] | |
with gr.Accordion( | |
"Access intermediate audio files", open=False, visible=False | |
) as intermediate_files_accordion: | |
song_retrieval_accordion.render() | |
with song_retrieval_accordion: | |
original_track.render() | |
vocals_separation_accordion.render() | |
with vocals_separation_accordion: | |
with gr.Row(): | |
vocals_track.render() | |
instrumentals_track.render() | |
main_vocals_separation_accordion.render() | |
with main_vocals_separation_accordion: | |
with gr.Row(): | |
main_vocals_track.render() | |
backup_vocals_track.render() | |
vocal_cleanup_accordion.render() | |
with vocal_cleanup_accordion: | |
with gr.Row(): | |
main_vocals_dereverbed_track.render() | |
main_vocals_reverb_track.render() | |
vocal_conversion_accordion.render() | |
with vocal_conversion_accordion: | |
converted_vocals_track.render() | |
vocals_postprocessing_accordion.render() | |
with vocals_postprocessing_accordion: | |
postprocessed_vocals_track.render() | |
pitch_shift_accordion.render() | |
with pitch_shift_accordion: | |
with gr.Row(): | |
instrumentals_shifted_track.render() | |
backup_vocals_shifted_track.render() | |
with gr.Row(): | |
clear_btn = gr.Button(value="Reset settings", scale=2) | |
generate_btn.render() | |
song_cover_track = gr.Audio(label="Song cover", scale=3) | |
show_intermediate_files.change( | |
_toggle_intermediate_files_accordion, | |
inputs=show_intermediate_files, | |
outputs=[ | |
intermediate_files_accordion, | |
song_retrieval_accordion, | |
vocals_separation_accordion, | |
main_vocals_separation_accordion, | |
vocal_cleanup_accordion, | |
vocal_conversion_accordion, | |
vocals_postprocessing_accordion, | |
pitch_shift_accordion, | |
original_track, | |
vocals_track, | |
instrumentals_track, | |
main_vocals_track, | |
backup_vocals_track, | |
main_vocals_dereverbed_track, | |
main_vocals_reverb_track, | |
converted_vocals_track, | |
postprocessed_vocals_track, | |
instrumentals_shifted_track, | |
backup_vocals_shifted_track, | |
], | |
show_progress="hidden", | |
) | |
generate_event_args_list = [ | |
EventArgs( | |
_run_pipeline_harness, | |
inputs=[ | |
song_input, | |
rvc_model, | |
pitch_change_vocals, | |
pitch_change_all, | |
index_rate, | |
filter_radius, | |
rms_mix_rate, | |
protect, | |
f0_method, | |
crepe_hop_length, | |
reverb_rm_size, | |
reverb_wet, | |
reverb_dry, | |
reverb_damping, | |
main_gain, | |
inst_gain, | |
backup_gain, | |
output_sr, | |
output_format, | |
output_name, | |
show_intermediate_files, | |
], | |
outputs=[ | |
original_track, | |
vocals_track, | |
instrumentals_track, | |
main_vocals_track, | |
backup_vocals_track, | |
main_vocals_dereverbed_track, | |
main_vocals_reverb_track, | |
converted_vocals_track, | |
postprocessed_vocals_track, | |
instrumentals_shifted_track, | |
backup_vocals_shifted_track, | |
song_cover_track, | |
], | |
), | |
EventArgs( | |
partial( | |
update_cached_input_songs, 3 + len(song_dir_dropdowns), [], [1] | |
), | |
outputs=[ | |
cached_input_songs_dropdown_1click, | |
intermediate_audio_to_delete, | |
cached_input_songs_dropdown_multi, | |
] | |
+ song_dir_dropdowns, | |
name="then", | |
show_progress="hidden", | |
), | |
EventArgs( | |
partial(update_output_audio, 1, [], [0]), | |
outputs=[output_audio_to_delete], | |
name="then", | |
show_progress="hidden", | |
), | |
] | |
setup_consecutive_event_listeners_with_toggled_interactivity( | |
generate_btn, | |
generate_event_args_list, | |
generate_buttons + [show_intermediate_files], | |
) | |
clear_btn.click( | |
lambda: [ | |
0, | |
0, | |
0.5, | |
3, | |
0.25, | |
0.33, | |
"rmvpe", | |
128, | |
0.15, | |
0.2, | |
0.8, | |
0.7, | |
0, | |
0, | |
0, | |
44100, | |
"mp3", | |
False, | |
], | |
outputs=[ | |
pitch_change_vocals, | |
pitch_change_all, | |
index_rate, | |
filter_radius, | |
rms_mix_rate, | |
protect, | |
f0_method, | |
crepe_hop_length, | |
reverb_rm_size, | |
reverb_wet, | |
reverb_dry, | |
reverb_damping, | |
main_gain, | |
inst_gain, | |
backup_gain, | |
output_sr, | |
output_format, | |
show_intermediate_files, | |
], | |
show_progress="hidden", | |
) | |