from pathlib import Path import streamlit as st from streamlit_player import st_player from streamlit_searchbox import st_searchbox from service.youtube import ( get_youtube_url, search_youtube, download_audio_from_youtube, ) from helpers import ( get_random_song, load_audio_segment, streamlit_player, local_audio, delete_old_files, ) from service.vocal_remover.runner import separate, load_model from footer import footer from header import header from loguru import logger as log out_path = Path("/tmp") in_path = Path("/tmp") sess = st.session_state def show_karaoke(pathname): cols = st.columns([1, 1, 3, 1]) with cols[1]: sess.delay = st.slider( label="Adjust video start delay in seconds (higher values anticipate lyrics)", key="delay_slider", value=2, min_value=0, max_value=5, help="Synchronize youtube player with karaoke audio by adding a delay to the youtube player.", ) with cols[2]: events = st_player( local_audio(pathname), **{ "progress_interval": 1000, "playing": False, "muted": False, "light": False, "play_inline": True, "playback_rate": 1, "height": 40, "config": { "start": 0, "forceAudio": True, }, "events": ["onProgress", "onPlay"], }, key="karaoke_player", ) st.markdown( "
⬆️ Click on the play button to start karaoke
", unsafe_allow_html=True, ) with st.columns([1, 4, 1])[1]: if events.name == "onPlay": st.session_state.player_restart = True log.info(f"Play Karaoke - {sess.selected_value}") elif events.name == "onProgress" and events.data["playedSeconds"] > 0: if st.session_state.player_restart: sess.tot_delay = sess.delay + events.data["playedSeconds"] st.session_state.player_restart = False st_player( sess.url + f"&t={sess.tot_delay}s", **{ "progress_interval": 1000, "playing": True, "muted": True, "light": False, "play_inline": False, "playback_rate": 1, "height": 250, "events": None, }, key="yt_muted_player", ) def body(): st.markdown( "

Play karaoke removing the vocals of your favorite song

", unsafe_allow_html=True, ) yt_cols = st.columns([1, 3, 2, 1]) with yt_cols[1]: selected_value = st_searchbox( search_youtube, label=None, placeholder="Search on YouTube by name...", clear_on_submit=True, key="yt_searchbox", ) if selected_value is not None and selected_value in sess.video_options: sess.random_song = None if selected_value != sess.selected_value: # New song selected sess.executed = False sess.selected_value = selected_value sess.url = get_youtube_url(selected_value) with yt_cols[2]: if st.button("🎲 Random song", use_container_width=True): sess.last_dir, sess.url = get_random_song() sess.selected_value = sess.last_dir sess.random_song = True sess.video_options = [] sess.executed = False if sess.url is not None: player_cols = st.columns([2, 2, 1, 1], gap="medium") with player_cols[1]: player = st.empty() streamlit_player( player, sess.url, height=200, is_active=False, muted=False, start=0, key="yt_player", events=["onProgress"], ) # Separate vocals cols_before_sep = st.columns([2, 4, 2]) with cols_before_sep[1]: execute_button = st.empty() execute = execute_button.button( "Confirm and remove vocals 🎤 🎶", type="primary", use_container_width=True, ) if execute or sess.executed: execute_button.empty() player.empty() if execute: sess.executed = False if sess.random_song is None: if not sess.executed: with st.spinner( "Separating vocals from music, it could take a few minutes... Don't close this page!" ): sess.filename = download_audio_from_youtube(sess.url, in_path) if sess.filename is None: st.stop() sess.url = None filename = sess.filename song = load_audio_segment(in_path / filename, filename.split(".")[-1]) song.export(in_path / filename, format=filename.split(".")[-1]) model, device = load_model(pretrained_model="baseline.pth") separate( input=in_path / filename, model=model, device=device, output_dir=out_path, only_no_vocals=True, ) selected_value = None sess.last_dir = ".".join(sess.filename.split(".")[:-1]) sess.executed = True else: sess.executed = True if sess.executed: show_karaoke(out_path / "vocal_remover" / sess.last_dir / "no_vocals.mp3") if __name__ == "__main__": header() body() footer() delete_old_files("/tmp", 60 * 30)