def re_encode(self, input_path, target_path, target_encoding=None, encoder=EncoderFFmpeg(must_exist=False), show_progress=True): stream = self.metadata["streams"].getbest() total_chunks = self.calculate_total_chunks(stream["filesize"]) process = encoder.re_encode_from_stdin( stream["encoding"], target_path, target_encoding=target_encoding ) with open(input_path, "rb") as fin: for _ in tqdm.trange(total_chunks): chunk = fin.read(self._chunksize) process.stdin.write(chunk) process.stdin.close() process.wait()
def download_while_re_encoding(self, stream, target_path, target_encoding=None, encoder=EncoderFFmpeg(must_exist=False), show_progress=True): total_chunks = self.calculate_total_chunks(stream["filesize"]) process = encoder.re_encode_from_stdin( stream["encoding"], target_path, target_encoding=target_encoding ) response = stream["connection"] progress_bar = self.make_progress_bar(total_chunks) for _ in progress_bar: chunk = response.read(self._chunksize) process.stdin.write(chunk) process.stdin.close() process.wait()
def download_while_re_encoding(self, stream, target_path, target_encoding=None, encoder=EncoderFFmpeg(must_exist=False), show_progress=True): """ Downloads a stream while simuntaneously encoding it to a given target format. Parameters ---------- stream: `dict` A `dict` containing stream information in the keys: `encoding`, `filesize`, `connection`. target_path: `str` Path to file to write the target stream to. target_encoding: `str`, `None` Specify a target encoding. If ``None``, the target encoding is automatically determined from the ``target_path``. encoder: :class:`spotdl.encode.EncoderBase` object A :class:`spotdl.encode.EncoderBase` object to use for encoding. show_progress: `bool` Whether or not to display a progress bar. """ total_chunks = self._calculate_total_chunks(stream["filesize"]) process = encoder.re_encode_from_stdin(stream["encoding"], target_path, target_encoding=target_encoding) response = stream["connection"] progress_bar = self._make_progress_bar(total_chunks) for _ in progress_bar: chunk = response.read(self._chunksize) process.stdin.write(chunk) process.stdin.close() process.wait()
def re_encode(self, input_path, target_path, target_encoding=None, encoder=EncoderFFmpeg(must_exist=False), show_progress=True): """ Encodes an already downloaded stream. Parameters ---------- input_path: `str` Path to input file. target_path: `str` Path to target file. target_encoding: `str` Encoding to encode the input file to. If ``None``, the target encoding is determined from ``target_path``. encoder: :class:`spotdl.encode.EncoderBase` object A :class:`spotdl.encode.EncoderBase` object to use for encoding. show_progress: `bool` Whether or not to display a progress bar. """ stream = self.metadata["streams"].getbest() total_chunks = self._calculate_total_chunks(stream["filesize"]) process = encoder.re_encode_from_stdin(stream["encoding"], target_path, target_encoding=target_encoding) with open(input_path, "rb") as fin: for _ in tqdm.trange(total_chunks): chunk = fin.read(self._chunksize) process.stdin.write(chunk) process.stdin.close() process.wait()
def download_track_from_metadata(self, metadata): track = Track(metadata, cache_albumart=(not self.arguments["no_metadata"])) stream = metadata["streams"].get( quality=self.arguments["quality"], preftype=self.arguments["input_ext"], ) if stream is None: logger.error('No matching streams found for given input format: "{}".'.format( self.arguments["input_ext"] )) return if self.arguments["no_encode"]: output_extension = stream["encoding"] else: output_extension = self.arguments["output_ext"] filename = spotdl.metadata.format_string( self.arguments["output_file"], metadata, output_extension=output_extension, sanitizer=lambda s: spotdl.util.sanitize( s, spaces_to_underscores=self.arguments["no_spaces"] ) ) download_to_stdout = filename == "-" temp_filename = self.generate_temp_filename(filename, for_stdout=download_to_stdout) to_skip_download = self.arguments["dry_run"] if os.path.isfile(filename): logger.info('A file with name "{filename}" already exists.'.format( filename=filename )) to_skip_download = to_skip_download \ or not self.should_we_overwrite_existing_file(self.arguments["overwrite"]) if to_skip_download: logger.debug("Skip track download.") return if not self.arguments["no_metadata"]: metadata["lyrics"].start() os.makedirs(os.path.dirname(filename) or ".", exist_ok=True) logger.info('Downloading to "{filename}"'.format(filename=filename)) if self.arguments["no_encode"]: track.download(stream, temp_filename) else: encoder = EncoderFFmpeg() if self.arguments["trim_silence"]: encoder.set_trim_silence() track.download_while_re_encoding( stream, temp_filename, target_encoding=output_extension, encoder=encoder, ) if not self.arguments["no_metadata"]: track.metadata["lyrics"] = track.metadata["lyrics"].join() self.apply_metadata(track, temp_filename, output_extension) if not download_to_stdout: logger.debug("Renaming {temp_filename} to {filename}.".format( temp_filename=temp_filename, filename=filename )) os.rename(temp_filename, filename) return filename
def test_generate_encode_command(self, files, expected_command): encoder = EncoderFFmpeg() assert encoder._generate_encode_command(*files) == expected_command
def test_generate_encode_command_and_trim_silence(self, files, expected_command): encoder = EncoderFFmpeg() encoder.set_trim_silence() assert encoder._generate_encode_command(*files) == expected_command
def test_ffmpeg_not_found_error(self): with pytest.raises(FFmpegNotFoundError): EncoderFFmpeg(encoder_path="/a/nonexistent/path")
def test_generate_encode_command_with_debug(self, files, expected_command): encoder = EncoderFFmpeg() encoder.set_debuglog() assert encoder._generate_encode_command(*files) == expected_command