diff --git a/zspotify/track.py b/zspotify/track.py index 8f4ef9de..e40c0a8d 100644 --- a/zspotify/track.py +++ b/zspotify/track.py @@ -1,3 +1,4 @@ +import math import os import re import time @@ -12,7 +13,7 @@ from const import TRACKS, ALBUM, NAME, ITEMS, DISC_NUMBER, TRACK_NUMBER, IS_PLAY RELEASE_DATE, ID, TRACKS_URL, SAVED_TRACKS_URL, TRACK_STATS_URL, CODEC_MAP, EXT_MAP, DURATION_MS from termoutput import Printer, PrintChannel from utils import fix_filename, set_audio_tags, set_music_thumbnail, create_download_directory, \ - get_directory_song_ids, add_to_directory_song_ids, get_previously_downloaded, add_to_archive + get_directory_song_ids, add_to_directory_song_ids, get_previously_downloaded, add_to_archive, fmt_seconds from zspotify import ZSpotify @@ -133,6 +134,8 @@ def download_track(mode: str, track_id: str, extra_keys={}, disable_progressbar= create_download_directory(filedir) total_size = stream.input_stream.size + time_start = time.time() + downloaded = 0 with open(filename, 'wb') as file, Printer.progress( desc=song_name, total=total_size, @@ -141,18 +144,25 @@ def download_track(mode: str, track_id: str, extra_keys={}, disable_progressbar= unit_divisor=1024, disable=disable_progressbar ) as p_bar: - pause = duration_ms / ZSpotify.CONFIG.get_chunk_size() for chunk in range(int(total_size / ZSpotify.CONFIG.get_chunk_size()) + 1): data = stream.input_stream.stream().read(ZSpotify.CONFIG.get_chunk_size()) p_bar.update(file.write(data)) + downloaded += len(data) if ZSpotify.CONFIG.get_download_real_time(): - time.sleep(pause) + delta_real = time.time() - time_start + delta_want = (downloaded / total_size) * (duration_ms/1000) + if delta_want > delta_real: + time.sleep(delta_want - delta_real) + + time_downloaded = time.time() convert_audio_format(filename) set_audio_tags(filename, artists, name, album_name, release_year, disc_number, track_number) set_music_thumbnail(filename, image_url) - Printer.print(PrintChannel.DOWNLOADS, f'### Downloaded "{song_name}" to "{os.path.relpath(filename, os.path.dirname(__file__))}" ###' + "\n") + time_finished = time.time() + + Printer.print(PrintChannel.DOWNLOADS, f'### Downloaded "{song_name}" to "{os.path.relpath(filename, os.path.dirname(__file__))}" in {fmt_seconds(time_downloaded - time_start)} (plus {fmt_seconds(time_finished - time_downloaded)} converting) ###' + "\n") # add song id to archive file if ZSpotify.CONFIG.get_skip_previously_downloaded(): diff --git a/zspotify/utils.py b/zspotify/utils.py index c7da4c39..e421b339 100644 --- a/zspotify/utils.py +++ b/zspotify/utils.py @@ -1,4 +1,5 @@ import datetime +import math import os import platform import re @@ -30,6 +31,7 @@ def create_download_directory(download_path: str) -> None: with open(hidden_file_path, 'w', encoding='utf-8') as f: pass + def get_previously_downloaded() -> List[str]: """ Returns list of all time downloaded songs """ @@ -42,6 +44,7 @@ def get_previously_downloaded() -> List[str]: return ids + def add_to_archive(song_id: str, filename: str, author_name: str, song_name: str) -> None: """ Adds song id to all time installed songs archive """ @@ -54,6 +57,7 @@ def add_to_archive(song_id: str, filename: str, author_name: str, song_name: str with open(archive_path, 'w', encoding='utf-8') as file: file.write(f'{song_id}\t{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\t{author_name}\t{song_name}\t{filename}\n') + def get_directory_song_ids(download_path: str) -> List[str]: """ Gets song ids of songs in directory """ @@ -66,6 +70,7 @@ def get_directory_song_ids(download_path: str) -> List[str]: return song_ids + def add_to_directory_song_ids(download_path: str, song_id: str, filename: str, author_name: str, song_name: str) -> None: """ Appends song_id to .song_ids file in directory """ @@ -75,6 +80,7 @@ def add_to_directory_song_ids(download_path: str, song_id: str, filename: str, a with open(hidden_file_path, 'a', encoding='utf-8') as file: file.write(f'{song_id}\t{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\t{author_name}\t{song_name}\t{filename}\n') + def get_downloaded_song_duration(filename: str) -> float: """ Returns the downloaded file's duration in seconds """ @@ -251,3 +257,26 @@ def fix_filename(name): True """ return re.sub(r'[/\\:|<>"?*\0-\x1f]|^(AUX|COM[1-9]|CON|LPT[1-9]|NUL|PRN)(?![^.])|^\s|[\s.]$', "_", str(name), flags=re.IGNORECASE) + + +def fmt_seconds(secs: float) -> str: + val = math.floor(secs) + + s = math.floor(val % 60) + val -= s + val /= 60 + + m = math.floor(val % 60) + val -= m + val /= 60 + + h = math.floor(val) + + if h == 0 and m == 0 and s == 0: + return "0" + elif h == 0 and m == 0: + return f'{s}'.zfill(2) + elif h == 0: + return f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2) + else: + return f'{h}'.zfill(2) + ':' + f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2)