mirror of
https://github.com/YuzuZensai/spleeter.git
synced 2026-01-06 04:32:43 +00:00
feat: add filename format
This commit is contained in:
@@ -28,6 +28,18 @@ OPT_OUTPUT = {
|
||||
'help': 'Path of the output directory to write audio files in'
|
||||
}
|
||||
|
||||
# -f opt specification (separate).
|
||||
OPT_FORMAT = {
|
||||
'dest': 'filename_format',
|
||||
'default': '{filename}/{instrument}.{codec}',
|
||||
'help': (
|
||||
'Template string that will be formatted to generated'
|
||||
'output filename. Such template should be Python formattable'
|
||||
'string, and could use {filename}, {instrument}, and {codec}'
|
||||
'variables.'
|
||||
)
|
||||
}
|
||||
|
||||
# -p opt specification (train, evaluate and separate).
|
||||
OPT_PARAMS = {
|
||||
'dest': 'configuration',
|
||||
@@ -37,23 +49,6 @@ OPT_PARAMS = {
|
||||
'help': 'JSON filename that contains params'
|
||||
}
|
||||
|
||||
# -n opt specification (separate).
|
||||
OPT_OUTPUT_NAMING = {
|
||||
'dest': 'output_naming',
|
||||
'default': 'filename',
|
||||
'choices': ('directory', 'filename'),
|
||||
'help': (
|
||||
'Choice for naming the output base path: '
|
||||
'"filename" (use the input filename, i.e '
|
||||
'/path/to/audio/mix.wav will be separated to '
|
||||
'<output_path>/mix/<instument1>.wav, '
|
||||
'<output_path>/mix/<instument2>.wav...) or '
|
||||
'"directory" (use the name of the input last level'
|
||||
' directory, for instance /path/to/audio/mix.wav '
|
||||
'will be separated to <output_path>/audio/<instument1>.wav'
|
||||
', <output_path>/audio/<instument2>.wav)')
|
||||
}
|
||||
|
||||
# -s opt specification (separate).
|
||||
OPT_OFFSET = {
|
||||
'dest': 'offset',
|
||||
@@ -175,7 +170,7 @@ def _create_separate_parser(parser_factory):
|
||||
_add_common_options(parser)
|
||||
parser.add_argument('-i', '--inputs', **OPT_INPUT)
|
||||
parser.add_argument('-o', '--output_path', **OPT_OUTPUT)
|
||||
parser.add_argument('-n', '--output_naming', **OPT_OUTPUT_NAMING)
|
||||
parser.add_argument('-f', '--filename_format', **OPT_FORMAT)
|
||||
parser.add_argument('-d', '--duration', **OPT_DURATION)
|
||||
parser.add_argument('-s', '--offset', **OPT_OFFSET)
|
||||
parser.add_argument('-c', '--codec', **OPT_CODEC)
|
||||
|
||||
@@ -44,7 +44,6 @@ __license__ = 'MIT License'
|
||||
|
||||
_SPLIT = 'test'
|
||||
_MIXTURE = 'mixture.wav'
|
||||
_NAMING = 'directory'
|
||||
_AUDIO_DIRECTORY = 'audio'
|
||||
_METRICS_DIRECTORY = 'metrics'
|
||||
_INSTRUMENTS = ('vocals', 'drums', 'bass', 'other')
|
||||
@@ -71,7 +70,6 @@ def _separate_evaluation_dataset(arguments, musdb_root_directory, params):
|
||||
audio_filenames=mixtures,
|
||||
audio_codec='wav',
|
||||
output_path=join(audio_output_directory, _SPLIT),
|
||||
output_naming=_NAMING,
|
||||
max_duration=600.,
|
||||
MWF=arguments.MWF,
|
||||
verbose=arguments.verbose),
|
||||
|
||||
@@ -27,7 +27,9 @@ def entrypoint(arguments, params):
|
||||
"""
|
||||
# TODO: check with output naming.
|
||||
audio_adapter = get_audio_adapter(arguments.audio_adapter)
|
||||
separator = Separator(arguments.configuration, arguments.MWF)
|
||||
separator = Separator(
|
||||
arguments.configuration,
|
||||
arguments.MWF)
|
||||
for filename in arguments.inputs:
|
||||
separator.separate_to_file(
|
||||
filename,
|
||||
@@ -37,6 +39,7 @@ def entrypoint(arguments, params):
|
||||
duration=arguments.duration,
|
||||
codec=arguments.codec,
|
||||
bitrate=arguments.bitrate,
|
||||
filename_format=arguments.filename_format,
|
||||
synchronous=False
|
||||
)
|
||||
separator.join()
|
||||
|
||||
@@ -18,8 +18,9 @@ import json
|
||||
from functools import partial
|
||||
from multiprocessing import Pool
|
||||
from pathlib import Path
|
||||
from os.path import join
|
||||
from os.path import basename, join
|
||||
|
||||
from . import SpleeterError
|
||||
from .audio.adapter import get_default_audio_adapter
|
||||
from .audio.convertor import to_stereo
|
||||
from .model import model_fn
|
||||
@@ -93,10 +94,13 @@ class Separator(object):
|
||||
self, audio_descriptor, destination,
|
||||
audio_adapter=get_default_audio_adapter(),
|
||||
offset=0, duration=600., codec='wav', bitrate='128k',
|
||||
synchronous=True):
|
||||
filename_format='{filename}/{instrument}.{codec}', synchronous=True):
|
||||
""" Performs source separation and export result to file using
|
||||
given audio adapter.
|
||||
|
||||
Filename format should be a Python formattable string that could use
|
||||
following parameters : {instrument}, {filename} and {codec}.
|
||||
|
||||
:param audio_descriptor: Describe song to separate, used by audio
|
||||
adapter to retrieve and load audio data,
|
||||
in case of file based audio adapter, such
|
||||
@@ -107,6 +111,7 @@ class Separator(object):
|
||||
:param duration: (Optional) Duration of loaded song.
|
||||
:param codec: (Optional) Export codec.
|
||||
:param bitrate: (Optional) Export bitrate.
|
||||
:param filename_format: (Optional) Filename format.
|
||||
:param synchronous: (Optional) True is should by synchronous.
|
||||
"""
|
||||
waveform, _ = audio_adapter.load(
|
||||
@@ -115,9 +120,20 @@ class Separator(object):
|
||||
duration=duration,
|
||||
sample_rate=self._sample_rate)
|
||||
sources = self.separate(waveform)
|
||||
filename = basename(audio_descriptor)
|
||||
generated = []
|
||||
for instrument, data in sources.items():
|
||||
path = join(destination, filename_format.format(
|
||||
filename=filename,
|
||||
instrument=instrument,
|
||||
codec=codec))
|
||||
if path in generated:
|
||||
raise SpleeterError((
|
||||
f'Separated source path conflict : {path},'
|
||||
'please check your filename format'))
|
||||
generated.append(path)
|
||||
task = self._pool.apply_async(audio_adapter.save, (
|
||||
join(destination, f'{instrument}.{codec}'),
|
||||
path,
|
||||
data,
|
||||
self._sample_rate,
|
||||
codec,
|
||||
|
||||
Reference in New Issue
Block a user