Nuke avconv

This commit is contained in:
Ritiek Malhotra
2020-05-10 04:44:31 +05:30
parent 4abdecf9ec
commit 083af5b802
8 changed files with 33 additions and 139 deletions

View File

@@ -109,11 +109,10 @@ def get_arguments(argv=None, base_config_file=spotdl.config.default_config_file)
action="store_true", action="store_true",
) )
parser.add_argument( parser.add_argument(
"-e", "--no-encode",
"--encoder", default=config["no-encode"],
default=config["encoder"], action="store_true",
choices={"ffmpeg", "avconv", "null"}, help="do not encode media using FFmpeg",
help="use this encoder for conversion",
) )
parser.add_argument( parser.add_argument(
"--overwrite", "--overwrite",
@@ -282,9 +281,6 @@ class Arguments:
if self.parsed.write_m3u and not self.parsed.list: if self.parsed.write_m3u and not self.parsed.list:
self.parser.error("--write-m3u can only be used with --list") self.parser.error("--write-m3u can only be used with --list")
if self.parsed.trim_silence and not "ffmpeg" in self.parsed.encoder:
self.parser.error("--trim-silence can only be used with FFmpeg")
if self.parsed.write_to and not ( if self.parsed.write_to and not (
self.parsed.playlist or self.parsed.album or self.parsed.all_albums or self.parsed.username self.parsed.playlist or self.parsed.album or self.parsed.all_albums or self.parsed.username
): ):
@@ -292,18 +288,10 @@ class Arguments:
"--write-to can only be used with --playlist, --album, --all-albums, or --username" "--write-to can only be used with --playlist, --album, --all-albums, or --username"
) )
encoder_exists = shutil.which(self.parsed.encoder) ffmpeg_exists = shutil.which("ffmpeg")
if not self.parsed.encoder == "null" and not encoder_exists: if not ffmpeg_exists:
logger.warn('Specified encoder "{}" was not found in PATH.') logger.warn("FFmpeg was not found in PATH. Will not re-encode media to specified output format.")
self.parsed.encoder = "null"
if self.parsed.encoder == "null":
self.parsed.output_ext = self.parsed.input_ext self.parsed.output_ext = self.parsed.input_ext
logger.warn(
"Encoder is null. Will not re-encode to specified output format.".format(
self.parsed.encoder
)
)
if self.parsed.output_file == "-" and self.parsed.no_metadata is False: if self.parsed.output_file == "-" and self.parsed.no_metadata is False:
logger.warn( logger.warn(
@@ -317,8 +305,9 @@ class Arguments:
self.parser.get_default("output_file") self.parser.get_default("output_file")
) )
logger.warn( logger.warn(
"Given output file is a directory. Will download tracks in this directory with " "Given output file is a directory. Will download tracks "
"their filename as per the default file format. Pass '--output-file=\"{}\"' to hide this " "in this directory with their filename as per the default "
"file format. Pass '--output-file=\"{}\"' to hide this "
"warning.".format( "warning.".format(
adjusted_output_file adjusted_output_file
) )

View File

@@ -5,9 +5,6 @@ from spotdl.metadata.embedders import EmbedderDefault
from spotdl.metadata.exceptions import SpotifyMetadataNotFoundError from spotdl.metadata.exceptions import SpotifyMetadataNotFoundError
import spotdl.metadata import spotdl.metadata
from spotdl.encode.encoders import EncoderFFmpeg
from spotdl.encode.encoders import EncoderAvconv
from spotdl.lyrics.providers import LyricWikia from spotdl.lyrics.providers import LyricWikia
from spotdl.lyrics.providers import Genius from spotdl.lyrics.providers import Genius
from spotdl.lyrics.exceptions import LyricsNotFoundError from spotdl.lyrics.exceptions import LyricsNotFoundError
@@ -171,11 +168,11 @@ class Spotdl:
else: else:
self.download_track_from_metadata(metadata) self.download_track_from_metadata(metadata)
def should_we_overwrite_existing_file(self): def should_we_overwrite_existing_file(self, overwrite):
if self.arguments["overwrite"] == "force": if overwrite == "force":
logger.info("Forcing overwrite on existing file.") logger.info("Forcing overwrite on existing file.")
to_overwrite = True to_overwrite = True
elif self.arguments["overwrite"] == "prompt": elif overwrite == "prompt":
to_overwrite = input("Overwrite? (y/N): ").lower() == "y" to_overwrite = input("Overwrite? (y/N): ").lower() == "y"
else: else:
logger.info("Not overwriting existing file.") logger.info("Not overwriting existing file.")
@@ -190,12 +187,7 @@ class Spotdl:
preftype=self.arguments["input_ext"], preftype=self.arguments["input_ext"],
) )
Encoder = { if self.arguments["no_encode"]:
"ffmpeg": EncoderFFmpeg,
"avconv": EncoderAvconv,
}.get(self.arguments["encoder"])
if Encoder is None:
output_extension = stream["encoding"] output_extension = stream["encoding"]
else: else:
output_extension = self.arguments["output_ext"] output_extension = self.arguments["output_ext"]
@@ -220,7 +212,7 @@ class Spotdl:
filename=filename filename=filename
)) ))
to_skip_download = to_skip_download \ to_skip_download = to_skip_download \
or not self.should_we_overwrite_existing_file() or not self.should_we_overwrite_existing_file(self.arguments["overwrite"])
if to_skip_download: if to_skip_download:
logger.debug("Skip track download.") logger.debug("Skip track download.")
@@ -230,14 +222,13 @@ class Spotdl:
metadata["lyrics"].start() metadata["lyrics"].start()
logger.info('Downloading to "{filename}"'.format(filename=filename)) logger.info('Downloading to "{filename}"'.format(filename=filename))
if Encoder is None: if self.arguments["no_encode"]:
track.download(stream, temp_filename) track.download(stream, temp_filename)
else: else:
track.download_while_re_encoding( track.download_while_re_encoding(
stream, stream,
temp_filename, temp_filename,
target_encoding=output_extension, target_encoding=output_extension,
encoder=Encoder()
) )
if not self.arguments["no_metadata"]: if not self.arguments["no_metadata"]:

