Download songs from Spotify, Apple Music and Deezer.
[![GitHub](https://img.shields.io/badge/by-miraclx-gray&plastic)](https://github.com/miraclx)
[![CodeFactor Grade](https://www.codefactor.io/repository/github/miraclx/freyr-js/badge/master)](https://www.codefactor.io/repository/github/miraclx/freyr-js/overview/master)
[![License](https://img.shields.io/github/license/miraclx/freyr-js)](https://github.com/miraclx/freyr-js)
[![CI checks](https://github.com/miraclx/freyr-js/actions/workflows/tests.yml/badge.svg)](https://github.com/miraclx/freyr-js/actions/workflows/tests.yml)
[![NPM Downloads](https://badgen.net/npm/dm/freyr)](https://www.npmjs.com/package/freyr)
[![Docker Cloud Pull Status](https://img.shields.io/docker/pulls/freyrcli/freyrjs.svg)](https://hub.docker.com/r/freyrcli/freyrjs)
[![NodeJS Version](https://img.shields.io/badge/node-%3E%3D%20v16-brightgreen)](https://github.com/miraclx/freyr-js)
[![Python Version](https://img.shields.io/badge/python-%3E%3D%20v3.2-blue)](https://github.com/miraclx/freyr-js)
[![Total Lines Of Code](https://tokei.rs/b1/github/miraclx/freyr-js?category=code)](https://github.com/miraclx/freyr-js)
[![GitHub top language](https://img.shields.io/github/languages/top/miraclx/freyr-js)](https://github.com/miraclx/freyr-js)
[![GitHub repo size](https://img.shields.io/github/repo-size/miraclx/freyr-js)](https://github.com/miraclx/freyr-js)
Built with ❤︎ by
Miraculous Owonubi
Demo
Overview
What freyr does
Depending on the URLs you provide freyr, it will;
Extract track metadata (title, album, artist, etc.) from the streaming service (Spotify if you provide a Spotify URL).
Then, it queries sources (e.g. YouTube), classifies the results to find you the best sounding, most accurate audio and downloads that in the raw format.
Next, it processes each track, encoding them in an Apple AAC format (.m4a file extension) at a default bitrate of 320kbps.
Then, it embeds all the metadata and the album art into each track.
And finally, it organizes all the files into a structured library (example).
Metadata Availability
Here's a list of the metadata that freyr can extract from each streaming service:
Requirements _Hey there, you might want to consider a cleaner and straight-forward installation method, without having to manually setup the requirements. If so, checkout the [Docker installation method](#docker)_ python >= v3.2
Download for your individual platforms here
Linux: _(check individual package managers)_
- Debian: `sudo apt-get install python3.6`
- Arch Linux: `sudo pacman -S python`
- Android (Termux): `apt install python`
- Alpine Linux: `sudo apk add python3`
nodejs >= v16.0.0
Download for your individual platforms here
macOS + Linux: [nvm](https://github.com/nvm-sh/nvm) recommended.
```bash
# install node with this nvm command
# freyr works with a minimum of v16
$ nvm install --lts
```
- Android (Termux): `apt install nodejs`
- Alpine Linux: `sudo apk add nodejs`
AtomicParsley >= 20230114
First, download the latest release for your individual platforms here
Then;
- Windows:
- unzip and place the `AtomicParsley.exe` in your `PATH`.
- or the `bins/windows` folder of this project directory. Create the folder(s) if they don't exist.
- Linux + macOS:
- unzip and place the `AtomicParsley` in your `PATH`.
- or the `bins/posix` folder of this project directory. Create the folder(s) if they don't exist.
- Alternatively:
- Debian: `sudo apt-get install atomicparsley`
- Arch Linux: `sudo pacman -S atomicparsley`
- Android (Termux): `apt install atomicparsley`
- Build from source: See [wez/AtomicParsley](https://github.com/miraclx/atomicparsley)
> _Please note that [YouTube Music](https://music.youtube.com/) must be available in your region for freyr to successfully work, this is because freyr sources raw audio from [YouTube Music](https://music.youtube.com/)._
---
First start by ensuring all requirements listed above are satisfied. Thereafter, you can use either of these options to install freyr:
Or you can build from source
```bash
git clone https://github.com/miraclx/freyr-js.git freyr
cd freyr
```
| % | NPM | Yarn |
| ----------------- | ------------- | -------------- |
| pull dependencies | `npm install` | `yarn install` |
| install globally | `npm link` | `yarn link` |
Docker
For convenience, we provide officially prebuilt images (automated builds from this repository) so you can skip the setup and build process and get right into it.
Image Size:
Usage (docker)
docker run -it --rm -v $PWD:/data freyrcli/freyrjs [options, arguments and queries...]
You can also create a handy alias to skip remembering that whole line everytime
alias freyr='docker run -it --rm -v $PWD:/data freyrcli/freyrjs'
The -v $PWD:/data part sets the working directory for freyr to the current working directory.
For example, you can use -v ~/Music/freyr:/data to set the work directory and consequently, default save location to ~/Music/freyr.
Please ensure the folder on the host already exists, create it if not. Otherwise, docker autocreates the folder as root and that causes unpleasant Permission Denied issues when you run freyr.
Usage: freyr [options] get [options] [query...]
Usage: freyr [options] [query...]
freyr get --help
```console
____
/ __/_______ __ _______
/ /_/ ___/ _ \/ / / / ___/
/ __/ / / __/ /_/ / /
/_/ /_/ \___/\__, /_/
/____/ v0.10.3
freyr - (c) Miraculous Owonubi
------------------------------------------------------
Usage: freyr get [options] [query...]
Download music tracks from queries
Options:
-i, --input use URIs found in the specified FILE as queries (file size limit: 1 MiB)
(each query on a new line, use '#' for comments, whitespaces ignored)
(example: `-i queue.txt`)
-b, --bitrate set audio quality / bitrate for audio encoding
(valid: 96,128,160,192,256,320) (default: "320k")
-n, --chunks number of concurrent chunk streams with which to download (default: 7)
-r, --retries set number of retries for each chunk before giving up
(`infinite` for infinite) (default: 10)
-t, --meta-retries set number of retries for collating track feeds (`infinite` for infinite) (default: 5)
-d, --directory save tracks to DIR/..
-D, --check-dir check if tracks already exist in another DIR (repeatable, optionally comma-separated)
(useful if you maintain multiple libraries)
(example: `-D dir1 -D dir2 -D dir3,dir4`)
-c, --cover custom name for the cover art, excluding the extension (default: "cover")
--cover-size preferred cover art dimensions
(format: x or as x) (default: "640x640")
-C, --no-cover skip saving a cover art
-S, --sources specify a preferred audio source or a `,`-separated preference order
(valid: youtube,yt_music) (prefix with `!` to exclude) (default: "yt_music")
-l, --filter filter matches off patterns (repeatable and optionally `,`-separated)
(value omission implies `true` if applicable)
(format: ) (example: title="when we all fall asleep*",type=album)
See `freyr help filter` for more information
-L, --filter-case enable case sensitivity for glob matches on the filters
-z, --concurrency key-value concurrency pairs (repeatable and optionally `,`-separated)
(format: <[key=]value>) (key omission implies track concurrency)
(valid(key): queries,tracks,trackStage,downloader,encoder,embedder)
(example: `queries=2,downloader=4` processes 2 CLI queries,
downloads at most 4 tracks concurrently)
--gapless set the gapless playback flag for all tracks
-f, --force force overwrite of existing files
-o, --config specify alternative configuration file
-p, --playlist create playlist for all successfully collated tracks
-P, --no-playlist skip creating a playlist file for collections
--playlist-dir directory to save playlist file to, if any, (default: tracks base directory)
--playlist-noappend do not append to the playlist file, if any exists
--playlist-noescape do not escape invalid characters within playlist entries
--playlist-namespace namespace to prefix on each track entry, relative to tracks base directory
useful for, but not limited to custom (file:// or http://) entries
(example, you can prefix with a HTTP domain path: `http://webpage.com/music`)
--playlist-force-append force append collection tracks to the playlist file
-s, --storefront country storefront code (example: us,uk,ru)
-T, --no-tree don't organise tracks in directory structure `[DIR/]//
Resilient visual progressbar per track download (powered by [xprogress])
Stats on runtime completion
runtime duration
number of successfully processed tracks
output directory
cover art name
total output size
total network usage
network usage for media
network usage for album art
output bitrate
Configuration
User / Session specific configuration
Persistent configuration such as authentication keys and their validity period are stored within a session specific configuration file.
This configuration file resides within the user config directory per-platform.
- `$HOME/.config/FreyrCLI/d3fault.x4p` for Linux.
- `$HOME/Library/Preferences/FreyrCLI/d3fault.x4p` for macOS.
Project specific configuration
All defaults are defined in the [conf.json](https://github.com/miraclx/freyr-js/blob/master/conf.json) file at the root of the project. This file should be of `JSON` format and is to be structured as such.
Do not edit this file directly, instead run freyr once and edit the user specific configuration (see above).
- `server`: \
Spotify
- `spotify`: \
- `clientId`: \
- `clientSecret`: \
- `refreshToken`: \
Spotify requires a `clientId` and a `clientSecret` that can be gotten from their developer dashboard.
If you wish to create and use custom keys, [See [Spotify API Authorization](#spotify-api-authorization)].
An optional `refreshToken` option can be defined which can be used to authenticate a session without necessarily requesting explicit permissions. The `refreshToken` is already bound to a pre-authenticated account.
An invalid `refreshToken`, when specified, would fallback to requesting account access which in-turn would request re-authentication of the users' account.
#### Spotify API Authorization
1. Sign in to the [Spotify Dashboard](https://developer.spotify.com/dashboard/)
2. Click `CREATE A CLIENT ID` and create an app
3. Now click `Edit Settings`
4. Add `http://localhost:36346/callback` to the Redirect URIs
5. Include the `clientId` and the `clientSecret` from the dashboard in the `spotify` object that is a property of the `services` object of the `conf.json` file. [See [Configuration](#configuration)]
6. You are now ready to authenticate with Spotify!
Apple Music
- `apple_music`: \
- `storefront`: \
- `developerToken`: \
Freyr would automatically fetch a developer token from the Apple Music site, which should suffice for all intents and purposes. But if you prefer to use a custom developer token, please refer to the Apple Music documentation on this topic.
The `storefront` option defines the default storefront to be used in the absence of a specification.
#### Apple Music API Authorization
[See [Apple Music API: Getting Keys and Creating Tokens](https://developer.apple.com/documentation/applemusicapi/getting_keys_and_creating_tokens)]
After successfully acquiring the developer token, include the `developerToken` to the `apple_music` object that's a property of the `services` object in the `conf.json` file. [See [Configuration](#configuration)]
An expired developer token in the `conf.json` would make freyr fallback to fetching it from the Apple Music site.
Deezer
- `deezer`: \
- `retries`: \
Authentication unrequired. API is freely accessible.
Because of the 50 requests / 5 seconds limit enforced on an IP-basis for Deezer's API [See [#32](https://github.com/miraclx/freyr-js/issues/32)],
occasionally a `Quota limit exceeded` error would be thrown by the API server.
To combat this, freyr employs request batching, managed delays and finally, retries when things go awry.
You can configure how many retries you want freyr to make before accepting failure.
Return Codes
0: OK
1: Invalid query
2: Invalid flag value
3: Invalid / Inexistent configuration file
4: Network error
5: Error with working directory
6: Failed to initialize a freyr instance
7: An error occurred checking dependency paths
FilterRules
Filter rules each to be matched against the tracks involved in any operation.
Used as values to the -l, --filter flag or as key-value pairs in the filters array of the configuration file.
yarn install
# to have access to the freyr command globally
yarn link
Testing
Freyr comes bundled with a lightweight test suite. See TEST.md for instructions on how to run it.
Docker Development
With docker, you can drop into a sandbox that has all the dependencies you need. Without needing to mess around with your host system or install any weird dependencies.
First, you need to either build a local docker image or submit a PR and use the corresponding auto-generated image.
Building A Local Image
The default provided Dockerfile builds minimal alpine images. Average build network usage is ~ 80 MB and disk usage is ~ 180 MB.
An alternative to building the docker image locally is to use a remote image. By default, all PRs submitted to this repository get an equivalently tagged docker image for testing.
For example, the PR #214 has a docker image called freyrcli/freyrjs-git:pr-214. And it stays updated with the current state of the branch.
You can then pull the development image for use locally.
docker pull freyrcli/freyrjs-git:pr-214
Once you have a built development image locally, you're ready to go. You can drop into the container by explicitly defining the entrypoint
docker run -it --entrypoint bash freyr-dev
# Alternatively, create a handy alias
alias freyrsh='docker run -it --entrypoint bash freyr-dev'
*: don't forget to replace freyr-dev with the appropriate image name if you pulled one of the auto-generated remote images.
Optionally, you can use these interesting flags to customize the experience.
-h freyr-dev sets the container hostname to freyr-dev
-m 1G sets the container memory limit
-v $PWD:/data mounts the current working directory to /data within the container.
--cpus 2 limits the container to using 2 CPU cores
The freyr source would be available in the /freyr directory within the container along with a globally registered command freyr for calling the script.
For more information and documentation about docker, please refer to its official site: