diff --git a/app/pages/Karaoke.py b/app/pages/Karaoke.py
index fb3df0c..2afc614 100644
--- a/app/pages/Karaoke.py
+++ b/app/pages/Karaoke.py
@@ -2,7 +2,6 @@
import streamlit as st
from streamlit_player import st_player
-from streamlit_searchbox import st_searchbox
from service.youtube import (
get_youtube_url,
@@ -30,6 +29,7 @@
def show_karaoke(pathname):
+ st.session_state.karaoke = True
cols = st.columns([1, 1, 3, 1])
with cols[1]:
sess.delay = st.slider(
@@ -65,13 +65,17 @@ def show_karaoke(pathname):
)
with st.columns([1, 4, 1])[1]:
if events.name == "onPlay":
- st.session_state.player_restart = True
+ sess.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:
+ elif (
+ events.name == "onProgress"
+ and events.data["playedSeconds"] > 0
+ and events.data["played"] < 1
+ ):
+ if sess.player_restart:
sess.tot_delay = sess.delay + events.data["playedSeconds"]
- st.session_state.player_restart = False
+ sess.player_restart = False
st_player(
sess.url + f"&t={sess.tot_delay}s",
**{
@@ -88,51 +92,75 @@ def show_karaoke(pathname):
)
+def reset_karaoke():
+ sess.karaoke = False
+ sess.url = None
+ sess.executed = False
+
+
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])
+ selected_value = None
with yt_cols[1]:
- selected_value = st_searchbox(
- search_youtube,
- label=None,
+ input_search = st.text_input(
+ label="Search a song on YouTube",
+ label_visibility="collapsed",
placeholder="Search on YouTube by name...",
- clear_on_submit=True,
- key="yt_searchbox",
+ key="yt_input_search",
+ on_change=reset_karaoke,
)
- if selected_value is not None and selected_value in sess.video_options:
- sess.random_song = None
+ if not sess.get("karaoke", False):
+ radio_selection = st.empty()
+ if input_search != "" and input_search != sess.get("input_search", ""):
+ sess.input_search = input_search
+ with st.spinner("Searching on YouTube..."):
+ sess.options = search_youtube(input_search)
+ if sess.get("options", []) != []:
+ selected_value = radio_selection.selectbox(
+ label="**⬇️ Select a title and see the video preview**",
+ index=len(sess.options),
+ options=sess.options + [""],
+ key="yt_radio",
+ )
- if selected_value != sess.selected_value: # New song selected
- sess.executed = False
+ if not sess.get("karaoke", False):
+ if selected_value is not None and selected_value in sess.video_options:
+ sess.random_song = None
- sess.selected_value = selected_value
- sess.url = get_youtube_url(selected_value)
+ if selected_value != sess.selected_value: # New song selected
+ sess.executed = False
- 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
+ sess.selected_value = selected_value
+ sess.url = get_youtube_url(selected_value)
- if sess.url is not None:
+ if selected_value is None or 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
+ radio_selection.empty()
+
+ if sess.url is not None and not sess.get("karaoke", False):
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"],
- )
+ with st.spinner("Loading video preview..."):
+ player = st.empty()
+ streamlit_player(
+ player,
+ sess.url,
+ height=200,
+ is_active=False,
+ muted=False,
+ start=0,
+ key="yt_player",
+ )
# Separate vocals
cols_before_sep = st.columns([2, 4, 2])
@@ -144,6 +172,7 @@ def body():
use_container_width=True,
)
if execute or sess.executed:
+ radio_selection.empty()
execute_button.empty()
player.empty()
if execute:
@@ -156,11 +185,15 @@ def body():
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")
+ cancel_button = st.empty()
+ if cancel_button.button(
+ "Cancel", use_container_width=True, type="secondary"
+ ):
+ st.experimental_rerun()
separate(
input=in_path / filename,
model=model,
@@ -171,11 +204,12 @@ def body():
selected_value = None
sess.last_dir = ".".join(sess.filename.split(".")[:-1])
sess.executed = True
+ cancel_button.empty()
else:
sess.executed = True
- if sess.executed:
- show_karaoke(out_path / "vocal_remover" / sess.last_dir / "no_vocals.mp3")
+ if sess.executed:
+ show_karaoke(out_path / "vocal_remover" / sess.last_dir / "no_vocals.mp3")
if __name__ == "__main__":
diff --git a/app/service/youtube.py b/app/service/youtube.py
index 193ff8c..9ff2ebf 100644
--- a/app/service/youtube.py
+++ b/app/service/youtube.py
@@ -2,7 +2,6 @@
import os
import re
import string
-import time
from typing import List
import streamlit as st
@@ -51,18 +50,17 @@ def download_audio_from_youtube(url, output_path):
return f"{video_title}.mp3"
-@st.cache_data(show_spinner=False)
+@st.cache_data(show_spinner=False, max_entries=10)
def query_youtube(query: str) -> Search:
return Search(query)
-def search_youtube(query: str) -> List:
+def search_youtube(query: str, limit=5) -> List:
if len(query) > 3:
- time.sleep(0.5)
search = query_youtube(query + " lyrics")
st.session_state.search_results = search.results
if "search_results" in st.session_state and st.session_state.search_results is not None:
- video_options = [video.title for video in st.session_state.search_results]
+ video_options = [video.title for video in st.session_state.search_results[:limit]]
else:
video_options = []
else:
diff --git a/requirements.in b/requirements.in
index 9b8d34f..dcdcb43 100644
--- a/requirements.in
+++ b/requirements.in
@@ -4,7 +4,6 @@ pandas==1.5.3
pydub==0.25.1
pytube==12.1.3
streamlit-player==0.1.5
-streamlit-searchbox==0.1.2
yt-dlp==2023.7.6
matplotlib==3.7.1
librosa==0.10.0.post2
diff --git a/requirements.txt b/requirements.txt
index 5f51351..8ab3a78 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
-# pip-compile --output-file=requirements.txt --resolver=backtracking requirements.in
+# pip-compile --output-file=requirements.txt requirements.in
#
altair==4.2.2
# via streamlit
@@ -30,7 +30,7 @@ cffi==1.15.1
# via soundfile
charset-normalizer==3.2.0
# via requests
-click==8.1.4
+click==8.1.5
# via streamlit
cloudpickle==2.2.1
# via submitit
@@ -56,7 +56,7 @@ entrypoints==0.4
# via altair
filelock==3.12.2
# via torch
-fonttools==4.40.0
+fonttools==4.41.0
# via matplotlib
gitdb==4.0.10
# via gitpython
@@ -77,7 +77,7 @@ joblib==1.3.1
# via
# librosa
# scikit-learn
-jsonschema==4.18.0
+jsonschema==4.18.3
# via altair
jsonschema-specifications==2023.6.1
# via jsonschema
@@ -227,20 +227,17 @@ streamlit==1.22.0
# stqdm
# streamlit-option-menu
# streamlit-player
- # streamlit-searchbox
streamlit-option-menu==0.3.6
# via -r requirements.in
streamlit-player==0.1.5
# via -r requirements.in
-streamlit-searchbox==0.1.2
- # via -r requirements.in
submitit==1.4.5
# via dora-search
sympy==1.12
# via torch
tenacity==8.2.2
# via streamlit
-threadpoolctl==3.1.0
+threadpoolctl==3.2.0
# via scikit-learn
toml==0.10.2
# via streamlit
@@ -283,5 +280,5 @@ websockets==11.0.3
# via yt-dlp
yt-dlp==2023.7.6
# via -r requirements.in
-zipp==3.16.0
+zipp==3.16.2
# via importlib-metadata