# Spotube
<div align="center">
[![PyPi](https://img.shields.io/badge/-PyPi-blue.svg?logo=pypi&labelColor=555555&style=for-the-badge)](https://pypi.org/project/spotube "PyPi")
![PyPI - Downloads](https://img.shields.io/pypi/dm/spotube?color=%230f80c0&style=for-the-badge)
![Sonar Logo](https://img.shields.io/badge/Sonar%20cloud-F3702A?style=for-the-badge&logo=sonarcloud&logoColor=white)
![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/GiorgosNik_spotube-package?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)
![Sonar Coverage](https://img.shields.io/sonar/coverage/GiorgosNik_spotube-package?label=COVERAGE&server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)
![Snyk Logo](https://img.shields.io/badge/Snyk-4C4A73?style=for-the-badge&logo=snyk&logoColor=white)
[![PyPI - License](https://img.shields.io/pypi/l/spotube?color=%23007ec6&style=for-the-badge)](LICENSE "License")
![Spotify Logo](https://img.shields.io/badge/Spotify-1ED760?&style=for-the-badge&logo=spotify&logoColor=white)
![Youtube Logo](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)
</div>
Spotube is a Python package that allows the user to download local `.mp3` copies of Spotify playlists, including cover art, artist information and lyrics.
## Description
The package can be used to download Spotify playlists, retrieving and pairing each song with the cover art as seen on Spotify, as well as any relevant metadata.
The user provides the link to a public spotify playlist, API keys for Spotify and Genius, and, optionally the directory to save the downloaded songs.
The application will then:
- Query the Spotify API for information on each song in the playlist, including the official name, artists, album cover art etc.
- Using the song name and artist(s), search for, and select the most relevant song video on Youtube. If possible, the application will avoid remixes, covers and video clip versions.
- Using the most relevant link, download the video in the highest possible quality, and convert to .mp3 format.
- Query the LyricsGenius API to retrieve the song lyrics, if available.
- Edit the .mp3 tags of the downloaded song to set the artist and album information, add the lyrics and set the cover art.
- Optionally, normalize the volume level of all downloaded `.mp3` files, to remedy the possible volume difference of YouTube videos from one another.
## Obtaining API keys
For instructions on how to generate the two sets of API keys needed to run the application, please refer to:
- [The Spotify API guide](https://developer.spotify.com/documentation/web-api/)
- [The Genius API guide](https://docs.genius.com/)
## Dependencies
In order to utilize all the features provided by Spotube, it is necessary to have ffmpeg installed and configured in your system`s PATH variable. If no ffmpeg installation is detected, Spotube will attempt to download the [prebuilt ffmpeg binaries](https://github.com/yt-dlp/FFmpeg-Builds) kindly provided by the yt-dlp team. This will allow Spotube to function, but will disable some advanced features like volume normalization.
To install ffmpeg manually, follow the instructions relevant to your system:
### Ubuntu:
```
sudo apt install software-properties-common
sudo apt update
sudo add-apt-repository ppa:jonathonf/ffmpeg-4
sudo apt install ffmpeg
```
### Windows:
- Download ffmpeg from the [ffmpeg downloads page](https://ffmpeg.org/download.html)
- Extract the downloaded archive
- Add the directory where ffmpeg was extracted to the PATH
## Installation
To install the package using pip:
```
pip install spotube
```
## Instructions and Examples
### Simple Use Case
The simplest way to use Spotube involves creating a downloader object using the `Spotify Client ID` and `Spotify Client Secret` and the `Genius API Token`, and then calling start_downloader with the link of a Spotify Playlist as the argument. The downloaded songs will be stored in the directory `./Songs` by default.
This simple use case looks like this:
```
from spotube import downloader
SPOTIFY_ID = {YOUR SPOTIFY API CLIENT ID}
SPOTIFY_SECRET = {YOUR SPOTIFY API CLIENT SECRET}
GENIUS_TOKEN = {YOUR GENIUS API TOKEN}
PLAYLIST_LINK = {THE LINK TO A SPOTIFY PLAYLIST}
my_downloaded = downloader(SPOTIFY_ID, SPOTIFY_SECRET, GENIUS_TOKEN)
my_downloaded.start_downloader(VALID_PLAYLIST)
```
### Download Directory
You can set the directory to download the songs to, in one of two ways:
By passing the optional argument `directory` in the downloaded constructor:
```
my_downloaded = downloader(SPOTIFY_ID, SPOTIFY_SECRET, GENIUS_TOKEN, directory = "./Songs")
```
By setting the directory after the downloader object has been created:
```
my_downloaded = set_directory("./Songs")
```
### Stopping the Downloader
You can stop the download process using the `cancel_downloader` method on a downloader object:
```
my_downloaded = cancel_downloader()
```
This will reset all download information, like the ETA and progress.
### Validate Playlist URL
You can examine if a Spotify playlist URL is valid by using the `validate_playlist_url` method:
```
my_downloaded = validate_playlist_url({LINK TO A PLAYLIST})
```
This method will return `True` for a valid link, `False` otherwise.
### Status Methods
The downloader class implements various methods to track the status of the downloader. These include:
- `get_progress()`: This method returns the number of songs processed.
- `get_total()`: This method returns the total number of songs in the playlist.
- `get_current_song()`: This method returns the title and artist(s) of the song currently being downloaded.
- `get_eta()`: This method returns the estimated time remaining for the download to finish, in seconds.
- `downloader_active()`: Returns `True` if there is an active download in progress, `False` otherwise.
## Disclaimer
Spotube is aimed strictly at personal use, as per the YouTube, Spotify and LyricsGenius license agreements. Sharing the
content collected by using this application, or using it for profit is strictly prohibited. For more information, please read the LICENSE file included with this distribution.
Raw data
{
"_id": null,
"home_page": "https://github.com/GiorgosNik/spotube-package",
"name": "spotube",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": null,
"author": "GiorgosNik",
"author_email": "giorgosnl17@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/5a/b3/f09b2471ca29069c7edc445d0334a85e674e56eaf3a786a62b2e2da1d351/spotube-0.5.22.tar.gz",
"platform": null,
"description": "# Spotube\n\n<div align=\"center\">\n\n[![PyPi](https://img.shields.io/badge/-PyPi-blue.svg?logo=pypi&labelColor=555555&style=for-the-badge)](https://pypi.org/project/spotube \"PyPi\")\n![PyPI - Downloads](https://img.shields.io/pypi/dm/spotube?color=%230f80c0&style=for-the-badge)\n![Sonar Logo](https://img.shields.io/badge/Sonar%20cloud-F3702A?style=for-the-badge&logo=sonarcloud&logoColor=white)\n![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/GiorgosNik_spotube-package?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)\n![Sonar Coverage](https://img.shields.io/sonar/coverage/GiorgosNik_spotube-package?label=COVERAGE&server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)\n![Snyk Logo](https://img.shields.io/badge/Snyk-4C4A73?style=for-the-badge&logo=snyk&logoColor=white)\n[![PyPI - License](https://img.shields.io/pypi/l/spotube?color=%23007ec6&style=for-the-badge)](LICENSE \"License\")\n![Spotify Logo](https://img.shields.io/badge/Spotify-1ED760?&style=for-the-badge&logo=spotify&logoColor=white)\n![Youtube Logo](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white)\n\n</div>\n\n\n\nSpotube is a Python package that allows the user to download local `.mp3` copies of Spotify playlists, including cover art, artist information and lyrics.\n\n## Description\n\nThe package can be used to download Spotify playlists, retrieving and pairing each song with the cover art as seen on Spotify, as well as any relevant metadata.\nThe user provides the link to a public spotify playlist, API keys for Spotify and Genius, and, optionally the directory to save the downloaded songs.\nThe application will then:\n\n- Query the Spotify API for information on each song in the playlist, including the official name, artists, album cover art etc.\n- Using the song name and artist(s), search for, and select the most relevant song video on Youtube. If possible, the application will avoid remixes, covers and video clip versions.\n- Using the most relevant link, download the video in the highest possible quality, and convert to .mp3 format.\n- Query the LyricsGenius API to retrieve the song lyrics, if available.\n- Edit the .mp3 tags of the downloaded song to set the artist and album information, add the lyrics and set the cover art.\n- Optionally, normalize the volume level of all downloaded `.mp3` files, to remedy the possible volume difference of YouTube videos from one another.\n\n## Obtaining API keys\n\nFor instructions on how to generate the two sets of API keys needed to run the application, please refer to:\n\n- [The Spotify API guide](https://developer.spotify.com/documentation/web-api/)\n- [The Genius API guide](https://docs.genius.com/)\n\n## Dependencies\n\nIn order to utilize all the features provided by Spotube, it is necessary to have ffmpeg installed and configured in your system`s PATH variable. If no ffmpeg installation is detected, Spotube will attempt to download the [prebuilt ffmpeg binaries](https://github.com/yt-dlp/FFmpeg-Builds) kindly provided by the yt-dlp team. This will allow Spotube to function, but will disable some advanced features like volume normalization.\n\nTo install ffmpeg manually, follow the instructions relevant to your system:\n\n### Ubuntu:\n\n```\nsudo apt install software-properties-common\nsudo apt update\nsudo add-apt-repository ppa:jonathonf/ffmpeg-4\nsudo apt install ffmpeg\n```\n\n### Windows:\n\n- Download ffmpeg from the [ffmpeg downloads page](https://ffmpeg.org/download.html)\n- Extract the downloaded archive\n- Add the directory where ffmpeg was extracted to the PATH\n\n## Installation\n\nTo install the package using pip:\n\n```\npip install spotube\n```\n\n## Instructions and Examples\n\n### Simple Use Case\n\nThe simplest way to use Spotube involves creating a downloader object using the `Spotify Client ID` and `Spotify Client Secret` and the `Genius API Token`, and then calling start_downloader with the link of a Spotify Playlist as the argument. The downloaded songs will be stored in the directory `./Songs` by default.\nThis simple use case looks like this:\n\n```\nfrom spotube import downloader\n\nSPOTIFY_ID = {YOUR SPOTIFY API CLIENT ID}\nSPOTIFY_SECRET = {YOUR SPOTIFY API CLIENT SECRET}\nGENIUS_TOKEN = {YOUR GENIUS API TOKEN}\nPLAYLIST_LINK = {THE LINK TO A SPOTIFY PLAYLIST}\n\nmy_downloaded = downloader(SPOTIFY_ID, SPOTIFY_SECRET, GENIUS_TOKEN)\n\nmy_downloaded.start_downloader(VALID_PLAYLIST)\n```\n\n### Download Directory\n\nYou can set the directory to download the songs to, in one of two ways:\n\nBy passing the optional argument `directory` in the downloaded constructor:\n\n```\nmy_downloaded = downloader(SPOTIFY_ID, SPOTIFY_SECRET, GENIUS_TOKEN, directory = \"./Songs\")\n```\n\nBy setting the directory after the downloader object has been created:\n\n```\nmy_downloaded = set_directory(\"./Songs\")\n```\n\n### Stopping the Downloader\n\nYou can stop the download process using the `cancel_downloader` method on a downloader object:\n\n```\nmy_downloaded = cancel_downloader()\n```\n\nThis will reset all download information, like the ETA and progress.\n\n### Validate Playlist URL\n\nYou can examine if a Spotify playlist URL is valid by using the `validate_playlist_url` method:\n\n```\nmy_downloaded = validate_playlist_url({LINK TO A PLAYLIST})\n```\n\nThis method will return `True` for a valid link, `False` otherwise.\n\n### Status Methods\n\nThe downloader class implements various methods to track the status of the downloader. These include:\n\n- `get_progress()`: This method returns the number of songs processed.\n- `get_total()`: This method returns the total number of songs in the playlist.\n- `get_current_song()`: This method returns the title and artist(s) of the song currently being downloaded.\n- `get_eta()`: This method returns the estimated time remaining for the download to finish, in seconds.\n- `downloader_active()`: Returns `True` if there is an active download in progress, `False` otherwise.\n\n## Disclaimer\n\nSpotube is aimed strictly at personal use, as per the YouTube, Spotify and LyricsGenius license agreements. Sharing the\ncontent collected by using this application, or using it for profit is strictly prohibited. For more information, please read the LICENSE file included with this distribution.\n",
"bugtrack_url": null,
"license": "Free for non-commercial use",
"summary": "A Python package to download Spotify playlists locally including the cover art, metadata and lyrics by leveraging the Spotify, YouTube and Genius APIs.",
"version": "0.5.22",
"project_urls": {
"Homepage": "https://github.com/GiorgosNik/spotube-package",
"Repository": "https://github.com/GiorgosNik/spotube-package"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "faf41ebc05334219b9c054941c5145eb1b0201b2e5a25f5d37e03ce987bbdc1b",
"md5": "60a3ac3c074481843ab2f662b2adfa53",
"sha256": "fc54f852dfe8adee49c1710748435f724aa8d206ffc7c390c842871c97c2775b"
},
"downloads": -1,
"filename": "spotube-0.5.22-py3-none-any.whl",
"has_sig": false,
"md5_digest": "60a3ac3c074481843ab2f662b2adfa53",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 12925,
"upload_time": "2024-10-17T13:22:28",
"upload_time_iso_8601": "2024-10-17T13:22:28.059457Z",
"url": "https://files.pythonhosted.org/packages/fa/f4/1ebc05334219b9c054941c5145eb1b0201b2e5a25f5d37e03ce987bbdc1b/spotube-0.5.22-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5ab3f09b2471ca29069c7edc445d0334a85e674e56eaf3a786a62b2e2da1d351",
"md5": "1357079e7f1d1ab8fa7a63f4f6abf514",
"sha256": "c509d2d35fd0f2f7a2887493ad2ea82a34d84e5f9bbd8fafd4ceee88cd8c5104"
},
"downloads": -1,
"filename": "spotube-0.5.22.tar.gz",
"has_sig": false,
"md5_digest": "1357079e7f1d1ab8fa7a63f4f6abf514",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 13209,
"upload_time": "2024-10-17T13:22:29",
"upload_time_iso_8601": "2024-10-17T13:22:29.373303Z",
"url": "https://files.pythonhosted.org/packages/5a/b3/f09b2471ca29069c7edc445d0334a85e674e56eaf3a786a62b2e2da1d351/spotube-0.5.22.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-17 13:22:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "GiorgosNik",
"github_project": "spotube-package",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "anyio",
"specs": [
[
">=",
"4.6.2.post1"
]
]
},
{
"name": "async-timeout",
"specs": [
[
">=",
"4.0.3"
]
]
},
{
"name": "attrs",
"specs": [
[
">=",
"24.2.0"
]
]
},
{
"name": "beautifulsoup4",
"specs": [
[
">=",
"4.12.3"
]
]
},
{
"name": "Brotli",
"specs": [
[
">=",
"1.1.0"
]
]
},
{
"name": "build",
"specs": [
[
">=",
"1.2.2.post1"
]
]
},
{
"name": "CacheControl",
"specs": [
[
">=",
"0.14.0"
]
]
},
{
"name": "certifi",
"specs": [
[
">=",
"2024.8.30"
]
]
},
{
"name": "cffi",
"specs": [
[
">=",
"1.17.1"
]
]
},
{
"name": "charset-normalizer",
"specs": [
[
">=",
"3.4.0"
]
]
},
{
"name": "cleo",
"specs": [
[
">=",
"2.1.0"
]
]
},
{
"name": "colorama",
"specs": [
[
">=",
"0.4.6"
]
]
},
{
"name": "coverage",
"specs": [
[
">=",
"5.5"
]
]
},
{
"name": "crashtest",
"specs": [
[
">=",
"0.4.1"
]
]
},
{
"name": "cryptography",
"specs": [
[
">=",
"43.0.1"
]
]
},
{
"name": "deprecation",
"specs": [
[
">=",
"2.1.0"
]
]
},
{
"name": "distlib",
"specs": [
[
">=",
"0.3.9"
]
]
},
{
"name": "dulwich",
"specs": [
[
">=",
"0.21.7"
]
]
},
{
"name": "exceptiongroup",
"specs": [
[
">=",
"1.2.2"
]
]
},
{
"name": "eyed3",
"specs": [
[
">=",
"0.9.7"
]
]
},
{
"name": "fastjsonschema",
"specs": [
[
">=",
"2.20.0"
]
]
},
{
"name": "filelock",
"specs": [
[
">=",
"3.16.1"
]
]
},
{
"name": "filetype",
"specs": [
[
">=",
"1.2.0"
]
]
},
{
"name": "h11",
"specs": [
[
">=",
"0.14.0"
]
]
},
{
"name": "html5lib",
"specs": [
[
">=",
"1.1"
]
]
},
{
"name": "httpcore",
"specs": [
[
">=",
"1.0.6"
]
]
},
{
"name": "httpx",
"specs": [
[
">=",
"0.27.2"
]
]
},
{
"name": "idna",
"specs": [
[
">=",
"3.10"
]
]
},
{
"name": "importlib_metadata",
"specs": [
[
">=",
"8.5.0"
]
]
},
{
"name": "iniconfig",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "installer",
"specs": [
[
">=",
"0.7.0"
]
]
},
{
"name": "jaraco.classes",
"specs": [
[
">=",
"3.4.0"
]
]
},
{
"name": "jeepney",
"specs": [
[
">=",
"0.8.0"
]
]
},
{
"name": "jsonschema",
"specs": [
[
">=",
"4.23.0"
]
]
},
{
"name": "jsonschema-specifications",
"specs": [
[
">=",
"2024.10.1"
]
]
},
{
"name": "keyring",
"specs": [
[
">=",
"24.3.1"
]
]
},
{
"name": "lockfile",
"specs": [
[
">=",
"0.12.2"
]
]
},
{
"name": "lyricsgenius",
"specs": [
[
">=",
"3.0.1"
]
]
},
{
"name": "more-itertools",
"specs": [
[
">=",
"10.5.0"
]
]
},
{
"name": "msgpack",
"specs": [
[
">=",
"1.1.0"
]
]
},
{
"name": "mutagen",
"specs": [
[
">=",
"1.47.0"
]
]
},
{
"name": "packaging",
"specs": [
[
">=",
"24.1"
]
]
},
{
"name": "pexpect",
"specs": [
[
">=",
"4.9.0"
]
]
},
{
"name": "pkginfo",
"specs": [
[
">=",
"1.11.2"
]
]
},
{
"name": "platformdirs",
"specs": [
[
">=",
"4.3.6"
]
]
},
{
"name": "pluggy",
"specs": [
[
">=",
"1.5.0"
]
]
},
{
"name": "poetry",
"specs": [
[
">=",
"1.8.4"
]
]
},
{
"name": "poetry-core",
"specs": [
[
">=",
"1.9.1"
]
]
},
{
"name": "poetry-plugin-export",
"specs": [
[
">=",
"1.8.0"
]
]
},
{
"name": "ptyprocess",
"specs": [
[
">=",
"0.7.0"
]
]
},
{
"name": "pycparser",
"specs": [
[
">=",
"2.22"
]
]
},
{
"name": "pycryptodomex",
"specs": [
[
">=",
"3.21.0"
]
]
},
{
"name": "pydub",
"specs": [
[
">=",
"0.25.1"
]
]
},
{
"name": "pyproject_hooks",
"specs": [
[
">=",
"1.2.0"
]
]
},
{
"name": "pyrsistent",
"specs": [
[
">=",
"0.20.0"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"8.3.3"
]
]
},
{
"name": "pywin32-ctypes",
"specs": [
[
">=",
"0.2.3"
]
]
},
{
"name": "RapidFuzz",
"specs": [
[
">=",
"3.10.0"
]
]
},
{
"name": "redis",
"specs": [
[
">=",
"5.1.1"
]
]
},
{
"name": "referencing",
"specs": [
[
">=",
"0.35.1"
]
]
},
{
"name": "requests",
"specs": [
[
">=",
"2.32.3"
]
]
},
{
"name": "requests-toolbelt",
"specs": [
[
">=",
"1.0.0"
]
]
},
{
"name": "rpds-py",
"specs": [
[
">=",
"0.20.0"
]
]
},
{
"name": "SecretStorage",
"specs": [
[
">=",
"3.3.3"
]
]
},
{
"name": "shellingham",
"specs": [
[
">=",
"1.5.4"
]
]
},
{
"name": "six",
"specs": [
[
">=",
"1.16.0"
]
]
},
{
"name": "sniffio",
"specs": [
[
">=",
"1.3.1"
]
]
},
{
"name": "soupsieve",
"specs": [
[
">=",
"2.6"
]
]
},
{
"name": "spotipy",
"specs": [
[
">=",
"2.24.0"
]
]
},
{
"name": "toml",
"specs": [
[
">=",
"0.10.2"
]
]
},
{
"name": "tomli",
"specs": [
[
">=",
"2.0.2"
]
]
},
{
"name": "tomlkit",
"specs": [
[
">=",
"0.13.2"
]
]
},
{
"name": "tqdm",
"specs": [
[
">=",
"4.66.5"
]
]
},
{
"name": "trove-classifiers",
"specs": [
[
">=",
"2024.10.16"
]
]
},
{
"name": "urllib3",
"specs": [
[
">=",
"2.2.3"
]
]
},
{
"name": "virtualenv",
"specs": [
[
">=",
"20.26.6"
]
]
},
{
"name": "webencodings",
"specs": [
[
">=",
"0.5.1"
]
]
},
{
"name": "websockets",
"specs": [
[
">=",
"13.1"
]
]
},
{
"name": "youtube-search-python",
"specs": [
[
">=",
"1.6.6"
]
]
},
{
"name": "yt-dlp",
"specs": [
[
">=",
"2024.10.7"
]
]
},
{
"name": "zipp",
"specs": [
[
">=",
"3.20.2"
]
]
}
],
"lcname": "spotube"
}