pythonspleeter

How do I pass a format-able string to a python function?


I am using a software library that saves its results in a few sound files. I want to save them with a better name in a different directory other than the default one. The software provides the optional parameter filename_format for this purpose. The docs say to use it this way:

separator.separate_to_file("/path/to/audio.mp3",  "/path/to/output",  filename_format="{filename}_{instrument}.{codec}")

The docs say, "You can user the keyword filename (input file name), instrument (name of the instrument), foldername (name of the folder the input file is in) and codec between curly brackets within the formatting string."

Here is how I am trying to call the function:

separator.separate_to_file(audioDescriptor, destination, filename_format='{}_{}.{}'.format(basename, "accompaniment", "wav"))

That throws the error:

spleeter.SpleeterError: Separated source path conflict : /Users/.../separation-component/music/audio_OUTPUT/Yellow_accompaniment.wav,please check your filename format

For reference here is the function I am calling.

    def save_to_file(
    self,
    sources: Dict,
    audio_descriptor: AudioDescriptor,
    destination: str,
    filename_format: str = "{filename}/{instrument}.{codec}",
    codec: Codec = Codec.WAV,
    audio_adapter: Optional[AudioAdapter] = None,
    bitrate: str = "128k",
    synchronous: bool = True,
) -> None:
    """
    Export dictionary of sources to files.

    Parameters:
        sources (Dict):
            Dictionary of sources to be exported. The keys are the name
            of the instruments, and the values are `N x 2` numpy arrays
            containing the corresponding intrument waveform, as
            returned by the separate method
        audio_descriptor (AudioDescriptor):
            Describe song to separate, used by audio adapter to
            retrieve and load audio data, in case of file based audio
            adapter, such descriptor would be a file path.
        destination (str):
            Target directory to write output to.
        filename_format (str):
            (Optional) Filename format.
        codec (Codec):
            (Optional) Export codec.
        audio_adapter (Optional[AudioAdapter]):
            (Optional) Audio adapter to use for I/O.
        bitrate (str):
            (Optional) Export bitrate.
        synchronous (bool):
            (Optional) True is should by synchronous.
    """
    if audio_adapter is None:
        audio_adapter = AudioAdapter.default()
    foldername = basename(dirname(audio_descriptor))
    filename = splitext(basename(audio_descriptor))[0]
    generated = []
    for instrument, data in sources.items():
        path = join(
            destination,
            filename_format.format(
                filename=filename,
                instrument=instrument,
                foldername=foldername,
                codec=codec,
            ),
        )
        directory = os.path.dirname(path)
        if not os.path.exists(directory):
            os.makedirs(directory)
        if path in generated:
            raise SpleeterError(
                (
                    f"Separated source path conflict : {path},"
                    "please check your filename format"
                )
            )
        generated.append(path)
        if self._pool:
            task = self._pool.apply_async(
                audio_adapter.save, (path, data, self._sample_rate, codec, bitrate)
            )
            self._tasks.append(task)
        else:
            audio_adapter.save(path, data, self._sample_rate, codec, bitrate)
    if synchronous and self._pool:
        self.join()

Solution

  • See where it's calling

    filename_format.format(
                    filename=filename,
                    instrument=instrument,
                    foldername=foldername,
                    codec=codec,
                ),
    

    it's expecting the filename_format arg to contain JUST the string (in your case "{filename}_{instrument}.{codec}" - it does the call to format for you. And it's using named parameters, so you need to put names between curly braces that match the names called in the format call.