Skip to content

CLI to manage your ListenBrainz listens and process listen dumps

License

Notifications You must be signed in to change notification settings

kellnerd/elbisaur

Repository files navigation

elbisaur

Command line app to manage your ListenBrainz listens and process listen dumps.

If you want to give it a try to see what you get, you can safely execute it with Deno. Run the following command to see its integrated help, Deno will prompt you for the necessary permissions:

deno run jsr:@kellnerd/elbisaur

Setup

If you don’t want to have to remember the URL and grant permissions every time, you can install it with the permissions specified as arguments:

deno install --global --allow-env=LB_USER,LB_TOKEN,ELBISAUR_LISTEN_TEMPLATE --allow-net=jsr.io,api.listenbrainz.org,musicbrainz.org --allow-read --allow-write jsr:@kellnerd/elbisaur

Now you can simply run the app by executing elbisaur, which should show you the help and complain about a missing required environment variable LB_TOKEN. This is your ListenBrainz user token which is required to submit listens and can be obtained from your ListenBrainz settings page. Running elbisaur automatically tries to load environment variables from a .env file in your working directory, so you can comfortably safe your LB user token inside there:

# example token below, insert your own
LB_TOKEN = "3b851ecc-474d-44eb-a4d0-db3bbb5ef8b8"
# user name is optional, but it sometimes saves an API request if it is specified
LB_USER = "Your LB user name here"

Commands

elbisaur is a modular command line app with multiple subcommands which you can execute with elbisaur <command>. The following commands are available:

Command Description
history Show the listening history of yourself or another user
delete Delete listens in the given JSON file from your history
import Import listens from the given JSON file
listen Submit listens for selected tracks from a release (given by its URL)
parse Parse listens from a file and write them into a JSONL file
statistics Show statistics for the given JSON file
transform Modify listens from a JSON input file and write them into a JSONL file

You can view the integrated help of each command with elbisaur <command> --help.

All commands which accept JSON files as input also accept JSONL files (one JSON object per line). These should contain (one or multiple) serialized Listen objects as included in a ListenBrainz listening history export (and as shown by the ListenBrainz “Inspect listen” dialog). JSONL files which are written by elbisaur also follow this format.

Parsers

The following formats can be parsed by elbisaur (in addition to native JSON and JSONL listens):

  • .scrobbler.log (*.log): Log file which is generated by some portable music players for later submission to Last.fm.
  • Spotify (*.json): JSON files from an Extended Streaming History download.

See the parser documentation for implementation details.

Note

The parsers perform no filtering of listens, so you have to detect potential duplicates and skipped listens yourself.

Examples

Listening History

View your most recent listening history using the history command:

elbisaur history

In order to see the listening history of another user, specify their name with the -u, --user option:

elbisaur history --user listenbrainz

You can filter listens by listening time (-a, --after and -b, --before, happens on the server) and metadata (-f, --filter, happens locally). If you want to apply metadata filters (locally), ensure that the API returns enough results by specifying a higher count with -c, --count.

Downloaded results can be stored as JSONL file by specifying an output path with -o, --output. If the file already exists, the new listens will be appended to it.

Download your listens for all tracks by Jane Doe to which you listened on 17th January 2024:

elbisaur history -f "artist_name==Jane Doe" -a 2024-01-17 -b 2024-01-18 -c 200 -o jane.jsonl

Importing Listens

Importing listens is straightforward if you have a JSON file which contains one or multiple listens. Such a file can be a ListenBrainz listening history export, the result of another elbisaur command or the content from a ListenBrainz “Inspect listen” dialog.

Before running the actual import command itself, it is recommended to run the same command with the -p, --preview flag to see which listens would be imported:

elbisaur import listens.json --preview

Only if you are satisfied with what you see, you should proceed:

elbisaur import listens.json

Manually Submitting Listens

You can also use elbisaur to submit listens for selected tracks from a release manually.

If you want to quickly submit a single listen with track title (Love Song) and artist (John Doe), you can use:

elbisaur listen "John Doe - Love Song" --at "2024-03-17 15:24:36"

Or quickly submit a playing now notification for that track:

elbisaur listen "John Doe - Love Song" --now

