diff --git a/SpotifyRecorder.py b/SpotifyRecorder.py index 05c44ef134bc2fa4db048bc8c6d9ebed21cf4fdd..99238527a737f76626c2e0b2ae914413b7190080 100644 --- a/SpotifyRecorder.py +++ b/SpotifyRecorder.py @@ -3,6 +3,7 @@ import os.path import time from typing import List, Dict +import click import spotipy from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger from spotipy import SpotifyOAuth, CacheFileHandler @@ -67,7 +68,13 @@ class SpotifyRecorder: LOGGER.info(f'Recording track #{self._startNumber} to (including) #{self._startNumber + self._limit - 1}') tracks = tracks[self._startNumber - 1:self._startNumber - 1 + self._limit] - self.__record_tracks(tracks) + totalDurationInSeconds = sum([track['track']['duration_ms'] // 1000 for track in tracks]) + LOGGER.info(f'Total duration: {self.__convert_seconds_to_duration(totalDurationInSeconds)}') + + if click.confirm('Do you want to start recording?', default=True): + self.__record_tracks(tracks) + else: + LOGGER.warning('Aborted') def __get_playlist(self, username: str, playlistID: str) -> Dict: LOGGER.info(f'Fetching playlist with ID: {playlistID} by {username}...') @@ -84,7 +91,7 @@ class SpotifyRecorder: tracks = self._spotify.next(tracks) results.extend(tracks['items']) - LOGGER.info(f'Found {len(tracks)} tracks in playlist') + LOGGER.info(f'Found {len(results)} tracks in playlist') return results def __record_tracks(self, tracks: list): @@ -107,26 +114,7 @@ class SpotifyRecorder: LOGGER.info(f'>>> Recording track {index + 1}/{len(tracks)}: ' f'#{indexInPlaylist} "{track["track"]["name"]}"...') try: - self.__stop_playback_if_playing(deviceId) - - fileName = self.__determine_file_name(indexInPlaylist, track) - filePathWav = f'{fileName}.wav' - filePathMp3 = f'{fileName}.mp3' - recorder = AudioRecorder(self._audioDeviceName, filePathWav) - with recorder.record(): - self.__play_track(deviceId, track['track']['uri']) - timeWaitedForPlaying = self.__wait_for_track_playing(track['track']['id']) - self.__wait_for_track_end(track, timeWaitedForPlaying) - - Mp3Converter.convert_to_mp3(filePathWav, filePathMp3) - Mp3Converter.set_mp3_tags(filePath=filePathMp3, - title=track['track']['name'], - artist=self.__join_artists(track), - album=track['track']['album']['name']) - - LOGGER.debug(f'\t\tRemoving wav file "{filePathWav}"') - os.remove(filePathWav) - + self.__record_single_track(deviceId, indexInPlaylist, track) recordedTrackNumbers.append(indexInPlaylist) except Exception as e: LOGGER.error(f'An error occurred while recording track "{track["track"]["name"]}"', exc_info=e) @@ -134,7 +122,31 @@ class SpotifyRecorder: self.__print_end_statistics(errorTrackNumbers, recordedTrackNumbers, skippedTrackNumbers, len(tracks)) - def __print_end_statistics(self, errorTrackNumbers: list[int], recordedTrackNumbers: list[int], + def __record_single_track(self, deviceId, indexInPlaylist, track): + self.__stop_playback_if_playing(deviceId) + + fileName = self.__determine_file_name(indexInPlaylist, track) + filePathWav = f'{fileName}.wav' + filePathMp3 = f'{fileName}.mp3' + + recorder = AudioRecorder(self._audioDeviceName, filePathWav) + + with recorder.record(): + self.__play_track(deviceId, track['track']['uri']) + timeWaitedForPlaying = self.__wait_for_track_playing(track['track']['id']) + self.__wait_for_track_end(track, timeWaitedForPlaying) + + Mp3Converter.convert_to_mp3(filePathWav, filePathMp3) + Mp3Converter.set_mp3_tags(filePath=filePathMp3, + title=track['track']['name'], + artist=self.__join_artists(track), + album=track['track']['album']['name']) + + LOGGER.debug(f'\t\tRemoving wav file "{filePathWav}"') + os.remove(filePathWav) + + @staticmethod + def __print_end_statistics(errorTrackNumbers: list[int], recordedTrackNumbers: list[int], skippedTrackNumbers: list[int], numberOfTracks: int): LOGGER.info('### DONE ###') diff --git a/poetry.lock b/poetry.lock index 41b2cc89a8723e740b56adf86a6a811a0fe4885e..a9c5ef1a2607608ef806db3592f7c4788b4b7caa 100644 --- a/poetry.lock +++ b/poetry.lock @@ -121,6 +121,31 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + [[package]] name = "idna" version = "3.6" @@ -352,4 +377,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "bb77de02b25207bf10249bf1370a69682b27ad88452311d42abc7d9830eb5494" +content-hash = "91e52e9622d0f476c5b0352fb8295ee9c4cac6a50a35992cf142b11a7f4a7db9" diff --git a/pyproject.toml b/pyproject.toml index e35ccc96a3a8bbe49969f41db99d93c9de5c50db..dc58f13fa3d41fb655cd0cc41ed0d7f47dbf2e07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ thecodelabs-baseutils = {version = "*", source = "TheCodeLabs" } spotipy = "2.22.0" PyAudioWPatch = "0.2.12.6" mutagen = "1.47.0" +click = "8.1.7" [tool.poetry.dev-dependencies]