File size: 3,278 Bytes
af8e0fa
 
f05c3e4
af8e0fa
 
 
 
d14d2b9
 
af8e0fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d14d2b9
a07d0b1
 
 
 
 
 
d14d2b9
a07d0b1
af8e0fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d14d2b9
 
a07d0b1
 
af8e0fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a07d0b1
 
 
 
af8e0fa
 
 
 
 
 
a07d0b1
af8e0fa
 
 
 
 
 
d14d2b9
af8e0fa
 
 
 
 
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
import gradio as gr
import os
import tarfile
import allin1

from pathlib import Path

from dissector import generate_dissector_data

HEADER = """
<header style="text-align: center;">
  <h1>
    All-In-One Music Structure Analyzer 🔮
  </h1>
  <p>
    <a href="https://github.com/mir-aidj/all-in-one">[Python Package]</a>
    <a href="https://arxiv.org/abs/2307.16425">[Paper]</a>
    <a href="https://taejun.kim/music-dissector/">[Visual Demo]</a>
  </p>
</header>
<main
  style="display: flex; justify-content: center;"
>
  <div
    style="display: inline-block;"
  >
    <p>
      This Space demonstrates the music structure analyzer predicts:
      <ul
        style="padding-left: 1rem;"
      >
        <li>BPM</li>
        <li>Beats</li>
        <li>Downbeats</li>
        <li>Functional segment boundaries</li>
        <li>Functional segment labels (e.g. intro, verse, chorus, bridge, outro)</li>
      </ul>
    </p>
    <p>
      It takes about 4:30 to analyze a 3-minute song.
      If you are in a hurry, you can <strong><u>try the examples at the bottom</u></strong>.
    </p>
    <p>
      For more information, please visit the links above ✨🧸
    </p>
  </div>
</main>
"""

CACHE_EXAMPLES = os.getenv('CACHE_EXAMPLES', '1') == '1'

def compress_files(folder_path, dissector_file):
    """Compresses files in the specified folder into a .tar.gz"""
    tar_path = folder_path + ".tar.gz"
    with tarfile.open(tar_path, "w:gz") as tar:
        for root, _, files in os.walk(folder_path):
            for file in files:
                tar.add(os.path.join(root, file), arcname=file)
        tar.add(dissector_file)
    return tar_path

def analyze(path):
  path = Path(path)
  result = allin1.analyze(
    path,
    multiprocess=False,
    keep_byproducts=True,  # TODO: remove this
  )

  fig = allin1.visualize(result)
  fig.set_dpi(300)

  allin1.sonify(result, out_dir='./sonif')
  sonif_path = Path(f'./sonif/{path.stem}.sonif{path.suffix}').resolve().as_posix()

  dissector_file = generate_dissector_data(path.stem, result)  
  compressed_file = compress_files(f"demix/htdemucs/{path.stem}", dissector_file)

  return result.bpm, fig, sonif_path, compressed_file


with gr.Blocks() as demo:
  gr.HTML(HEADER)

  input_audio_path = gr.Audio(
    label='Input',
    source='upload',
    type='filepath',
    format='mp3',
    show_download_button=False,
  )
  button = gr.Button('Analyze', variant='primary')
  output_viz = gr.Plot(label='Visualization')
  with gr.Row():
    output_bpm = gr.Textbox(label='BPM', scale=1)
    output_sonif = gr.Audio(
      label='Sonification',
      type='filepath',
      format='mp3',
      show_download_button=False,
      scale=9,
    )
    output_compressed = gr.File(
        label="Compressed Files",
        type="file",
    )
  gr.Examples(
    examples=[
      './assets/NewJeans - Super Shy.mp3',
      './assets/Bruno Mars - 24k Magic.mp3'
    ],
    inputs=input_audio_path,
    outputs=[output_bpm, output_viz, output_sonif, output_compressed],
    fn=analyze,
    cache_examples=CACHE_EXAMPLES,
  )
  button.click(
    fn=analyze,
    inputs=input_audio_path,
    outputs=[output_bpm, output_viz, output_sonif, output_compressed],
    api_name='analyze',
  )

if __name__ == '__main__':
  demo.launch()