Files
spotify-downloader/spotdl/track.py
2020-04-12 17:09:15 +05:30

88 lines
2.8 KiB
Python

import tqdm
import urllib.request
import subprocess
from spotdl.encode.encoders import EncoderFFmpeg
from spotdl.metadata.embedders import EmbedderDefault
import spotdl.util
CHUNK_SIZE= 16 * 1024
class Track:
def __init__(self, metadata, cache_albumart=False):
self.metadata = metadata
self._chunksize = CHUNK_SIZE
if cache_albumart:
self._albumart_thread = self._cache_albumart()
self._cache_albumart = cache_albumart
def _cache_albumart(self):
albumart_thread = spotdl.util.ThreadWithReturnValue(
target=lambda url: urllib.request.urlopen(url).read(),
args=(self.metadata["album"]["images"][0]["url"],)
)
albumart_thread.start()
return albumart_thread
def _calculate_total_chunks(self, filesize):
return (filesize // self._chunksize) + 1
def download_while_re_encoding(self, stream, target_path, target_encoding=None,
encoder=EncoderFFmpeg(), 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"]
for _ in tqdm.trange(total_chunks):
chunk = response.read(self._chunksize)
process.stdin.write(chunk)
process.stdin.close()
process.wait()
def download(self, stream, target_path, show_progress=True):
total_chunks = self._calculate_total_chunks(stream["filesize"])
response = stream["connection"]
with open(target_path, "wb") as fout:
for _ in tqdm.trange(total_chunks):
chunk = response.read(self._chunksize)
fout.write(chunk)
def re_encode(self, input_path, target_path, target_encoding=None,
encoder=EncoderFFmpeg(), 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 apply_metadata(self, input_path, encoding=None, embedder=EmbedderDefault()):
if self._cache_albumart:
albumart = self._albumart_thread.join()
else:
albumart = None
embedder.apply_metadata(
input_path,
self.metadata,
cached_albumart=albumart,
encoding=encoding,
)