A modular downloading tool (JS library)
Go to file
aria fbccef8399 bump version 2024-04-18 20:53:40 -04:00
scripts Initial commit 2023-09-16 21:05:49 -05:00
src qobuz sample erroring 2024-04-18 20:52:41 -04:00
.eslintignore Initial commit 2023-09-16 21:05:49 -05:00
.eslintrc.cjs Initial commit 2023-09-16 21:05:49 -05:00
.gitignore remove testing file, bump version, update constants 2024-04-11 13:54:35 -04:00
.prettierignore Initial commit 2023-09-16 21:05:49 -05:00
.prettierrc update dependencies 2023-10-31 22:09:29 -05:00
LICENSE Initial commit 2023-09-16 21:05:49 -05:00
package.json bump version 2024-04-18 20:53:40 -04:00
pnpm-lock.yaml update dependencies 2024-02-10 20:39:38 -05:00
README.md add spotify support 2023-09-16 22:39:32 -05:00
tsconfig.json fix tsconfig 2023-09-17 01:05:51 -05:00


A modular downloading tool. Includes code for a small collection of streaming services (does not come with accounts or tokens).

Lucida is made to use few NodeJS dependencies and no system dependencies (...besides ffmpeg)


import Lucida from 'lucida'
import Tidal from 'lucida/streamers/tidal/main.js'
import Qobuz from 'lucida/streamers/qobuz/main.js'
import Spotify from 'lucida/streamers/spotify/main.js'

const lucida = new Lucida({
	modules: {
		tidal: new Tidal({
			// tokens
		qobuz: new Qobuz({
			// tokens
		spotify: new Spotify({
			// options
		// Any other modules
	logins: {
		qobuz: {
			username: '',
			password: ''
		spotify: {
			username: '',
			password: ''

// only needed if using modules which use the logins configuration rather than tokens
await lucida.login()

const track = await lucida.getByUrl('https://tidal.com/browse/track/255207223')

await fs.promises.writeFile('test.flac', (await track.getStream()).stream)

// only needed for modules which create persistent connections (of the built-in modules, this is just Spotify)
await lucida.disconnect()

For using a specific module, you can just use the functions built into the Streamer interface.

Project Structure



Default export is a class which implements the Streamer interface:

interface Streamer {
	hostnames: string[]
	search(query: string, limit: number): Promise<SearchResults>
	getByUrl(url: string): Promise<GetByUrlResponse>

They can optionally include a login function in this class which takes a username and password (if supported):

async login(username: string, password: string): void

Options for the app, including tokens (if supported by the given app), are passed to the class's constructor:

new StreamerApp({ token: 'secret!' })

The classes can also include their own custom functions. Any function used by Lucida's app-agnostic code should be defined in the Streamer interface for compatibility across multiple apps.


Functions for parsing the app's API into the types defined in src/types.ts.


Constants used by main.ts. Secrets should not be defined here (or anywhere else in the project).


Wraps all the Streamers using a module system. See the usage section.


Types used across the project. The purpose of many of these is to make sure all apps' functions return the same types so the rest of the logic can work across all apps the same.


Lucida is partially inspired by OrpheusDL, a Python program for music archival which can be used similarly to Lucida. Some scripts inside Lucida are modeled after OrpheusDL modules.


Copyright hazycora. Licensed under AGPLv3.