mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 9795d7e9b8 | ||
|  | bbe43da191 | ||
|  | 8b7fd04321 | ||
|  | cd5f224e37 | ||
|  | 675d1805ed | 
							
								
								
									
										13
									
								
								CHANGES.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CHANGES.md
									
									
									
									
									
								
							| @@ -8,6 +8,14 @@ The release dates mentioned follow the format `DD-MM-YYYY`. | |||||||
|  |  | ||||||
| ## [Unreleased] | ## [Unreleased] | ||||||
|  |  | ||||||
|  | ## [2.0.2] (Hotfix Release) - 18-05-2020 | ||||||
|  | ### Fixed | ||||||
|  | - Skipping tracks with `-m` would crash. | ||||||
|  |  | ||||||
|  | ## [2.0.1] (Hotfix Release) - 18-05-2020 | ||||||
|  | ### Fixed | ||||||
|  | - `-o m4a` would always fail. | ||||||
|  |  | ||||||
| ## [2.0.0] - 18-05-2020 | ## [2.0.0] - 18-05-2020 | ||||||
| ### Migrating from v1.2.6 to v2.0.0 | ### Migrating from v1.2.6 to v2.0.0 | ||||||
| For v2.0.0 to work correctly, you need to remove your previous `config.yml` due to | For v2.0.0 to work correctly, you need to remove your previous `config.yml` due to | ||||||
| @@ -45,15 +53,14 @@ All the below changes were made as a part of #690. | |||||||
|   Such as `-o .mp3` is now written as `-o mp3`. |   Such as `-o .mp3` is now written as `-o mp3`. | ||||||
| - **[Breaking]** Search format now uses hyphen for word break instead of underscore. Such as | - **[Breaking]** Search format now uses hyphen for word break instead of underscore. Such as | ||||||
|   `-sf "{artist} - {track_name}"` is now written as `-sf "{artist} - {track-name}"`. |   `-sf "{artist} - {track_name}"` is now written as `-sf "{artist} - {track-name}"`. | ||||||
| - **[Breaking]** `--write-sucessful` and `--skip` is renamed to `--write-succesful-file` and | - **[Breaking]** `--write-successful` and `--skip` is renamed to `--write-successful-file` and | ||||||
|   `--skip-file` respectively. |   `--skip-file` respectively. | ||||||
|   Such as `-o .mp3` is now written as `-o mp3`. |  | ||||||
| - Partial re-write and internal API refactor. | - Partial re-write and internal API refactor. | ||||||
| - Enhance debug log output readability. | - Enhance debug log output readability. | ||||||
| - Internally adapt to latest changes made in Spotipy library. | - Internally adapt to latest changes made in Spotipy library. | ||||||
| - Switch to `logging` + `coloredlogs` instead of `logzero`. Our loggers weren't being | - Switch to `logging` + `coloredlogs` instead of `logzero`. Our loggers weren't being | ||||||
|   setup properly with `logzero`. |   setup properly with `logzero`. | ||||||
| - Simplify checking for an already track. Previously it also analyzed metadata | - Simplify checking for an downloaded already track. Previously it also analyzed metadata | ||||||
|   for the already downloaded track to determine whether to overwrite the already downloaded |   for the already downloaded track to determine whether to overwrite the already downloaded | ||||||
|   track, which caused unexpected behvaiours at times. |   track, which caused unexpected behvaiours at times. | ||||||
| - Codebase is now more modular making it easier to use spotdl in python scripts. | - Codebase is now more modular making it easier to use spotdl in python scripts. | ||||||
|   | |||||||
| @@ -224,6 +224,11 @@ class Spotdl: | |||||||
|             quality=self.arguments["quality"], |             quality=self.arguments["quality"], | ||||||
|             preftype=self.arguments["input_ext"], |             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"]: |         if self.arguments["no_encode"]: | ||||||
|             output_extension = stream["encoding"] |             output_extension = stream["encoding"] | ||||||
|   | |||||||
| @@ -21,6 +21,13 @@ from spotdl.encode.exceptions import EncoderNotFoundError | |||||||
|  |  | ||||||
| """ | """ | ||||||
|  |  | ||||||
|  | _TARGET_FORMATS_FROM_ENCODING = { | ||||||
|  |     "m4a": "mp4", | ||||||
|  |     "mp3": "mp3", | ||||||
|  |     "opus": "opus", | ||||||
|  |     "flac": "flac" | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| class EncoderBase(ABC): | class EncoderBase(ABC): | ||||||
|     """ |     """ | ||||||
| @@ -44,6 +51,7 @@ class EncoderBase(ABC): | |||||||
|         self.encoder_path = encoder_path |         self.encoder_path = encoder_path | ||||||
|         self._loglevel = loglevel |         self._loglevel = loglevel | ||||||
|         self._additional_arguments = additional_arguments |         self._additional_arguments = additional_arguments | ||||||
|  |         self._target_formats_from_encoding = _TARGET_FORMATS_FROM_ENCODING | ||||||
|  |  | ||||||
|     def set_argument(self, argument): |     def set_argument(self, argument): | ||||||
|         """ |         """ | ||||||
| @@ -94,6 +102,14 @@ class EncoderBase(ABC): | |||||||
|         """ |         """ | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|  |     def target_format_from_encoding(self, encoding): | ||||||
|  |         """ | ||||||
|  |         This method generates the target stream format from given | ||||||
|  |         input encoding. | ||||||
|  |         """ | ||||||
|  |         target_format = self._target_formats_from_encoding[encoding] | ||||||
|  |         return target_format | ||||||
|  |  | ||||||
|     def re_encode_from_stdin(self, input_encoding, target_path): |     def re_encode_from_stdin(self, input_encoding, target_path): | ||||||
|         """ |         """ | ||||||
|         This method must invoke the encoder to encode stdin to a |         This method must invoke the encoder to encode stdin to a | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ class EncoderFFmpeg(EncoderBase): | |||||||
|             + ["-i", input_path] \ |             + ["-i", input_path] \ | ||||||
|             + arguments.split() \ |             + arguments.split() \ | ||||||
|             + self._additional_arguments \ |             + self._additional_arguments \ | ||||||
|             + ["-f", target_encoding] \ |             + ["-f", self.target_format_from_encoding(target_encoding)] \ | ||||||
|             + [target_file] |             + [target_file] | ||||||
|  |  | ||||||
|         return command |         return command | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ class TestEncodingDefaults: | |||||||
|             '-acodec', 'copy', |             '-acodec', 'copy', | ||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-f', 'm4a', |             '-f', 'mp4', | ||||||
|              target_path |              target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
| @@ -112,7 +112,7 @@ class TestEncodingInDebugMode: | |||||||
|             '-acodec', 'copy', |             '-acodec', 'copy', | ||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-f', 'm4a', |             '-f', 'mp4', | ||||||
|              target_path |              target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
| @@ -180,7 +180,7 @@ class TestEncodingAndTrimSilence: | |||||||
|             '-b:a', '192k', |             '-b:a', '192k', | ||||||
|             '-vn', |             '-vn', | ||||||
|             '-af', 'silenceremove=start_periods=1', |             '-af', 'silenceremove=start_periods=1', | ||||||
|             '-f', 'm4a', |             '-f', 'mp4', | ||||||
|             target_path |             target_path | ||||||
|         ] |         ] | ||||||
|         return command |         return command | ||||||
|   | |||||||
| @@ -86,3 +86,12 @@ class TestMethods: | |||||||
|     def test_encoder_not_found_error(self): |     def test_encoder_not_found_error(self): | ||||||
|         with pytest.raises(EncoderNotFoundError): |         with pytest.raises(EncoderNotFoundError): | ||||||
|             self.EncoderKid("/a/nonexistent/path", "0", []) |             self.EncoderKid("/a/nonexistent/path", "0", []) | ||||||
|  |  | ||||||
|  |     @pytest.mark.parametrize("encoding, target_format", [ | ||||||
|  |         ("m4a", "mp4"), | ||||||
|  |         ("mp3", "mp3"), | ||||||
|  |         ("opus", "opus"), | ||||||
|  |         ("flac", "flac"), | ||||||
|  |     ]) | ||||||
|  |     def test_target_format_from_encoding(self, encoderkid, encoding, target_format): | ||||||
|  |         assert encoderkid.target_format_from_encoding(encoding) == target_format | ||||||
|   | |||||||
| @@ -138,6 +138,7 @@ class YouTubeStreams(StreamsBase): | |||||||
|         self.all = [] |         self.all = [] | ||||||
|  |  | ||||||
|         for stream in audiostreams: |         for stream in audiostreams: | ||||||
|  |             encoding = "m4a" if "mp4a" in stream.audio_codec else stream.audio_codec | ||||||
|             standard_stream = { |             standard_stream = { | ||||||
|                 # Store only the integer part for bitrate. For example |                 # Store only the integer part for bitrate. For example | ||||||
|                 # the given bitrate would be "192kbps", we store only |                 # the given bitrate would be "192kbps", we store only | ||||||
| @@ -145,7 +146,7 @@ class YouTubeStreams(StreamsBase): | |||||||
|                 "bitrate": int(stream.abr[:-4]), |                 "bitrate": int(stream.abr[:-4]), | ||||||
|                 "connection": None, |                 "connection": None, | ||||||
|                 "download_url": stream.url, |                 "download_url": stream.url, | ||||||
|                 "encoding": stream.audio_codec, |                 "encoding": encoding, | ||||||
|                 "filesize": None, |                 "filesize": None, | ||||||
|             } |             } | ||||||
|             establish_connection = threading.Thread( |             establish_connection = threading.Thread( | ||||||
|   | |||||||
| @@ -163,7 +163,7 @@ class MetadataSearch: | |||||||
|         if video is None: |         if video is None: | ||||||
|             raise NoYouTubeVideoMatchError( |             raise NoYouTubeVideoMatchError( | ||||||
|                 'No matching videos found on YouTube for the search query "{}".'.format( |                 'No matching videos found on YouTube for the search query "{}".'.format( | ||||||
|                     search_query |                     query | ||||||
|                 ) |                 ) | ||||||
|             ) |             ) | ||||||
|         return video |         return video | ||||||
|   | |||||||
| @@ -1,2 +1,2 @@ | |||||||
| __version__ = "2.0.0" | __version__ = "2.0.2" | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user