Download music from YouTube, YouTube Music and Soundcloud, with great metadata and little effort.
Project description
shira
A smart music downloader
Download music from YouTube, YouTube Music and Soundcloud,
with great metadata and little effort.
Installation
You need to have:
- python (3.11+) installed
ffmpeginstalled (See Installing ffmpeg) and added to PATH, or specify it with--ffmpeg-location/config
Installation methods:
- uv (preferred) -> install uv, then run:
uv tool install shiradl
- pipx -> install pipx, then run:
pipx install shiradl
- local installation with uv (for development) - see Contributing
If you don't want to install shira and just want to try it out / use it once, run
uvx shiradl <args>
Updating
If you have previously installed shira, it's important to update it to the last version, otherwise it may not work.
Guides: Using a cookies file, Troubleshooting
Usage Examples
shiradl https://music.youtube.com/watch?v=HdX2COsY2XkYouTube Musicshiradl "https://music.youtube.com/watch?v=8YwKlPH93Ps&list=PLC1og_v3eb4jE0bmdkWtizrSQ4zt86-3D"shiradl https://www.youtube.com/watch?v=X0-AvRA7kB0YouTube (video)shiradl https://soundcloud.com/neffexmusic/fight-backSoundCloudshiradl https://music.youtube.com/playlist?list=PLC1og_v3eb4jE0bmdkWtizrSQ4zt86-3DAlbum/Playlistshiradl -u ./links.txtList of links to download
Goals
- Provide an easy way to download audio from YouTube Music, YouTube or SoundCloud
- Instead of a GUI/manual input for some steps like in tiger, shira requires no additional user input once ran.
- Provide objectively correct or at least very reasonable music metadata & properly tag music files.
- objectively correct: Shira queries the MusicBrainz Database and YouTube Music's API to get metadata
- very reasonable: When downloading a Youtube video, tags will be inferred from the video info:
title,channel_name,description,upload_date, etc.
Tagging
- Adds a lot of metadata to music files, in these native tags (m4a, mp3)
- Embeds proper
m4a(iTunes) and.mp3(ID3v2.4) tags with mediafile - Uses YouTube Music's API to get info.
- Uses MusicBrainz API to resolve MusicBrainz ID's from their api
track,album,artist,albumartistids- falls back to
artist,albumartistif this recording can't be found, but artist can.
- falls back to
- Uses my custom smart-metadata system from tiger for non-music videos
- collects as much information as possible for each tag, and selects the value with most occurrences (with fallbacks)
- Cleans up messy titles into more reasonable ones:
IDOL【ENGLISH EDM COVER】「アイドル」 by ARTIST【Artist1 x @Artist2 】=>IDOL [ENGLISH EDM COVER] [アイドル] by ARTIST
- Is smart about turning a video's thumbnail into a square album cover
More info about YouTube thumbnail to Album Art algorithm
- samples 4 pixels near the corners of the thumbnail (which is first smoothed and reduced to 64 colors)
- decides to crop if average of standard deviations of r, g and b color channels from each sample point is lower than a than a threshold
- otherwise pads the image to 1:1 with it's dominant color
About & Credits
- This software is for educational purposes only and comes without any warranty; See LICENSE.
- Credits for copyright-free example tracks used: Andy Leech, 4lienetic, NEFFEX
- The name Shira was inspired by a saber-toothed tiger from Ice Age.
- It also means 'poetry', 'singing' or 'music' in Hebrew.
- The project is based on my previous YouTube downloader tiger and Glomatico's YouTube Music Downloader
- Project logo is based on this DeviantArt fanart, which has been modified, vectorized and cleaned up.
- Thanks to this pydantic blogpost for introducing me to
inline-snapshot, because otherwise shira probably wouldn't have tests. :)
Support development
Any donations are highly appreciated! <3
Configuration
Shira can be configured using the command line arguments or the config file.
The config file is created automatically when you run shira for the first time at ~/.shiradl/config.json on Linux and %USERPROFILE%\.shiradl\config.json on Windows. Config file values can be overridden using command line arguments.
| Command line argument / Config file key | Description | Default value |
|---|---|---|
-f, --final-path / final_path |
Path where the downloaded files will be saved. | ./YouTube Music |
-t, --temp-path / temp_path |
Path where the temporary files will be saved. | ./temp |
-c, --cookies-location / cookies_location |
Location of the cookies file. | null |
--ffmpeg-location / ffmpeg_location |
Location of the FFmpeg binary. | ffmpeg |
--config-location / - |
Location of the config file. | <home folder>/.shiradl/config.json |
-i, --itag / itag |
Itag (audio quality/format). More info | 140 |
--cover-size / cover_size |
Size of the cover. size >= 0 and <= 16383 |
1200 |
--cover-format / cover_format |
Format of the cover. jpg or png |
jpg |
--cover-quality / cover_quality |
JPEG quality of the cover. [1<=x<=100] | 94 |
--cover-img / cover_img |
Path to image or folder of images. More info | null |
--cover-crop / cover_crop |
'crop' takes a 1:1 square from the center, pad always pads top & bottom. auto, crop or pad |
auto - More info |
--template-folder / template_folder |
Template of the album folders as a format string. | {albumartist}/{album} |
--template-file / template_file |
Template of the track files as a format string. | {track:02d} {title} |
-e, --exclude-tags / exclude_tags |
List of tags to exclude from file tagging separated by commas without spaces. | null |
--truncate / truncate |
Maximum length of the file/folder names. | 40 |
-l, --log-level / log_level |
Log level. | INFO |
-s, --save-cover / save_cover |
Save cover as a separate file. | false |
-o, --overwrite / overwrite |
Overwrite existing files. | false |
-p, --print-exceptions / print_exceptions |
Print exceptions. | false |
-u, --url-txt / - |
Read URLs as location of text files containing URLs. | false |
-n, --no-config-file / - |
Don't use the config file. | false |
-w, --single-folder / - |
Wrap singles in their own folder instead of placing them directly into artist's folder. | false |
Itags
The following itags are available:
140(128kbps AAC) - default, because it's the result ofbestaudio/beston a free account141(256kbps AAC) - use if you have premium alongside--cookies-location251(128kbps Opus) - most stuff will error withFailed to check URL 1/1. Better to use140
SoundCloud will always download in 128kbps MP3
- SoundCloud also offers OPUS, which is currently not supported. Some people were complaining that the quality is worse
- These are questionable claims at best, but better safe than sorry.
Tag variables
The following variables can be used in the template folder/file and/or in the exclude_tags list:
title, album, artist, albumartist, track, tracktotal, year, date, cover, comments, lyrics, media_type, rating, track, tracktotal, mb_releasetrackid, mb_releasegroupid, mb_artistid, mb_albumartistid
To exclude all musicbrainz tags, you can add mb* to exclude_tags. (This does not work for other types of tags).
Cover formats
Can be either jpg or png.
Cover img
- Pass in a path to an image file, and it will get used for all of the links you're currently downloading.
- Pass in a path to a folder, and the script will use the first image matching the track/video id and jpeg/png format
- You don't have to create covers for all tracks/videos in the playlist/album/etc.
- SoundCloud will also consider images based on the URL slug instead of id
- for example:
https://soundcloud.com/yatashi-gang-63564467/lovely-bastards-yatashigang=>lovely-bastards-yatashigang.jpg/.png
Troubleshooting
- if shira can't download songs, first try updating; the issue is likely that
yt-dlpor something else needs updating - In case shira still can't download songs / you're having other issues:
- If the PyPI version is outdated or broken, you can install directly from git as a workaround:
- uv:
uv tool install git+https://github.com/KraXen72/shira - pipx:
pipx install git+https://github.com/KraXen72/shira - uvx:
uvx --from git+https://github.com/KraXen72/shira shiradl <args>(doesn't install, only runs)- as a temporary measure, you can try these steps
- uv:
python: No module named shiradl- Make sure you are not already in the
shiradldirectory, e.g./shira/shiradl. if yes, move up one directory withcd ..and retry.
- Make sure you are not already in the
- I really need to run this on
python3.8+ and updating to 3.11+ is not an option- run
uv add typing-extensionsand modifytagging.pyaccordingly:
- from typing import NotRequired, TypedDict + from typing_extensions import NotRequired, TypedDict
- run
Uninstalling
If you're uninstalling because shira doesn't work, I would like to kindly ask you to please make a GitHub issue about what exactly doesn't work. Thanks!
To uninstall, run the appropriate command. If unsure which way you installed shira, run both.
- uv:
uv tool uninstall shiradl - pipx:
pipx uninstall shiradl
Installing ffmpeg
Installing ffmpeg with scoop
- Scoop is a package manager for windows. It allows easy installing of programs and their updating from the command line.
- Install scoop by running a powershell command (on their website)
- Run
scoop install main/ffmpeg - Scoop automatically adds it to path. you can update ffmpeg by doing
scoop updateandscoop update ffmpeg/* - If installing scoop/with scoop is not an option, continue reading:
Installing ffmpeg on Windows (manual install)
- Related: Comprehensive tutorial with screenshots
- Download an auto-built zip of latest ffmpeg: download / mirror.
- Extract it somewhere, for example into
C:\ffmpeg. It's best if the path doesn't have spaces.
Adding ffmpeg to PATH
- Look for
Edit the system environment variablesin the Start Menu, launch it. - Find the
Pathuser variable, clickEdit - Click
Newon the side and enter the path to theffmpeg\binfolder which hasffmpeg.exein it, e.g.C:\ffmpeg\bin - Click
Ok. To verify thatffmpegis installed, runffmpeg -versionin the terminal.
Pointing to ffmpeg manually
- If you do not want to add
ffmpegto path, you can point to it manually. - Use the config option
ffmpeg_locationor the cli flag--ffmpeg-locationto point to theffmpeg.exefile. - Keep the
ffplay.exeandffprobe.exefiles in the same directory.
Installing ffmpeg on linux
- use your distro's package manager to install
ffmpeg-
Setting a cookies file
- By setting a cookies file, you can download age restricted tracks, private playlists and songs in 256kbps AAC if you are a premium user.
- You can export your cookies to a file by using this Google Chrome extension or Firefox extension on
https://music.youtube.com
Contributing
- Please report any bugs in Issues. Pull requests are welcome!
- To contribute, you'll (likely) need a local installation of shira
- If you're planning on implementing something big / that changes a lot, it's worth opening an issue about it to discuss it first.
- Thanks!
Running tests
- Install dev dependencies:
uv sync(includes dev deps automatically) - Run all tests:
uv run task test(will take a couple of minutes, has to download stuff) - There are different types of tests
- Smoke
uv run task test:smoke: Downloads only like 3 songs, checking both resulting file size & metadata - Metadata
uv run task test:meta: Skips downloading, only checking metadata - Download
uv run task test:dl: performs real downloads, checking only if the files are large enough
- Smoke
- To record or refresh inline snapshots run: e.g.
uv run pytest tests/metadata.test.py -v --inline-snapshot=review - You can append additional pytest args after
--when using theuv run taskhelpers
Publishing a new release
- Bump the version:
uv version --bump patch(orminor/major) - Commit the version bump (replace
X.Y.Zwith the new version):git commit -am "chore: bump version to X.Y.Z"
- Tag and push:
uv run task release(see./scripts/release.sh) This automatically creates avX.Y.Zgit tag and runsgit push && git push --tags.
Pushing the tag triggers the CI workflow, which runsuv build+uv publishto release the new version to PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shiradl-1.8.2.tar.gz.
File metadata
- Download URL: shiradl-1.8.2.tar.gz
- Upload date:
- Size: 79.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a97e19fdfa126b7b2f62b71624395cb4e9c453783ef36b85c02ae23924d960ec
|
|
| MD5 |
712ef961f4b58e0acbf0b58f608d4398
|
|
| BLAKE2b-256 |
ac95d23ebab34498298614082e01d3a9c16d6749c0da6ee30550aaa92fbff6ab
|
File details
Details for the file shiradl-1.8.2-py3-none-any.whl.
File metadata
- Download URL: shiradl-1.8.2-py3-none-any.whl
- Upload date:
- Size: 29.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a858c82e85dc1cbf2f0439022bd2eb54325fb2d35e76c49e7bedd83ede52518
|
|
| MD5 |
856b47fe40c6675cb044b3bf20384a63
|
|
| BLAKE2b-256 |
60122ebb44a14c31e69c788af72d36849679fcf3aba04f6fc58f9ee6e37c50c0
|