mirror of
https://github.com/correl/dejavu.git
synced 2024-11-23 11:09:52 +00:00
Merging in new test suite with modifications, mp3 example files to test on, and shell files for automation
This commit is contained in:
parent
7cbb894501
commit
a779ca4cf9
12 changed files with 522 additions and 414 deletions
41
README.md
41
README.md
|
@ -122,6 +122,47 @@ Or by reading files via scripting functions:
|
||||||
>>> song = djv.recognize(FileRecognizer, "va_us_top_40/wav/07 - Mirrors - Justin Timberlake.wav")
|
>>> song = djv.recognize(FileRecognizer, "va_us_top_40/wav/07 - Mirrors - Justin Timberlake.wav")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing (New!)
|
||||||
|
|
||||||
|
Test your Dejavu settings on a corpus of audio files on a number of different metrics:
|
||||||
|
|
||||||
|
* Confidence of match (number fingerprints aligned)
|
||||||
|
* Offset matching accuracy
|
||||||
|
* Song matching accuracy
|
||||||
|
* Time to match
|
||||||
|
|
||||||
|
An example script is given in `test_dejavu.sh`, shown below:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#####################################
|
||||||
|
### Dejavu example testing script ###
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Clear out previous results
|
||||||
|
rm -rf ./results ./temp_audio
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Fingerprint files of extension mp3 in the ./mp3 folder
|
||||||
|
python dejavu.py fingerprint ./mp3/ mp3
|
||||||
|
|
||||||
|
##########
|
||||||
|
# Run a test suite on the ./mp3 folder by extracting 1, 2, 3, 4, and 5
|
||||||
|
# second clips sampled randomly from within each song 8 seconds
|
||||||
|
# away from start or end, sampling offset with random seed = 42, and finally,
|
||||||
|
# store results in ./results and log to ./results/dejavu-test.log
|
||||||
|
python run_tests.py \
|
||||||
|
--secs 5 \
|
||||||
|
--temp ./temp_audio \
|
||||||
|
--log-file ./results/dejavu-test.log \
|
||||||
|
--padding 8 \
|
||||||
|
--seed 42 \
|
||||||
|
--results ./results \
|
||||||
|
./mp3
|
||||||
|
```
|
||||||
|
|
||||||
|
The testing scripts are as of now are a bit rough, and could certainly use some love and attention if you're interested in submitting a PR!
|
||||||
|
|
||||||
## How does it work?
|
## How does it work?
|
||||||
|
|
||||||
The algorithm works off a fingerprint based system, much like:
|
The algorithm works off a fingerprint based system, much like:
|
||||||
|
|
270
dejavu/testing.py
Normal file
270
dejavu/testing.py
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
from __future__ import division
|
||||||
|
from pydub import AudioSegment
|
||||||
|
from dejavu.decoder import path_to_songname
|
||||||
|
from dejavu import Dejavu
|
||||||
|
from dejavu.fingerprint import *
|
||||||
|
import traceback
|
||||||
|
import fnmatch
|
||||||
|
import os, re, ast
|
||||||
|
import subprocess
|
||||||
|
import random
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def set_seed(seed=None):
|
||||||
|
"""
|
||||||
|
`seed` as None means that the sampling will be random.
|
||||||
|
|
||||||
|
Setting your own seed means that you can produce the
|
||||||
|
same experiment over and over.
|
||||||
|
"""
|
||||||
|
if seed != None:
|
||||||
|
random.seed(seed)
|
||||||
|
|
||||||
|
def get_files_recursive(src, fmt):
|
||||||
|
"""
|
||||||
|
`src` is the source directory.
|
||||||
|
`fmt` is the extension, ie ".mp3" or "mp3", etc.
|
||||||
|
"""
|
||||||
|
for root, dirnames, filenames in os.walk(src):
|
||||||
|
for filename in fnmatch.filter(filenames, '*' + fmt):
|
||||||
|
yield os.path.join(root, filename)
|
||||||
|
|
||||||
|
def get_length_audio(audiopath, extension):
|
||||||
|
"""
|
||||||
|
Returns length of audio in seconds.
|
||||||
|
Returns None if format isn't supported or in case of error.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
audio = AudioSegment.from_file(audiopath, extension.replace(".", ""))
|
||||||
|
except:
|
||||||
|
print "Error in get_length_audio(): %s" % traceback.format_exc()
|
||||||
|
return None
|
||||||
|
return int(len(audio) / 1000.0)
|
||||||
|
|
||||||
|
def get_starttime(length, nseconds, padding):
|
||||||
|
"""
|
||||||
|
`length` is total audio length in seconds
|
||||||
|
`nseconds` is amount of time to sample in seconds
|
||||||
|
`padding` is off-limits seconds at beginning and ending
|
||||||
|
"""
|
||||||
|
maximum = length - padding - nseconds
|
||||||
|
if padding > maximum:
|
||||||
|
return 0
|
||||||
|
return random.randint(padding, maximum)
|
||||||
|
|
||||||
|
def generate_test_files(src, dest, nseconds, fmts=[".mp3", ".wav"], padding=10):
|
||||||
|
"""
|
||||||
|
Generates a test file for each file recursively in `src` directory
|
||||||
|
of given format using `nseconds` sampled from the audio file.
|
||||||
|
|
||||||
|
Results are written to `dest` directory.
|
||||||
|
|
||||||
|
`padding` is the number of off-limit seconds and the beginning and
|
||||||
|
end of a track that won't be sampled in testing. Often you want to
|
||||||
|
avoid silence, etc.
|
||||||
|
"""
|
||||||
|
# create directories if necessary
|
||||||
|
for directory in [src, dest]:
|
||||||
|
try:
|
||||||
|
os.stat(directory)
|
||||||
|
except:
|
||||||
|
os.mkdir(directory)
|
||||||
|
|
||||||
|
# find files recursively of a given file format
|
||||||
|
for fmt in fmts:
|
||||||
|
testsources = get_files_recursive(src, fmt)
|
||||||
|
for audiosource in testsources:
|
||||||
|
|
||||||
|
print "audiosource:", audiosource
|
||||||
|
|
||||||
|
filename, extension = os.path.splitext(os.path.basename(audiosource))
|
||||||
|
length = get_length_audio(audiosource, extension)
|
||||||
|
starttime = get_starttime(length, nseconds, padding)
|
||||||
|
|
||||||
|
test_file_name = "%s_%s_%ssec.%s" % (
|
||||||
|
os.path.join(dest, filename), starttime,
|
||||||
|
nseconds, extension.replace(".", ""))
|
||||||
|
|
||||||
|
subprocess.check_output([
|
||||||
|
"ffmpeg", "-y",
|
||||||
|
"-ss", "%d" % starttime,
|
||||||
|
'-t' , "%d" % nseconds,
|
||||||
|
"-i", audiosource,
|
||||||
|
test_file_name])
|
||||||
|
|
||||||
|
def log_msg(msg, log=True, silent=False):
|
||||||
|
if log:
|
||||||
|
logging.debug(msg)
|
||||||
|
if not silent:
|
||||||
|
print msg
|
||||||
|
|
||||||
|
def autolabel(rects, ax):
|
||||||
|
# attach some text labels
|
||||||
|
for rect in rects:
|
||||||
|
height = rect.get_height()
|
||||||
|
ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height,
|
||||||
|
'%d' % int(height), ha='center', va='bottom')
|
||||||
|
|
||||||
|
def autolabeldoubles(rects, ax):
|
||||||
|
# attach some text labels
|
||||||
|
for rect in rects:
|
||||||
|
height = rect.get_height()
|
||||||
|
ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height,
|
||||||
|
'%s' % round(float(height), 3), ha='center', va='bottom')
|
||||||
|
|
||||||
|
class DejavuTest(object):
|
||||||
|
def __init__(self, folder, seconds):
|
||||||
|
super(DejavuTest, self).__init__()
|
||||||
|
|
||||||
|
self.test_folder = folder
|
||||||
|
self.test_seconds = seconds
|
||||||
|
self.test_songs = []
|
||||||
|
|
||||||
|
print "test_seconds", self.test_seconds
|
||||||
|
|
||||||
|
self.test_files = [
|
||||||
|
f for f in os.listdir(self.test_folder)
|
||||||
|
if os.path.isfile(os.path.join(self.test_folder, f))
|
||||||
|
and re.findall("[0-9]*sec", f)[0] in self.test_seconds]
|
||||||
|
|
||||||
|
print "test_files", self.test_files
|
||||||
|
|
||||||
|
self.n_columns = len(self.test_seconds)
|
||||||
|
self.n_lines = int(len(self.test_files) / self.n_columns)
|
||||||
|
|
||||||
|
print "columns:", self.n_columns
|
||||||
|
print "length of test files:", len(self.test_files)
|
||||||
|
print "lines:", self.n_lines
|
||||||
|
|
||||||
|
# variable match results (yes, no, invalid)
|
||||||
|
self.result_match = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
||||||
|
|
||||||
|
print "result_match matrix:", self.result_match
|
||||||
|
|
||||||
|
# variable match precision (if matched in the corrected time)
|
||||||
|
self.result_matching_times = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
||||||
|
|
||||||
|
# variable mahing time (query time)
|
||||||
|
self.result_query_duration = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
||||||
|
|
||||||
|
# variable confidence
|
||||||
|
self.result_match_confidence = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
||||||
|
|
||||||
|
self.begin()
|
||||||
|
|
||||||
|
def get_column_id (self, secs):
|
||||||
|
for i, sec in enumerate(self.test_seconds):
|
||||||
|
if secs == sec:
|
||||||
|
return i
|
||||||
|
|
||||||
|
def get_line_id (self, song):
|
||||||
|
for i, s in enumerate(self.test_songs):
|
||||||
|
if song == s:
|
||||||
|
return i
|
||||||
|
self.test_songs.append(song)
|
||||||
|
return len(self.test_songs) - 1
|
||||||
|
|
||||||
|
def create_plots(self, name, results, results_folder):
|
||||||
|
for sec in range(0, len(self.test_seconds)):
|
||||||
|
ind = np.arange(self.n_lines) #
|
||||||
|
width = 0.25 # the width of the bars
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_xlim([-1 * width, 2 * width])
|
||||||
|
|
||||||
|
means_dvj = [x[0] for x in results[sec]]
|
||||||
|
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
||||||
|
|
||||||
|
# add some
|
||||||
|
ax.set_ylabel(name)
|
||||||
|
ax.set_title("%s %s Results" % (self.test_seconds[sec], name))
|
||||||
|
ax.set_xticks(ind + width)
|
||||||
|
|
||||||
|
labels = [0 for x in range(0, self.n_lines)]
|
||||||
|
for x in range(0, self.n_lines):
|
||||||
|
labels[x] = "song %s" % (x+1)
|
||||||
|
ax.set_xticklabels(labels)
|
||||||
|
|
||||||
|
box = ax.get_position()
|
||||||
|
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
||||||
|
|
||||||
|
#ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
||||||
|
|
||||||
|
if name == 'Confidence':
|
||||||
|
autolabel(rects1, ax)
|
||||||
|
else:
|
||||||
|
autolabeldoubles(rects1, ax)
|
||||||
|
|
||||||
|
plt.grid()
|
||||||
|
|
||||||
|
fig_name = os.path.join(results_folder, "%s_%s.png" % (name, self.test_seconds[sec]))
|
||||||
|
fig.savefig(fig_name)
|
||||||
|
|
||||||
|
def begin(self):
|
||||||
|
for f in self.test_files:
|
||||||
|
log_msg('--------------------------------------------------')
|
||||||
|
log_msg('file: %s' % f)
|
||||||
|
|
||||||
|
# get column
|
||||||
|
col = self.get_column_id(re.findall("[0-9]*sec",f)[0])
|
||||||
|
song = path_to_songname(f).split("_")[0] # format: XXXX_offset_length.mp3
|
||||||
|
line = self.get_line_id (song)
|
||||||
|
result = subprocess.check_output(["python", "dejavu.py", 'recognize', 'file', self.test_folder + "/" + f])
|
||||||
|
|
||||||
|
if result.strip() == "None":
|
||||||
|
log_msg('No match')
|
||||||
|
self.result_match[line][col] = 'no'
|
||||||
|
self.result_matching_times[line][col] = 0
|
||||||
|
self.result_query_duration[line][col] = 0
|
||||||
|
self.result_match_confidence[line][col] = 0
|
||||||
|
|
||||||
|
else:
|
||||||
|
result = result.strip()
|
||||||
|
result = result.replace(" \'", ' "')
|
||||||
|
result = result.replace("{\'", '{"')
|
||||||
|
result = result.replace("\':", '":')
|
||||||
|
result = result.replace("\',", '",')
|
||||||
|
|
||||||
|
# which song did we predict?
|
||||||
|
result = ast.literal_eval(result)
|
||||||
|
song_result = result["song_name"]
|
||||||
|
log_msg('song: %s' % song)
|
||||||
|
log_msg('song_result: %s' % song_result)
|
||||||
|
|
||||||
|
if song_result != song:
|
||||||
|
log_msg('invalid match')
|
||||||
|
self.result_match[line][col] = 'invalid'
|
||||||
|
self.result_matching_times[line][col] = 0
|
||||||
|
self.result_query_duration[line][col] = 0
|
||||||
|
self.result_match_confidence[line][col] = 0
|
||||||
|
else:
|
||||||
|
log_msg('correct match')
|
||||||
|
print self.result_match
|
||||||
|
self.result_match[line][col] = 'yes'
|
||||||
|
self.result_query_duration[line][col] = round(result[Dejavu.MATCH_TIME],3)
|
||||||
|
self.result_match_confidence[line][col] = result[Dejavu.CONFIDENCE]
|
||||||
|
|
||||||
|
song_start_time = re.findall("\_[^\_]+",f)
|
||||||
|
song_start_time = song_start_time[0].lstrip("_ ")
|
||||||
|
|
||||||
|
result_start_time = round((result[Dejavu.OFFSET] * DEFAULT_WINDOW_SIZE *
|
||||||
|
DEFAULT_OVERLAP_RATIO) / (DEFAULT_FS), 0)
|
||||||
|
|
||||||
|
self.result_matching_times[line][col] = int(result_start_time) - int(song_start_time)
|
||||||
|
if (abs(self.result_matching_times[line][col]) == 1):
|
||||||
|
self.result_matching_times[line][col] = 0
|
||||||
|
|
||||||
|
log_msg('query duration: %s' % round(result[Dejavu.MATCH_TIME],3))
|
||||||
|
log_msg('confidence: %s' % result[Dejavu.CONFIDENCE])
|
||||||
|
log_msg('song start_time: %s' % song_start_time)
|
||||||
|
log_msg('result start time: %s' % result_start_time)
|
||||||
|
if (self.result_matching_times[line][col] == 0):
|
||||||
|
log_msg('accurate match')
|
||||||
|
else:
|
||||||
|
log_msg('inaccurate match')
|
||||||
|
log_msg('--------------------------------------------------\n')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
mp3/Brad-Sucks--Total-Breakdown.mp3
Normal file
BIN
mp3/Brad-Sucks--Total-Breakdown.mp3
Normal file
Binary file not shown.
BIN
mp3/Choc--Eigenvalue-Subspace-Decomposition.mp3
Normal file
BIN
mp3/Choc--Eigenvalue-Subspace-Decomposition.mp3
Normal file
Binary file not shown.
BIN
mp3/Josh-Woodward--I-Want-To-Destroy-Something-Beautiful.mp3
Normal file
BIN
mp3/Josh-Woodward--I-Want-To-Destroy-Something-Beautiful.mp3
Normal file
Binary file not shown.
BIN
mp3/Sean-Fournier--Falling-For-You.mp3
Normal file
BIN
mp3/Sean-Fournier--Falling-For-You.mp3
Normal file
Binary file not shown.
BIN
mp3/The-Lights-Galaxia--While-She-Sleeps.mp3
Normal file
BIN
mp3/The-Lights-Galaxia--While-She-Sleeps.mp3
Normal file
Binary file not shown.
2
mp3/about.txt
Normal file
2
mp3/about.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
* Audio in this folder for testing dejavu is taken from here:
|
||||||
|
http://freemusicarchive.org/curator/creative_commons/
|
184
run_tests.py
Normal file
184
run_tests.py
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
from dejavu.testing import *
|
||||||
|
from dejavu import Dejavu
|
||||||
|
from optparse import OptionParser
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
usage = "usage: %prog [options] TESTING_AUDIOFOLDER"
|
||||||
|
parser = OptionParser(usage=usage, version="%prog 1.1")
|
||||||
|
parser.add_option("--secs",
|
||||||
|
action="store",
|
||||||
|
dest="secs",
|
||||||
|
default=5,
|
||||||
|
type=int,
|
||||||
|
help='Number of seconds starting from zero to test')
|
||||||
|
parser.add_option("--results",
|
||||||
|
action="store",
|
||||||
|
dest="results_folder",
|
||||||
|
default="./dejavu_test_results",
|
||||||
|
help='Sets the path where the results are saved')
|
||||||
|
parser.add_option("--temp",
|
||||||
|
action="store",
|
||||||
|
dest="temp_folder",
|
||||||
|
default="./dejavu_temp_testing_files",
|
||||||
|
help='Sets the path where the temp files are saved')
|
||||||
|
parser.add_option("--log",
|
||||||
|
action="store_true",
|
||||||
|
dest="log",
|
||||||
|
default=True,
|
||||||
|
help='Enables logging')
|
||||||
|
parser.add_option("--silent",
|
||||||
|
action="store_false",
|
||||||
|
dest="silent",
|
||||||
|
default=False,
|
||||||
|
help='Disables printing')
|
||||||
|
parser.add_option("--log-file",
|
||||||
|
dest="log_file",
|
||||||
|
default="results-compare.log",
|
||||||
|
help='Set the path and filename of the log file')
|
||||||
|
parser.add_option("--padding",
|
||||||
|
action="store",
|
||||||
|
dest="padding",
|
||||||
|
default=10,
|
||||||
|
type=int,
|
||||||
|
help='Number of seconds to pad choice of place to test from')
|
||||||
|
parser.add_option("--seed",
|
||||||
|
action="store",
|
||||||
|
dest="seed",
|
||||||
|
default=None,
|
||||||
|
type=int,
|
||||||
|
help='Random seed')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
test_folder = args[0]
|
||||||
|
|
||||||
|
# set random seed if set by user
|
||||||
|
set_seed(options.seed)
|
||||||
|
|
||||||
|
# ensure results folder exists
|
||||||
|
try:
|
||||||
|
os.stat(options.results_folder)
|
||||||
|
except:
|
||||||
|
os.mkdir(options.results_folder)
|
||||||
|
|
||||||
|
# set logging
|
||||||
|
if options.log == True:
|
||||||
|
logging.basicConfig(filename=options.log_file, level=logging.DEBUG)
|
||||||
|
|
||||||
|
# set test seconds
|
||||||
|
test_seconds = ['%dsec' % i for i in range(1, options.secs + 1, 1)]
|
||||||
|
|
||||||
|
# generate testing files
|
||||||
|
for i in range(1, options.secs + 1, 1):
|
||||||
|
generate_test_files(test_folder, options.temp_folder,
|
||||||
|
i, padding=options.padding)
|
||||||
|
|
||||||
|
# scan files
|
||||||
|
log_msg("Running Dejavu fingerprinter on files in %s..." % test_folder,
|
||||||
|
log=options.log, silent=options.silent)
|
||||||
|
|
||||||
|
tm = time.time()
|
||||||
|
djv = DejavuTest(options.temp_folder, test_seconds)
|
||||||
|
log_msg("finished obtaining results from dejavu in %s" % (time.time() - tm),
|
||||||
|
log=options.log, silent=options.silent)
|
||||||
|
|
||||||
|
tests = 1 # djv
|
||||||
|
n_secs = len(test_seconds)
|
||||||
|
|
||||||
|
# set result variables -> 4d variables
|
||||||
|
all_match_counter = [[[0 for x in xrange(tests)] for x in xrange(3)] for x in xrange(n_secs)]
|
||||||
|
all_matching_times_counter = [[[0 for x in xrange(tests)] for x in xrange(2)] for x in xrange(n_secs)]
|
||||||
|
all_query_duration = [[[0 for x in xrange(tests)] for x in xrange(djv.n_lines)] for x in xrange(n_secs)]
|
||||||
|
all_match_confidence = [[[0 for x in xrange(tests)] for x in xrange(djv.n_lines)] for x in xrange(n_secs)]
|
||||||
|
|
||||||
|
# group results by seconds
|
||||||
|
for line in range(0, djv.n_lines):
|
||||||
|
for col in range(0, djv.n_columns):
|
||||||
|
# for dejavu
|
||||||
|
all_query_duration[col][line][0] = djv.result_query_duration[line][col]
|
||||||
|
all_match_confidence[col][line][0] = djv.result_match_confidence[line][col]
|
||||||
|
|
||||||
|
djv_match_result = djv.result_match[line][col]
|
||||||
|
|
||||||
|
if djv_match_result == 'yes':
|
||||||
|
all_match_counter[col][0][0] += 1
|
||||||
|
elif djv_match_result == 'no':
|
||||||
|
all_match_counter[col][1][0] += 1
|
||||||
|
else:
|
||||||
|
all_match_counter[col][2][0] += 1
|
||||||
|
|
||||||
|
djv_match_acc = djv.result_matching_times[line][col]
|
||||||
|
|
||||||
|
if djv_match_acc == 0 and djv_match_result == 'yes':
|
||||||
|
all_matching_times_counter[col][0][0] += 1
|
||||||
|
elif djv_match_acc != 0:
|
||||||
|
all_matching_times_counter[col][1][0] += 1
|
||||||
|
|
||||||
|
# create plots
|
||||||
|
djv.create_plots('Confidence', all_match_confidence, options.results_folder)
|
||||||
|
djv.create_plots('Query duration', all_query_duration, options.results_folder)
|
||||||
|
|
||||||
|
for sec in range(0, n_secs):
|
||||||
|
ind = np.arange(3) #
|
||||||
|
width = 0.25 # the width of the bars
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_xlim([-1 * width, 2.75])
|
||||||
|
|
||||||
|
means_dvj = [round(x[0] * 100 / djv.n_lines, 1) for x in all_match_counter[sec]]
|
||||||
|
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
||||||
|
|
||||||
|
# add some
|
||||||
|
ax.set_ylabel('Matching Percentage')
|
||||||
|
ax.set_title('%s Matching Percentage' % test_seconds[sec])
|
||||||
|
ax.set_xticks(ind + width)
|
||||||
|
|
||||||
|
labels = ['yes','no','invalid']
|
||||||
|
ax.set_xticklabels( labels )
|
||||||
|
|
||||||
|
box = ax.get_position()
|
||||||
|
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
||||||
|
#ax.legend((rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
||||||
|
autolabeldoubles(rects1,ax)
|
||||||
|
plt.grid()
|
||||||
|
|
||||||
|
fig_name = os.path.join(options.results_folder, "matching_perc_%s.png" % test_seconds[sec])
|
||||||
|
fig.savefig(fig_name)
|
||||||
|
|
||||||
|
for sec in range(0, n_secs):
|
||||||
|
ind = np.arange(2) #
|
||||||
|
width = 0.25 # the width of the bars
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_xlim([-1*width, 1.75])
|
||||||
|
|
||||||
|
div = all_match_counter[sec][0][0]
|
||||||
|
if div == 0 :
|
||||||
|
div = 1000000
|
||||||
|
|
||||||
|
means_dvj = [round(x[0] * 100 / div, 1) for x in all_matching_times_counter[sec]]
|
||||||
|
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
||||||
|
|
||||||
|
# add some
|
||||||
|
ax.set_ylabel('Matching Accuracy')
|
||||||
|
ax.set_title('%s Matching Times Accuracy' % test_seconds[sec])
|
||||||
|
ax.set_xticks(ind + width)
|
||||||
|
|
||||||
|
labels = ['yes','no']
|
||||||
|
ax.set_xticklabels( labels )
|
||||||
|
|
||||||
|
box = ax.get_position()
|
||||||
|
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
||||||
|
|
||||||
|
#ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
||||||
|
autolabeldoubles(rects1,ax)
|
||||||
|
|
||||||
|
plt.grid()
|
||||||
|
|
||||||
|
fig_name = os.path.join(options.results_folder, "matching_acc_%s.png" % test_seconds[sec])
|
||||||
|
fig.savefig(fig_name)
|
||||||
|
|
||||||
|
# remove temporary folder
|
||||||
|
shutil.rmtree(options.temp_folder)
|
|
@ -1,69 +0,0 @@
|
||||||
import os, subprocess
|
|
||||||
from os import listdir
|
|
||||||
from os.path import isfile, join
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
usage = "usage: %prog [options] SONGS_PATH DESTINATION_FOLDER"
|
|
||||||
parser = OptionParser(usage=usage, version="%prog 1.1")
|
|
||||||
|
|
||||||
parser.add_option("-s", "--start",
|
|
||||||
action="store",
|
|
||||||
dest="start_time",
|
|
||||||
type=int,
|
|
||||||
default=10,
|
|
||||||
metavar="X",
|
|
||||||
help='Test files begin on X sec of the original song'
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_option("--test-seconds",
|
|
||||||
action="append",
|
|
||||||
dest="test_seconds",
|
|
||||||
type=int,
|
|
||||||
default=[],
|
|
||||||
metavar="X",
|
|
||||||
help='Sets the seconds of the test files'
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_option("--audio-format",
|
|
||||||
action="append",
|
|
||||||
dest="audio_formats",
|
|
||||||
default=[],
|
|
||||||
metavar="FORMAT",
|
|
||||||
help='Sets audio formats of files to read'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
if len(args) != 2:
|
|
||||||
parser.error("wrong number of arguments")
|
|
||||||
|
|
||||||
if args[0][len(args[0])-1] != "/":
|
|
||||||
args[0] += "/"
|
|
||||||
|
|
||||||
if args[1][len(args[1])-1] != "/":
|
|
||||||
args[1] += "/"
|
|
||||||
|
|
||||||
if len(options.test_seconds) == 0:
|
|
||||||
options.test_seconds = [1,2,3,4,5,6,7,8,9,10]
|
|
||||||
|
|
||||||
if len(options.audio_formats) == 0:
|
|
||||||
options.audio_formats = ['wav','mp3']
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.stat(args[1])
|
|
||||||
except:
|
|
||||||
os.mkdir(args[1])
|
|
||||||
|
|
||||||
test_files = [ f for f in listdir(args[0]) if isfile(join(args[0],f)) and
|
|
||||||
os.path.splitext(f)[len(os.path.splitext(f))-1][1:] in options.audio_formats ]
|
|
||||||
|
|
||||||
for file in test_files:
|
|
||||||
|
|
||||||
filename = os.path.basename(file)
|
|
||||||
filename,extension = os.path.splitext(filename)
|
|
||||||
|
|
||||||
for i in options.test_seconds:
|
|
||||||
|
|
||||||
test_file_name = "%s%s_%s_%ssec%s" % (args[1],filename,options.start_time,i,extension)
|
|
||||||
subprocess.check_output(["ffmpeg", "-ss", "%s" % options.start_time, '-t' , "%s" % i, "-i", args[0]+file, test_file_name])
|
|
345
test.py
345
test.py
|
@ -1,345 +0,0 @@
|
||||||
# result generator for dejavu
|
|
||||||
|
|
||||||
# TODO: Don't work very well with musics with special chars.
|
|
||||||
# use test file on the format below, with no special chars and only one "-" to separate artist from song
|
|
||||||
|
|
||||||
import os, subprocess, json, re, sys
|
|
||||||
import logging, time
|
|
||||||
from os import listdir
|
|
||||||
from os.path import isfile, join
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from optparse import OptionParser
|
|
||||||
from dejavu.decoder import path_to_songname
|
|
||||||
import ast
|
|
||||||
|
|
||||||
#####
|
|
||||||
### Test files are in specific format:
|
|
||||||
### 'artist_name'-'song_name'_'start_time'_'duration'sec.wav
|
|
||||||
#####
|
|
||||||
|
|
||||||
DEFAULT_FS = 44100
|
|
||||||
DEFAULT_WINDOW_SIZE = 4096
|
|
||||||
DEFAULT_OVERLAP_RATIO = 0.5
|
|
||||||
|
|
||||||
FIELD_SONG_NAME = 'song_name'
|
|
||||||
FIELD_CONFIDENCE = 'confidence'
|
|
||||||
FIELD_QUERY_TIME = 'match_time'
|
|
||||||
FIELD_OFFSET = 'offset'
|
|
||||||
|
|
||||||
# Parse options
|
|
||||||
usage = "usage: %prog [options] DEJAVU_PATH TEST_FOLDER"
|
|
||||||
parser = OptionParser(usage=usage, version="%prog 1.1")
|
|
||||||
parser.add_option("--no-log",
|
|
||||||
action="store_false",
|
|
||||||
dest="log",
|
|
||||||
default=True,
|
|
||||||
help='Disables logging')
|
|
||||||
parser.add_option("--log-file",
|
|
||||||
dest="log_file",
|
|
||||||
default="results-compare.log",
|
|
||||||
metavar="LOG_FILE",
|
|
||||||
help='Set the path and filename of the log file')
|
|
||||||
parser.add_option("--test-seconds",
|
|
||||||
action="append",
|
|
||||||
dest="test_seconds",
|
|
||||||
default=[],
|
|
||||||
metavar="Xsec",
|
|
||||||
help='Appends seconds to test suit')
|
|
||||||
parser.add_option("--results-folder",
|
|
||||||
action="store",
|
|
||||||
dest="results_folder",
|
|
||||||
metavar="FOLDER",
|
|
||||||
help='Sets the path where the results are saved')
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
if len(args) != 2:
|
|
||||||
parser.error("wrong number of arguments")
|
|
||||||
|
|
||||||
if len(options.test_seconds) == 0:
|
|
||||||
options.test_seconds = ['1sec','2sec','3sec','4sec','5sec','6sec','7sec','8sec','9sec','10sec']
|
|
||||||
|
|
||||||
if options.log == True:
|
|
||||||
logging.basicConfig(filename=options.log_file, level=logging.DEBUG)
|
|
||||||
|
|
||||||
if options.results_folder != "" and options.results_folder[len(options.results_folder) - 1] != '/':
|
|
||||||
options.results_folder += "/"
|
|
||||||
|
|
||||||
# ensure results folder exists
|
|
||||||
try:
|
|
||||||
os.stat(options.results_folder)
|
|
||||||
except:
|
|
||||||
os.mkdir(options.results_folder)
|
|
||||||
|
|
||||||
def log_msg(msg):
|
|
||||||
if options.log == True:
|
|
||||||
logging.debug(msg)
|
|
||||||
|
|
||||||
class DejavuTest (object):
|
|
||||||
def __init__(self, folder, seconds):
|
|
||||||
super(DejavuTest, self).__init__()
|
|
||||||
|
|
||||||
self.test_folder = folder
|
|
||||||
self.test_seconds = seconds
|
|
||||||
self.test_songs = []
|
|
||||||
self.test_files = [ f for f in listdir(self.test_folder) if isfile(join(self.test_folder,f))
|
|
||||||
and re.findall("[0-9]*sec",f)[0] in self.test_seconds ]
|
|
||||||
self.n_columns = len(self.test_seconds)
|
|
||||||
self.n_lines = len(self.test_files) / self.n_columns
|
|
||||||
|
|
||||||
# variable match results (yes, no, invalid)
|
|
||||||
self.result_match = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
|
||||||
|
|
||||||
print "columns:", self.n_columns
|
|
||||||
print "length of test files:", len(self.test_files)
|
|
||||||
print "lines:", self.n_lines
|
|
||||||
print "result_match matrix:", self.result_match
|
|
||||||
|
|
||||||
# variable match precision (if matched in the corrected time)
|
|
||||||
self.result_matching_times = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
|
||||||
|
|
||||||
# variable mahing time (query time)
|
|
||||||
self.result_query_duration = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
|
||||||
|
|
||||||
# variable confidence
|
|
||||||
self.result_match_confidence = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)]
|
|
||||||
|
|
||||||
self.begin()
|
|
||||||
|
|
||||||
def get_column_id (self, secs):
|
|
||||||
for i, sec in enumerate(self.test_seconds):
|
|
||||||
if secs == sec:
|
|
||||||
return i
|
|
||||||
|
|
||||||
def get_line_id (self, song):
|
|
||||||
for i, s in enumerate(self.test_songs):
|
|
||||||
if song == s:
|
|
||||||
return i
|
|
||||||
self.test_songs.append(song)
|
|
||||||
return len(self.test_songs) - 1
|
|
||||||
|
|
||||||
def begin(self):
|
|
||||||
for f in self.test_files:
|
|
||||||
log_msg('--------------------------------------------------')
|
|
||||||
log_msg('file: %s' % f)
|
|
||||||
|
|
||||||
# get column
|
|
||||||
col = self.get_column_id(re.findall("[0-9]*sec",f)[0])
|
|
||||||
song = path_to_songname(f).split("_")[0] # format: XXXX_offset_length.mp3
|
|
||||||
line = self.get_line_id (song)
|
|
||||||
result = subprocess.check_output(["python", args[0] + "/dejavu.py", 'recognize', 'file', self.test_folder+"/"+f])
|
|
||||||
log_msg('RESULT: %s' % result.strip() )
|
|
||||||
|
|
||||||
if result.strip() == "None":
|
|
||||||
log_msg('No match')
|
|
||||||
self.result_match[line][col] = 'no'
|
|
||||||
self.result_matching_times[line][col] = 0
|
|
||||||
self.result_query_duration[line][col] = 0
|
|
||||||
self.result_match_confidence[line][col] = 0
|
|
||||||
|
|
||||||
else:
|
|
||||||
result = result.strip()
|
|
||||||
result = result.replace(" \'", ' "')
|
|
||||||
result = result.replace("{\'", '{"')
|
|
||||||
result = result.replace("\':", '":')
|
|
||||||
result = result.replace("\',", '",')
|
|
||||||
|
|
||||||
# which song did we predict?
|
|
||||||
result = ast.literal_eval(result)
|
|
||||||
print "result", result
|
|
||||||
song_result = result["song_name"]
|
|
||||||
log_msg('song: %s' % song)
|
|
||||||
log_msg('song_result: %s' % song_result)
|
|
||||||
|
|
||||||
if song_result != song:
|
|
||||||
log_msg('invalid match')
|
|
||||||
self.result_match[line][col] = 'invalid'
|
|
||||||
self.result_matching_times[line][col] = 0
|
|
||||||
self.result_query_duration[line][col] = 0
|
|
||||||
self.result_match_confidence[line][col] = 0
|
|
||||||
else:
|
|
||||||
log_msg('correct match')
|
|
||||||
print self.result_match
|
|
||||||
self.result_match[line][col] = 'yes'
|
|
||||||
self.result_query_duration[line][col] = round(result[FIELD_QUERY_TIME],3)
|
|
||||||
self.result_match_confidence[line][col] = result[FIELD_CONFIDENCE]
|
|
||||||
|
|
||||||
song_start_time = re.findall("\_[^\_]+",f)
|
|
||||||
song_start_time = song_start_time[0].lstrip("_ ")
|
|
||||||
|
|
||||||
#result_start_time = round((result[FIELD_SONG_DURATION] * result[FIELD_OFFSET]) / float(result[FIELD_SONG_SPEC_DURATION]), 0)
|
|
||||||
result_start_time = round((result[FIELD_OFFSET] * DEFAULT_WINDOW_SIZE * DEFAULT_OVERLAP_RATIO) / (DEFAULT_FS),0)
|
|
||||||
|
|
||||||
self.result_matching_times[line][col] = int(result_start_time) - int(song_start_time)
|
|
||||||
if (abs(self.result_matching_times[line][col]) == 1):
|
|
||||||
self.result_matching_times[line][col] = 0
|
|
||||||
|
|
||||||
log_msg('query duration: %s' % round(result[FIELD_QUERY_TIME],3))
|
|
||||||
log_msg('confidence: %s' % result[FIELD_CONFIDENCE])
|
|
||||||
log_msg('song start_time: %s' % song_start_time)
|
|
||||||
log_msg('result start time: %s' % result_start_time)
|
|
||||||
if (self.result_matching_times[line][col] == 0):
|
|
||||||
log_msg('accurate match')
|
|
||||||
else:
|
|
||||||
log_msg('inaccurate match')
|
|
||||||
log_msg('--------------------------------------------------\n')
|
|
||||||
|
|
||||||
print "obtaining results from dejavu"
|
|
||||||
log_msg('obtaining results from dejavu')
|
|
||||||
tm = time.time()
|
|
||||||
djv = DejavuTest(args[1], options.test_seconds)
|
|
||||||
print "finished obtaining results from dejavu in %s" % (time.time() - tm)
|
|
||||||
log_msg("finished obtaining results from dejavu in %s" % (time.time() - tm))
|
|
||||||
|
|
||||||
tests_n_lines = djv.n_lines
|
|
||||||
tests_n_columns = djv.n_columns # len(options.test_seconds)
|
|
||||||
tests = 1 # djv
|
|
||||||
n_secs = len(options.test_seconds) # = tests.n_columns
|
|
||||||
|
|
||||||
# set result variables -> 4d variables
|
|
||||||
all_match_counter = [[[0 for x in xrange(tests)] for x in xrange(3)] for x in xrange(n_secs)]
|
|
||||||
all_matching_times_counter = [[[0 for x in xrange(tests)] for x in xrange(2)] for x in xrange(n_secs)]
|
|
||||||
all_query_duration = [[[0 for x in xrange(tests)] for x in xrange(tests_n_lines)] for x in xrange(n_secs)]
|
|
||||||
all_match_confidence = [[[0 for x in xrange(tests)] for x in xrange(tests_n_lines)] for x in xrange(n_secs)]
|
|
||||||
|
|
||||||
# agroup results by seconds
|
|
||||||
for line in range(0, tests_n_lines):
|
|
||||||
for col in range(0, tests_n_columns):
|
|
||||||
# for dejavu
|
|
||||||
all_query_duration[col][line][0] = djv.result_query_duration[line][col]
|
|
||||||
all_match_confidence[col][line][0] = djv.result_match_confidence[line][col]
|
|
||||||
|
|
||||||
djv_match_result = djv.result_match[line][col]
|
|
||||||
|
|
||||||
if djv_match_result == 'yes':
|
|
||||||
all_match_counter[col][0][0] += 1
|
|
||||||
elif djv_match_result == 'no':
|
|
||||||
all_match_counter[col][1][0] += 1
|
|
||||||
else:
|
|
||||||
all_match_counter[col][2][0] += 1
|
|
||||||
|
|
||||||
djv_match_acc = djv.result_matching_times[line][col]
|
|
||||||
|
|
||||||
if djv_match_acc == 0 and djv_match_result == 'yes':
|
|
||||||
all_matching_times_counter[col][0][0] += 1
|
|
||||||
elif djv_match_acc != 0:
|
|
||||||
all_matching_times_counter[col][1][0] += 1
|
|
||||||
|
|
||||||
def autolabel(rects,ax):
|
|
||||||
# attach some text labels
|
|
||||||
for rect in rects:
|
|
||||||
height = rect.get_height()
|
|
||||||
ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height),
|
|
||||||
ha='center', va='bottom')
|
|
||||||
|
|
||||||
def autolabeldoubles(rects,ax):
|
|
||||||
# attach some text labels
|
|
||||||
for rect in rects:
|
|
||||||
height = rect.get_height()
|
|
||||||
ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%s'%round(float(height),3),
|
|
||||||
ha='center', va='bottom')
|
|
||||||
|
|
||||||
def create_plots(name,results):
|
|
||||||
for sec in range(0,n_secs):
|
|
||||||
ind = np.arange(tests_n_lines) #
|
|
||||||
width = 0.25 # the width of the bars
|
|
||||||
|
|
||||||
fig = plt.figure()
|
|
||||||
ax = fig.add_subplot(111)
|
|
||||||
ax.set_xlim([-1*width, 2*width])
|
|
||||||
|
|
||||||
means_dvj = [x[0] for x in results[sec]]
|
|
||||||
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
|
||||||
|
|
||||||
# add some
|
|
||||||
ax.set_ylabel(name)
|
|
||||||
ax.set_title("%s %s Results" % (options.test_seconds[sec],name))
|
|
||||||
ax.set_xticks(ind+width)
|
|
||||||
|
|
||||||
labels = [0 for x in range(0,tests_n_lines)]
|
|
||||||
for x in range(0,tests_n_lines):
|
|
||||||
labels[x] = "song %s" % (x+1)
|
|
||||||
ax.set_xticklabels( labels )
|
|
||||||
|
|
||||||
box = ax.get_position()
|
|
||||||
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
|
||||||
|
|
||||||
#ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
|
||||||
|
|
||||||
if name == 'Confidence':
|
|
||||||
autolabel(rects1,ax)
|
|
||||||
else:
|
|
||||||
autolabeldoubles(rects1,ax)
|
|
||||||
|
|
||||||
plt.grid()
|
|
||||||
|
|
||||||
fig_name = "%s%s_%s.png" % (options.results_folder,name,options.test_seconds[sec])
|
|
||||||
fig.savefig(fig_name)
|
|
||||||
|
|
||||||
create_plots('Confidence',all_match_confidence)
|
|
||||||
create_plots('Query duration',all_query_duration)
|
|
||||||
|
|
||||||
for sec in range(0,n_secs):
|
|
||||||
ind = np.arange(3) #
|
|
||||||
width = 0.25 # the width of the bars
|
|
||||||
|
|
||||||
fig = plt.figure()
|
|
||||||
ax = fig.add_subplot(111)
|
|
||||||
ax.set_xlim([-1*width, 2.75])
|
|
||||||
|
|
||||||
means_dvj = [round(x[0]*100/tests_n_lines,1) for x in all_match_counter[sec]]
|
|
||||||
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
|
||||||
|
|
||||||
# add some
|
|
||||||
ax.set_ylabel('Matching Percentage')
|
|
||||||
ax.set_title('%s Matching Percentage' % options.test_seconds[sec])
|
|
||||||
ax.set_xticks(ind+width)
|
|
||||||
|
|
||||||
labels = ['yes','no','invalid']
|
|
||||||
ax.set_xticklabels( labels )
|
|
||||||
|
|
||||||
box = ax.get_position()
|
|
||||||
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
|
||||||
|
|
||||||
#ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
|
||||||
autolabeldoubles(rects1,ax)
|
|
||||||
|
|
||||||
plt.grid()
|
|
||||||
|
|
||||||
fig_name = "%smatching_perc_%s.png" % (options.results_folder,options.test_seconds[sec])
|
|
||||||
fig.savefig(fig_name)
|
|
||||||
|
|
||||||
for sec in range(0,n_secs):
|
|
||||||
ind = np.arange(2) #
|
|
||||||
width = 0.25 # the width of the bars
|
|
||||||
|
|
||||||
fig = plt.figure()
|
|
||||||
ax = fig.add_subplot(111)
|
|
||||||
ax.set_xlim([-1*width, 1.75])
|
|
||||||
|
|
||||||
div = all_match_counter[sec][0][0]
|
|
||||||
if div == 0 :
|
|
||||||
div = 1000000
|
|
||||||
|
|
||||||
means_dvj = [round(x[0]*100/div,1) for x in all_matching_times_counter[sec]]
|
|
||||||
rects1 = ax.bar(ind, means_dvj, width, color='r')
|
|
||||||
|
|
||||||
# add some
|
|
||||||
ax.set_ylabel('Matching Accuracy')
|
|
||||||
ax.set_title('%s Matching Times Accuracy' % options.test_seconds[sec])
|
|
||||||
ax.set_xticks(ind+width)
|
|
||||||
|
|
||||||
labels = ['yes','no']
|
|
||||||
ax.set_xticklabels( labels )
|
|
||||||
|
|
||||||
box = ax.get_position()
|
|
||||||
ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
|
|
||||||
|
|
||||||
#ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
|
|
||||||
autolabeldoubles(rects1,ax)
|
|
||||||
|
|
||||||
plt.grid()
|
|
||||||
|
|
||||||
fig_name = "%smatching_acc_%s.png" % (options.results_folder,options.test_seconds[sec])
|
|
||||||
fig.savefig(fig_name)
|
|
25
test_dejavu.sh
Normal file
25
test_dejavu.sh
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#####################################
|
||||||
|
### Dejavu example testing script ###
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Clear out previous results
|
||||||
|
rm -rf ./results ./temp_audio
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Fingerprint files of extension mp3 in the ./mp3 folder
|
||||||
|
python dejavu.py fingerprint ./mp3/ mp3
|
||||||
|
|
||||||
|
##########
|
||||||
|
# Run a test suite on the ./mp3 folder by extracting 1, 2, 3, 4, and 5
|
||||||
|
# second clips sampled randomly from within each song 8 seconds
|
||||||
|
# away from start or end, sampling with random seed = 42, and finally
|
||||||
|
# store results in ./results and log to dejavu-test.log
|
||||||
|
python run_tests.py \
|
||||||
|
--secs 5 \
|
||||||
|
--temp ./temp_audio \
|
||||||
|
--log-file ./results/dejavu-test.log \
|
||||||
|
--padding 8 \
|
||||||
|
--seed 42 \
|
||||||
|
--results ./results \
|
||||||
|
./mp3
|
Loading…
Reference in a new issue