mirror of
https://github.com/YuzuZensai/spleeter.git
synced 2026-01-31 14:58:23 +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'
|
'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).
|
# -p opt specification (train, evaluate and separate).
|
||||||
OPT_PARAMS = {
|
OPT_PARAMS = {
|
||||||
'dest': 'configuration',
|
'dest': 'configuration',
|
||||||
@@ -37,23 +49,6 @@ OPT_PARAMS = {
|
|||||||
'help': 'JSON filename that contains 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).
|
# -s opt specification (separate).
|
||||||
OPT_OFFSET = {
|
OPT_OFFSET = {
|
||||||
'dest': 'offset',
|
'dest': 'offset',
|
||||||
@@ -175,7 +170,7 @@ def _create_separate_parser(parser_factory):
|
|||||||
_add_common_options(parser)
|
_add_common_options(parser)
|
||||||
parser.add_argument('-i', '--inputs', **OPT_INPUT)
|
parser.add_argument('-i', '--inputs', **OPT_INPUT)
|
||||||
parser.add_argument('-o', '--output_path', **OPT_OUTPUT)
|
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('-d', '--duration', **OPT_DURATION)
|
||||||
parser.add_argument('-s', '--offset', **OPT_OFFSET)
|
parser.add_argument('-s', '--offset', **OPT_OFFSET)
|
||||||
parser.add_argument('-c', '--codec', **OPT_CODEC)
|
parser.add_argument('-c', '--codec', **OPT_CODEC)
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ __license__ = 'MIT License'
|
|||||||
|
|
||||||
_SPLIT = 'test'
|
_SPLIT = 'test'
|
||||||
_MIXTURE = 'mixture.wav'
|
_MIXTURE = 'mixture.wav'
|
||||||
_NAMING = 'directory'
|
|
||||||
_AUDIO_DIRECTORY = 'audio'
|
_AUDIO_DIRECTORY = 'audio'
|
||||||
_METRICS_DIRECTORY = 'metrics'
|
_METRICS_DIRECTORY = 'metrics'
|
||||||
_INSTRUMENTS = ('vocals', 'drums', 'bass', 'other')
|
_INSTRUMENTS = ('vocals', 'drums', 'bass', 'other')
|
||||||
@@ -71,7 +70,6 @@ def _separate_evaluation_dataset(arguments, musdb_root_directory, params):
|
|||||||
audio_filenames=mixtures,
|
audio_filenames=mixtures,
|
||||||
audio_codec='wav',
|
audio_codec='wav',
|
||||||
output_path=join(audio_output_directory, _SPLIT),
|
output_path=join(audio_output_directory, _SPLIT),
|
||||||
output_naming=_NAMING,
|
|
||||||
max_duration=600.,
|
max_duration=600.,
|
||||||
MWF=arguments.MWF,
|
MWF=arguments.MWF,
|
||||||
verbose=arguments.verbose),
|
verbose=arguments.verbose),
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ def entrypoint(arguments, params):
|
|||||||
"""
|
"""
|
||||||
# TODO: check with output naming.
|
# TODO: check with output naming.
|
||||||
audio_adapter = get_audio_adapter(arguments.audio_adapter)
|
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:
|
for filename in arguments.inputs:
|
||||||
separator.separate_to_file(
|
separator.separate_to_file(
|
||||||
filename,
|
filename,
|
||||||
@@ -37,6 +39,7 @@ def entrypoint(arguments, params):
|
|||||||
duration=arguments.duration,
|
duration=arguments.duration,
|
||||||
codec=arguments.codec,
|
codec=arguments.codec,
|
||||||
bitrate=arguments.bitrate,
|
bitrate=arguments.bitrate,
|
||||||
|
filename_format=arguments.filename_format,
|
||||||
synchronous=False
|
synchronous=False
|
||||||
)
|
)
|
||||||
separator.join()
|
separator.join()
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ import json
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from pathlib import Path
|
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.adapter import get_default_audio_adapter
|
||||||
from .audio.convertor import to_stereo
|
from .audio.convertor import to_stereo
|
||||||
from .model import model_fn
|
from .model import model_fn
|
||||||
@@ -93,10 +94,13 @@ class Separator(object):
|
|||||||
self, audio_descriptor, destination,
|
self, audio_descriptor, destination,
|
||||||
audio_adapter=get_default_audio_adapter(),
|
audio_adapter=get_default_audio_adapter(),
|
||||||
offset=0, duration=600., codec='wav', bitrate='128k',
|
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
|
""" Performs source separation and export result to file using
|
||||||
given audio adapter.
|
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
|
:param audio_descriptor: Describe song to separate, used by audio
|
||||||
adapter to retrieve and load audio data,
|
adapter to retrieve and load audio data,
|
||||||
in case of file based audio adapter, such
|
in case of file based audio adapter, such
|
||||||
@@ -107,6 +111,7 @@ class Separator(object):
|
|||||||
:param duration: (Optional) Duration of loaded song.
|
:param duration: (Optional) Duration of loaded song.
|
||||||
:param codec: (Optional) Export codec.
|
:param codec: (Optional) Export codec.
|
||||||
:param bitrate: (Optional) Export bitrate.
|
:param bitrate: (Optional) Export bitrate.
|
||||||
|
:param filename_format: (Optional) Filename format.
|
||||||
:param synchronous: (Optional) True is should by synchronous.
|
:param synchronous: (Optional) True is should by synchronous.
|
||||||
"""
|
"""
|
||||||
waveform, _ = audio_adapter.load(
|
waveform, _ = audio_adapter.load(
|
||||||
@@ -115,9 +120,20 @@ class Separator(object):
|
|||||||
duration=duration,
|
duration=duration,
|
||||||
sample_rate=self._sample_rate)
|
sample_rate=self._sample_rate)
|
||||||
sources = self.separate(waveform)
|
sources = self.separate(waveform)
|
||||||
|
filename = basename(audio_descriptor)
|
||||||
|
generated = []
|
||||||
for instrument, data in sources.items():
|
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, (
|
task = self._pool.apply_async(audio_adapter.save, (
|
||||||
join(destination, f'{instrument}.{codec}'),
|
path,
|
||||||
data,
|
data,
|
||||||
self._sample_rate,
|
self._sample_rate,
|
||||||
codec,
|
codec,
|
||||||
|
|||||||
Reference in New Issue
Block a user