View File

@@ -11,7 +11,7 @@ DEFAULT_CONFIGURATION = {
"manual": False, "manual": False,
"no_metadata": False, "no_metadata": False,
"no_fallback_metadata": False, "no_fallback_metadata": False,
"encoder": "ffmpeg", "no-encode": False,
"overwrite": "prompt", "overwrite": "prompt",
"quality": "best", "quality": "best",
"input_ext": "automatic", "input_ext": "automatic",

View File

@@ -10,9 +10,6 @@ from spotdl.encode.exceptions import EncoderNotFoundError
NOTE ON ENCODERS NOTE ON ENCODERS
================ ================
* A comparision between FFmpeg, avconv, and libav:
https://stackoverflow.com/questions/9477115
* FFmeg encoders sorted in descending order based * FFmeg encoders sorted in descending order based
on the quality of audio produced: on the quality of audio produced:
libopus > libvorbis >= libfdk_aac > aac > libmp3lame libopus > libvorbis >= libfdk_aac > aac > libmp3lame

View File

@@ -1,4 +1 @@
from spotdl.encode.encoders.ffmpeg import EncoderFFmpeg from spotdl.encode.encoders.ffmpeg import EncoderFFmpeg
from spotdl.encode.encoders.avconv import EncoderAvconv
EncodeClasses = (EncoderFFmpeg, EncoderAvconv)

View File

@@ -1,87 +0,0 @@
import subprocess
import os
import logging
logger = logging.getLogger(__name__)
from spotdl.encode import EncoderBase
from spotdl.encode.exceptions import EncoderNotFoundError
from spotdl.encode.exceptions import AvconvNotFoundError
class EncoderAvconv(EncoderBase):
def __init__(self, encoder_path="avconv"):
logger.warn(
"Using EncoderAvconv is deprecated and will be removed",
"in future versions. Use EncoderFFmpeg instead."
)
encoder_path = encoder_path
_loglevel = "-loglevel 0"
_additional_arguments = ["-ab", "192k"]
try:
super().__init__(encoder_path, _loglevel, _additional_arguments)
except EncoderNotFoundError as e:
raise AvconvNotFoundError(e.args[0])
def set_argument(self, argument):
super().set_argument(argument)
def get_encoding(self, filename):
return super().get_encoding(filename)
def _generate_encoding_arguments(self, input_encoding, target_encoding):
initial_arguments = self._rules.get(input_encoding)
if initial_arguments is None:
raise TypeError(
'The input format ("{}") is not supported.'.format(
input_extension,
)
)
arguments = initial_arguments.get(target_encoding)
if arguments is None:
raise TypeError(
'The output format ("{}") is not supported.'.format(
output_extension,
)
)
return arguments
def _generate_encoding_arguments(self, input_encoding, target_encoding):
return ""
def set_debuglog(self):
self._loglevel = "-loglevel debug"
def _generate_encode_command(self, input_file, target_file):
input_encoding = self.get_encoding(input_file)
target_encoding = self.get_encoding(target_file)
arguments = self._generate_encoding_arguments(
input_encoding,
target_encoding
)
command = [self.encoder_path] \
+ ["-y"] \
+ self._loglevel.split() \
+ ["-i", input_file] \
+ self._additional_arguments \
+ [target_file]
return command
def re_encode(self, input_file, target_file, delete_original=False):
encode_command = self._generate_encode_command(
input_file,
target_file
)
returncode = subprocess.call(encode_command)
encode_successful = returncode == 0
if encode_successful and delete_original:
os.remove(input_file)
return returncode

View File

@@ -60,12 +60,12 @@ class EncoderFFmpeg(EncoderBase):
def set_debuglog(self): def set_debuglog(self):
self._loglevel = "-loglevel debug" self._loglevel = "-loglevel debug"
def _generate_encode_command(self, input_path, target_path, def _generate_encode_command(self, input_path, target_file,
input_encoding=None, target_encoding=None): input_encoding=None, target_encoding=None):
if input_encoding is None: if input_encoding is None:
input_encoding = self.get_encoding(input_path) input_encoding = self.get_encoding(input_path)
if target_encoding is None: if target_encoding is None:
target_encoding = self.get_encoding(target_path) target_encoding = self.get_encoding(target_file)
arguments = self._generate_encoding_arguments( arguments = self._generate_encoding_arguments(
input_encoding, input_encoding,
target_encoding target_encoding
@@ -77,14 +77,14 @@ class EncoderFFmpeg(EncoderBase):
+ arguments.split() \ + arguments.split() \
+ self._additional_arguments \ + self._additional_arguments \
+ ["-f", target_encoding] \ + ["-f", target_encoding] \
+ [target_path] + [target_file]
return command return command
def re_encode(self, input_path, target_path, target_encoding=None, delete_original=False): def re_encode(self, input_path, target_file, target_encoding=None, delete_original=False):
encode_command = self._generate_encode_command( encode_command = self._generate_encode_command(
input_path, input_path,
target_path, target_file,
target_encoding=target_encoding target_encoding=target_encoding
) )
logger.debug("Calling FFmpeg with:\n{command}".format( logger.debug("Calling FFmpeg with:\n{command}".format(
@@ -97,10 +97,10 @@ class EncoderFFmpeg(EncoderBase):
os.remove(input_path) os.remove(input_path)
return process return process
def re_encode_from_stdin(self, input_encoding, target_path, target_encoding=None): def re_encode_from_stdin(self, input_encoding, target_file, target_encoding=None):
encode_command = self._generate_encode_command( encode_command = self._generate_encode_command(
"-", "-",
target_path, target_file,
input_encoding=input_encoding, input_encoding=input_encoding,
target_encoding=target_encoding, target_encoding=target_encoding,
) )

View File

@@ -2,6 +2,7 @@ import tqdm
import urllib.request import urllib.request
import subprocess import subprocess
import sys
from spotdl.encode.encoders import EncoderFFmpeg from spotdl.encode.encoders import EncoderFFmpeg
from spotdl.metadata.embedders import EmbedderDefault from spotdl.metadata.embedders import EmbedderDefault
@@ -64,10 +65,16 @@ class Track:
total_chunks = self.calculate_total_chunks(stream["filesize"]) total_chunks = self.calculate_total_chunks(stream["filesize"])
progress_bar = self.make_progress_bar(total_chunks) progress_bar = self.make_progress_bar(total_chunks)
response = stream["connection"] response = stream["connection"]
with open(target_path, "wb") as fout: if target_path == "-":
# Target is STDOUT
for _ in progress_bar: for _ in progress_bar:
chunk = response.read(self._chunksize) chunk = response.read(self._chunksize)
fout.write(chunk) sys.stdout.buffer.write(chunk)
else:
with open(target_path, "wb") as fout:
for _ in progress_bar:
chunk = response.read(self._chunksize)
fout.write(chunk)
def re_encode(self, input_path, target_path, target_encoding=None, def re_encode(self, input_path, target_path, target_encoding=None,
encoder=EncoderFFmpeg(), show_progress=True): encoder=EncoderFFmpeg(), show_progress=True):