Alternatively you can also submit multiple listens using the MusicBrainz URL of a release. Say you started listening to side A of a vinyl record today at 12:34:56 and want to submit listens for these tracks. The app automatically calculates the listening timestamps for all tracks based on the track lengths.

elbisaur listen https://musicbrainz.org/release/d6010be3-98f8-422c-a6c9-787e2e491e58 A --at 12:34:56

Of course you can also specify the time when you finished listening (to the last track):

elbisaur listen https://musicbrainz.org/release/d6010be3-98f8-422c-a6c9-787e2e491e58 A --until 12:59:52

And if you finished listening to side B right now (this second), you can simply omit the time option:

elbisaur listen https://musicbrainz.org/release/d6010be3-98f8-422c-a6c9-787e2e491e58 B

Instead of specifying the track number prefix (here: the side number A), you could also explicitly type the track range A1-A6. For releases with multiple media, you can additionally specify the medium number (2:1-5), or even just a medium number (2:, since simply 2 would be interpreted as track number prefix).

Deleting Listens

If you want to delete some of your listens, you need to obtain a JSON file which contains the bad listens. You can either use a filtered listening history export for this or create the file using elbisaur history.

The file not only contains the necessary data to send deletion requests to the API, it can also serve as a backup in case you accidentally delete the wrong listens.

Before running the actual delete command itself, it is recommended to run the same command with the -p, --preview flag to see which listens would be deleted:

elbisaur delete bad-listens.jsonl --preview

Only if you are satisfied with what you see, you should proceed:

elbisaur delete bad-listens.jsonl

Please note that this only marks listens for deletion currently and that it takes until the full hour before the deleted listens finally disappear from ListenBrainz.

Parsing .scrobbler.log Files

Parse a .scrobbler.log file (for example from a Rockbox player) and discard all scrobbles which are marked as skipped:

elbisaur parse .scrobbler.log --filter skipped!=1

You can also run the parser again and write skipped scrobbles to a separate file for manual review:

elbisaur parse .scrobbler.log --filter skipped==1 skipped-listens.jsonl

Note

Timestamps are automatically converted from your local timezone to UTC as Rockbox players are usually not timezone-aware.

Parsing Spotify Extended Streaming History

If you have requested your Extended Streaming History from Spotify, you receive one or more Streaming_History_Audio_*.json files. These files can be parsed with elbisaur, but they also contain skipped streams which are sometimes not marked as such.

Parse Spotify history file and only keep streams which were not skipped and were played for at least 30 seconds:

elbisaur parse Streaming_History_Audio_2024.json --filter "skipped!=1&&ms_played>=30e3"

While some skipped listens can be detected by their reason_end properties, bad listens can also have a reason of trackdone although Spotify failed to play them (playback duration is only a second or two).

You might have to experiment with the filter options a bit or do multiple passes to get optimal results. Limiting the output by specifying a time range (-a, --after and -b, --before) makes reviewing the results (using the -p, --preview option) a lot more comfortable.

Note

This parser calculates the correct listen (start) timestamp from stream end time and duration.

In some cases this time is completely inaccurate because the logged end timestamp is wrong and does not indicate when the track stopped playing. It appears to be the next time when Spotify was opened again after the app or the web player had been closed unexpectedly.

In those cases the parser uses the so called “offline” timestamp which, despite its name, is not exclusively used to track offline playback. While it seems to be a few seconds off in general, it is pretty accurate for those cases where the logged end time is bogus.

You can specify the -d, --debug flag to include all possible timestamp data in the additional_info properties of each parsed listen.

Modifying Listens

Correct a typo in the release name property of a few listens from a JSON file:

elbisaur transform input.jsonl -f "release_name==Exmaple" -e "release_name=Example" fixed.jsonl

Inject (or correct) the release MBID for all listens with a given release name:

elbisaur transform input.jsonl -f "release_name==Example" -e "release_mbid=bf9e91ea-8029-4a04-a26a-224e00a83266" output.jsonl

Compensate a wrong listen time offset of an hour for all listens (by adding 3600 seconds):

elbisaur transform wrong-time.jsonl -t 3600 correct-time.jsonl

About

CLI to manage your ListenBrainz listens and process listen dumps

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published