-
Notifications
You must be signed in to change notification settings - Fork 1
/
run.py
137 lines (91 loc) · 3.79 KB
/
run.py
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
import os
import sys
import argparse
import subprocess
import pandas as pd
import operator
import numpy as np
from instr_timeline import *
from visualization import viz
from spleeter.separator import Separator
THIS_PATH = os.path.abspath(os.getcwd())
def youtube_download(artist, song, ext='mp3'):
"""
Downloads first result of search 'artist - song' from youtube. Requires youtube-dl to be installed
"""
outdir = os.path.join(THIS_PATH, 'data')
filename = artist + '_' + song
audio_file = os.path.join(outdir, filename + '.' + ext)
if not os.path.exists(audio_file):
search = 'ytsearch1:{} {}'.format( artist.replace('_',' '), song.replace('_',' ') )
cmd = [ 'youtube-dl', '--extract-audio', '--audio-format', ext, '-o', os.path.join(outdir, filename) + '.' + '%(ext)s', search]
subprocess.call(cmd)
return audio_file
def run_spleeter(audio_file, model='spleeter:5stems'):
print('\nPerforming source separation using', model)
destination = os.path.splitext(audio_file)[0]
if not os.path.exists(destination):
separator = Separator(model)
separator.separate_to_file(audio_descriptor=audio_file, destination=destination)
return destination
def process(audio_file):
print('\nProcessing', audio_file)
# spleeter separation
destination = run_spleeter(audio_file)
destination = os.path.join(destination, os.path.splitext(os.path.split(destination)[-1])[0])
instruments = os.listdir(destination)
instruments = [i for i in instruments if '.wav' in i]
duration = {}
for instr in instruments:
instr = os.path.splitext(instr)[0]
print('\n', instr, '\n')
input_file = os.path.join(THIS_PATH, destination, instr + '.wav')
dest_file = os.path.join(THIS_PATH, destination, instr + '.txt')
cmd = [ 'auditok', input_file]
output = subprocess.check_output(cmd, encoding='UTF-8')
output = output.split('\n')
output = [i.split(' ') for i in output]
start = []
end = []
for i in output:
if len(i) == 3:
start.append(float(i[1]))
end.append(float(i[2]))
df = pd.DataFrame()
df['start'] = start
df['end'] = end
df['duration'] = df['end'] - df['start']
print(df.head())
print('-------------------')
df.to_csv(dest_file, sep='\t', index=False)
duration[instr] = df['duration'].sum()
duration = dict(sorted(duration.items(),key=operator.itemgetter(1),reverse=True))
print('\nInstruments and their durations:\n')
for k, v in duration.items():
print(k, np.round(v, 2))
print('\nInstruments Timeline:\n')
timeline = instruments_timeline(datadir=destination)
print(timeline)
# live visualization
path = os.path.splitext( os.path.split(audio_file)[-1] )[0]
viz(path=path)
return
def main():
parser = argparse.ArgumentParser(description='Instruments activity detection.')
parser.add_argument('-a', '--audio_file', nargs='?',
help='path to audio file to process')
parser.add_argument('artist', nargs='?',
help='artist name')
parser.add_argument('song', nargs='?',
help='song title')
args = vars(parser.parse_args())
if args['audio_file'] is None:
if args['artist'] and args['song']:
print('Downloading audio from youtube..')
audio_file = youtube_download(args['artist'], args['song'], ext='mp3')
args['audio_file'] = audio_file
else:
raise Exception("Provide either an audio file or artist and song title")
process(audio_file=args['audio_file'])
if __name__ == '__main__':
main()