File size: 7,796 Bytes
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72ad181
b1fdcc2
 
 
 
 
faebcc3
b1fdcc2
 
 
 
 
 
 
 
2c9d596
dc66c98
b1fdcc2
 
 
3ecd555
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c9d596
dc66c98
faebcc3
2c9d596
dc66c98
 
 
 
 
 
2c9d596
dc66c98
b1fdcc2
2c9d596
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
dc66c98
 
 
 
 
 
b1fdcc2
5472963
 
 
 
b1fdcc2
dc66c98
b1fdcc2
dc66c98
 
 
5472963
dc66c98
 
b1fdcc2
dc66c98
 
 
 
 
 
 
 
 
 
 
 
 
b1fdcc2
dc66c98
 
 
b1fdcc2
dc66c98
 
b1fdcc2
dc66c98
 
b1fdcc2
dc66c98
 
 
 
 
 
 
 
 
 
 
b1fdcc2
 
dc66c98
 
 
 
 
 
 
 
 
 
 
b1fdcc2
 
 
 
 
 
 
 
 
 
 
dc66c98
b1fdcc2
 
 
 
 
 
444aecb
 
 
 
 
 
 
 
 
 
dc66c98
 
 
 
 
444aecb
 
 
 
 
 
 
 
 
 
dc66c98
b1fdcc2
 
 
dc66c98
 
b1fdcc2
 
 
 
 
 
72ad181
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from pathlib import Path

import streamlit as st
from streamlit_player import st_player

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):
    st.session_state.karaoke = True
    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(
        "<center>⬆️ Click on the play button to start karaoke<center>",
        unsafe_allow_html=True,
    )
    with st.columns([1, 4, 1])[1]:
        if events.name == "onPlay":
            sess.player_restart = True
            log.info(f"Play Karaoke - {sess.selected_value}")

        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"]
                sess.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 reset_karaoke():
    sess.karaoke = False
    sess.url = None
    sess.executed = False


def body():
    st.markdown(
        "<h4><center>Play karaoke removing the vocals of your favorite song <center></h4>",
        unsafe_allow_html=True,
    )
    yt_cols = st.columns([1, 3, 2, 1])
    selected_value = None
    with yt_cols[1]:
        input_search = st.text_input(
            label="Search a song on YouTube",
            label_visibility="collapsed",
            placeholder="Search on YouTube by name...",
            key="yt_input_search",
            on_change=reset_karaoke,
        )
        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 not sess.get("karaoke", False):
            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)

    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]:
            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])
            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:
                radio_selection.empty()
                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()
                            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,
                                device=device,
                                output_dir=out_path,
                                only_no_vocals=True,
                            )
                            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 __name__ == "__main__":
    header()
    body()
    footer()
    delete_old_files("/tmp", 60 * 30)