File size: 6,324 Bytes
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72ad181
b1fdcc2
 
 
 
 
faebcc3
b1fdcc2
 
 
 
 
 
 
 
2c9d596
b1fdcc2
 
 
3ecd555
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c9d596
 
faebcc3
2c9d596
faebcc3
2c9d596
 
 
b1fdcc2
2c9d596
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5472963
 
 
 
b1fdcc2
 
 
 
 
5472963
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
faebcc3
b1fdcc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444aecb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b1fdcc2
 
 
 
2c9d596
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
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(
        "<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":
            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(
        "<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])
    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)