feat: add detailed ffprobe logs

This commit is contained in:
Félix Voituret
2019-11-20 14:33:18 +01:00
parent eb32348c34
commit 7b5222a64a
10 changed files with 58 additions and 41 deletions

View File

@@ -16,3 +16,9 @@
__email__ = 'research@deezer.com'
__author__ = 'Deezer Research'
__license__ = 'MIT License'
class SpleeterError(Exception):
""" Custom exception for Spleeter related error. """
pass

View File

@@ -10,9 +10,13 @@
import sys
import warnings
from . import SpleeterError
from .commands import create_argument_parser
from .utils.configuration import load_configuration
from .utils.logging import enable_logging, enable_tensorflow_logging
from .utils.logging import (
enable_logging,
enable_tensorflow_logging,
get_logger)
__email__ = 'research@deezer.com'
__author__ = 'Deezer Research'
@@ -26,19 +30,22 @@ def main(argv):
:param argv: Provided command line arguments.
"""
parser = create_argument_parser()
arguments = parser.parse_args(argv[1:])
enable_logging()
if arguments.verbose:
enable_tensorflow_logging()
if arguments.command == 'separate':
from .commands.separate import entrypoint
elif arguments.command == 'train':
from .commands.train import entrypoint
elif arguments.command == 'evaluate':
from .commands.evaluate import entrypoint
params = load_configuration(arguments.params_filename)
entrypoint(arguments, params)
try:
parser = create_argument_parser()
arguments = parser.parse_args(argv[1:])
enable_logging()
if arguments.verbose:
enable_tensorflow_logging()
if arguments.command == 'separate':
from .commands.separate import entrypoint
elif arguments.command == 'train':
from .commands.train import entrypoint
elif arguments.command == 'evaluate':
from .commands.evaluate import entrypoint
params = load_configuration(arguments.configuration)
entrypoint(arguments, params)
except SpleeterError as e:
get_logger().error(e)
def entrypoint():

View File

@@ -16,6 +16,7 @@ import tensorflow as tf
from tensorflow.contrib.signal import stft, hann_window
# pylint: enable=import-error
from .. import SpleeterError
from ..utils.logging import get_logger
__email__ = 'research@deezer.com'
@@ -73,7 +74,8 @@ class AudioAdapter(ABC):
# Defined safe loading function.
def safe_load(path, offset, duration, sample_rate, dtype):
get_logger().info(
logger = get_logger()
logger.info(
f'Loading audio {path} from {offset} to {offset + duration}')
try:
(data, _) = self.load(
@@ -82,10 +84,12 @@ class AudioAdapter(ABC):
duration.numpy(),
sample_rate.numpy(),
dtype=dtype.numpy())
get_logger().info('Audio data loaded successfully')
logger.info('Audio data loaded successfully')
return (data, False)
except Exception as e:
get_logger().warning(e)
logger.exception(
'An error occurs while loading audio',
exc_info=e)
return (np.float32(-1.0), True)
# Execute function and format results.
@@ -140,6 +144,6 @@ def get_audio_adapter(descriptor):
adapter_module = import_module(module_path)
adapter_class = getattr(adapter_module, adapter_class_name)
if not isinstance(adapter_class, AudioAdapter):
raise ValueError(
raise SpleeterError(
f'{adapter_class_name} is not a valid AudioAdapter class')
return adapter_class()

View File

@@ -16,6 +16,7 @@ import numpy as np
# pylint: enable=import-error
from .adapter import AudioAdapter
from .. import SpleeterError
from ..utils.logging import get_logger
__email__ = 'research@deezer.com'
@@ -54,12 +55,18 @@ class FFMPEGProcessAudioAdapter(AudioAdapter):
:param sample_rate: (Optional) Sample rate to load audio with.
:param dtype: (Optional) Numpy data type to use, default to float32.
:returns: Loaded data a (waveform, sample_rate) tuple.
:raise SpleeterError: If any error occurs while loading audio.
"""
if not isinstance(path, str):
path = path.decode()
probe = ffmpeg.probe(path)
try:
probe = ffmpeg.probe(path)
except ffmpeg._run.Error as e:
raise SpleeterError(
'An error occurs with ffprobe (see ffprobe output below)\n\n{}'
.format(e.stderr.decode()))
if 'streams' not in probe or len(probe['streams']) == 0:
raise IOError('No stream was found with ffprobe')
raise SpleeterError('No stream was found with ffprobe')
metadata = next(
stream
for stream in probe['streams']
@@ -117,5 +124,5 @@ class FFMPEGProcessAudioAdapter(AudioAdapter):
process.stdin.close()
process.wait()
except IOError:
raise IOError(f'FFMPEG error: {process.stderr.read()}')
raise SpleeterError(f'FFMPEG error: {process.stderr.read()}')
get_logger().info('File %s written', path)

View File

@@ -84,7 +84,6 @@ OPT_CODEC = {
# -b opt specification (separate).
OPT_BITRATE = {
'dest': 'bitrate',
'type': int,
'default': '128k',
'help': 'Audio bitrate to be used for the separated output'
}
@@ -177,8 +176,8 @@ def _create_separate_parser(parser_factory):
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_
parser.add_argument('-d', '--duration', **OPT_DURATION)
parser.add_argument('-s', '--offset', **OPT_OFFSET)
parser.add_argument('-c', '--codec', **OPT_CODEC)
parser.add_argument('-b', '--birate', **OPT_BITRATE)
parser.add_argument('-m', '--mwf', **OPT_MWF)

View File

@@ -28,13 +28,13 @@ def entrypoint(arguments, params):
# TODO: check with output naming.
audio_adapter = get_audio_adapter(arguments.audio_adapter)
separator = Separator(arguments.configuration, arguments.MWF)
for filename in arguments.audio_filenames:
for filename in arguments.inputs:
separator.separate_to_file(
filename,
arguments.output_path,
audio_adapter=audio_adapter,
offset=arguments.offset,
duration=arguments.max_duration,
duration=arguments.duration,
codec=arguments.codec,
bitrate=arguments.bitrate,
synchronous=False

View File

@@ -57,7 +57,7 @@ class Separator(object):
self._predictor = to_predictor(estimator)
return self._predictor
def join(self, timeout=20):
def join(self, timeout=200):
""" Wait for all pending tasks to be finished.
:param timeout: (Optional) task waiting timeout.

View File

@@ -13,7 +13,7 @@ except ImportError:
from os.path import exists
from .. import resources
from .. import resources, SpleeterError
__email__ = 'research@deezer.com'
@@ -31,17 +31,17 @@ def load_configuration(descriptor):
:param descriptor: Configuration descriptor to use for lookup.
:returns: Loaded description as dict.
:raise ValueError: If required embedded configuration does not exists.
:raise IOError: If required configuration file does not exists.
:raise SpleeterError: If required configuration file does not exists.
"""
# Embedded configuration reading.
if descriptor.startswith(_EMBEDDED_CONFIGURATION_PREFIX):
name = descriptor[len(_EMBEDDED_CONFIGURATION_PREFIX):]
if not loader.is_resource(resources, f'{name}.json'):
raise ValueError(f'No embedded configuration {name} found')
raise SpleeterError(f'No embedded configuration {name} found')
with loader.open_text(resources, f'{name}.json') as stream:
return json.load(stream)
# Standard file reading.
if not exists(descriptor):
raise IOError(f'Configuration file {descriptor} not found')
raise SpleeterError(f'Configuration file {descriptor} not found')
with open(descriptor, 'r') as stream:
return json.load(stream)

View File

@@ -1,4 +1,8 @@
#!/usr/bin/env python
# coding: utf8
""" TO DOCUMENT """
""" Unit testing package. """
__email__ = 'research@deezer.com'
__author__ = 'Deezer Research'
__license__ = 'MIT License'

View File

@@ -1,10 +0,0 @@
#!/bin/bash
######################################################################
# Script that performs PyPi packaging test.
#
# @author Deezer Research <research@deezer.com>
# @version 1.0.0
######################################################################
twine upload --repository-url https://test.pypi.org/legacy/ dist/*