mirror of
https://github.com/KevinMidboe/spotify-downloader.git
synced 2025-10-29 18:00:15 +00:00
101 lines
2.8 KiB
Python
101 lines
2.8 KiB
Python
import shutil
|
|
import os
|
|
|
|
from abc import ABC
|
|
from abc import abstractmethod
|
|
|
|
from spotdl.encode.exceptions import EncoderNotFoundError
|
|
|
|
"""
|
|
NOTE ON ENCODERS
|
|
================
|
|
|
|
* A comparision between FFmpeg, avconv, and libav:
|
|
https://stackoverflow.com/questions/9477115
|
|
|
|
* FFmeg encoders sorted in descending order based
|
|
on the quality of audio produced:
|
|
libopus > libvorbis >= libfdk_aac > aac > libmp3lame
|
|
|
|
* libfdk_aac encoder, due to copyrights needs to be compiled
|
|
by end user on MacOS brew install ffmpeg --with-fdk-aac
|
|
will do just that. Other OS? See:
|
|
https://trac.ffmpeg.org/wiki/Encode/AAC
|
|
|
|
"""
|
|
|
|
|
|
class EncoderBase(ABC):
|
|
"""
|
|
Defined encoders must inherit from this abstract base class
|
|
and implement their own functionality for the below defined
|
|
methods.
|
|
"""
|
|
|
|
@abstractmethod
|
|
def __init__(self, encoder_path, loglevel, additional_arguments=[]):
|
|
"""
|
|
This method must make sure whether specified encoder
|
|
is available under PATH.
|
|
"""
|
|
if shutil.which(encoder_path) is None:
|
|
raise EncoderNotFoundError(
|
|
"{} executable does not exist or was not found in PATH.".format(
|
|
encoder_path
|
|
)
|
|
)
|
|
self.encoder_path = encoder_path
|
|
self._loglevel = loglevel
|
|
self._additional_arguments = additional_arguments
|
|
|
|
@abstractmethod
|
|
def set_argument(self, argument):
|
|
"""
|
|
This method must be used to set any custom functionality
|
|
for the encoder by passing arguments to it.
|
|
"""
|
|
self._additional_arguments += argument.split()
|
|
|
|
@abstractmethod
|
|
def get_encoding(self, filename):
|
|
"""
|
|
This method must determine the encoding for a local
|
|
audio file. Such as "mp3", "wav", "m4a", etc.
|
|
"""
|
|
_, extension = os.path.splitext(filename)
|
|
# Ignore the initial dot from file extension
|
|
return extension[1:]
|
|
|
|
@abstractmethod
|
|
def set_debuglog(self):
|
|
"""
|
|
This method must enable verbose logging in the defined
|
|
encoder.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def _generate_encode_command(self, input_file, output_file):
|
|
"""
|
|
This method must the complete command for that would be
|
|
used to invoke the encoder and perform the encoding.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def _generate_encoding_arguments(self, input_encoding, output_encoding):
|
|
"""
|
|
This method must return the core arguments for the defined
|
|
encoder such as defining the sample rate, audio bitrate,
|
|
etc.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def re_encode(self, input_file, output_file):
|
|
"""
|
|
This method must invoke FFmpeg to encode a given input
|
|
file to a specified output file.
|
|
"""
|
|
pass
|