Segue
A crossfading queueing daemon for mpv - kind of like mpd but nowhere near as flexible or
useful.
A segue is the radio and DJ term for a transition where one track fades into the next, which is the whole point of this thing.
The player daemon starts two instances of mpv and uses those to play any tracks placed in the queue.
Why two instances? mpv doesn't support crossfading between tracks, so this crossfades by starting the other mpv instance playing the next track and adjusting the volume of both.
This is a rewrite of vlcraptor, which did the same thing with two
copies of the VLC desktop app. mpv is a better fit: it's a headless binary rather than a .app bundle, it
speaks JSON over a unix socket instead of a line oriented telnet interface, and it runs anywhere rather than
only where VLC happens to be installed in /Applications.
Installation
brew install mpv (or your platform's equivalent) - segue looks for mpv on your PATH.
brew install ffmpeg is required by the queue command for extracting tags to place in the queue, and by
the player for pulling album art out of a track.
brew install terminal-notifier is optional depending on whether you want notifications when new tracks
start. Notifications carry the album art where the track has any.
This gem can be installed with gem install segue.
Usage
Running segue without any parameters will list the available subcommands.
Player
Run segue player in a shell session.
This is the player daemon that controls two instances of mpv. It takes over the display in that terminal, drawing its panel with ANSI escapes rather than curses - which is what lets it show the album art beside the track, in any terminal that speaks the kitty graphics protocol (ghostty, kitty and wezterm all do). In a terminal that doesn't, or one too narrow to fit it, the art is simply left out.
You can quit with 'q', pause with ' ', stop with 's', play (resume) with 'p' and skip with 'n'.
Indexing a collection
segue scan /Volumes/music walks a directory, reads the tags out of every audio file below it and records them
in an index at ~/.segue/library.db.
The first run is slow, because reading tags means running ffmpeg over every file. Later runs only read the files whose size or modification time has changed, so a rescan of an unchanged collection takes seconds.
Tracks are keyed by their path relative to the directory that was scanned, rather than by their absolute path
- which is also how an object store holds them, so the index stays meaningful when the files themselves are somewhere other than the drive they were scanned from.
An interrupted scan costs nothing: the index is updated in place as the walk proceeds, and tracks whose files have gone away are only dropped once a scan has finished walking.
Searching the index
segue search aphex sel lists indexed tracks matching every word given, against artist, album, title and album
artist. Words match on their start, so part of a name is enough.
Each line begins with the track's library id, which is what segue add takes.
Queueing from the index
segue add 4f0 4f2 queues tracks by their library id, in the order the ids are given.
Ids are written in base 36 to keep them short, and a run of them can be given as a range - 4f0-4f9, or just
4f0-9, since the end of a range only has to carry the digits that differ from its start. Queueing an album is
usually segue search followed by one range.
Tags come from the index rather than from the file, so this doesn't touch the drive the music is on.
Playing a collection that isn't on this machine
The index keys every track by its path relative to the directory that was scanned, which is also how object stores hold them. Anything serving that same tree over http can be played from directly - mpv loads a url exactly as it loads a file, so the crossfade doesn't know the difference.
rclone is the easiest way to put one in front of a collection. It speaks to most places music might be kept - Backblaze B2, Amazon S3 and the other S3 compatible stores, Google Drive, Dropbox, an sftp host, or a directory on another machine:
rclone serve http remote:collection --addr localhost:8080 --vfs-cache-mode full --vfs-cache-max-size 20G
segue remote http://localhost:8080
segue remote off goes back to playing from local files, and segue remote on its own says which it is doing.
Whatever serves the collection has to expose it under the same relative paths the index was built from:
scanning a directory and serving that same directory is what makes a key like Artist/Album/01 Track.flac
resolve at both ends. Scan while the collection is attached, play from the url once it isn't.
Configuring a cache on that server is worth it. Crossfading opens the next track five seconds before the current one ends, which is not long to open a connection and buffer over it - so segue reads the start of the next track, and warms its album art, while the current one is still playing. A cache is what turns that into a track already sitting on local disk by the time the fade starts.
Nothing in segue authenticates. rclone serve is expected to be listening on localhost, holding the
credentials itself, which keeps them out of segue and out of the urls handed to mpv.
Tracks queued from a path rather than from the index are always played from where they sit, so a remote collection and a one-off local file can share a queue.
Adding tracks to the queue
segue queue folder_containing_audio_files audio_file.mp3 will place any number of audio files in the queue
and the player should immediately start playing the first track.
Viewing queue contents
segue list will list currently queued tracks with an estimated start time if the player is currently running
and playing a track.
Managing queue
segue clear will clear all queued tracks.
segue remove 2 will remove the queued track at index position 2.
segue swap 2 4 will swap the tracks at index positions 2 and 4.
Media controls
segue pause will pause, segue stop will stop and segue play will resume.
segue skip will fade out the current track and start the next one (unless the queue is empty).
Optional features
A number of features can be turned on/off while the player is running that will determine certain behaviour:
segue autoplay off will cause the player to stop and politely wait after the current track has finished.
segue autoplay on and tracks will start playing again.
segue crossfade off will turn off crossfading so new tracks will start once the previous one is completely
finished.
segue scrobble on will turn on last.fm scrobbling - you will require your own application api key and secret
to enable this.
Configuration
| Variable | Default | Purpose |
|---|---|---|
SEGUE_HOME |
~/.segue |
Where preferences, history and the queue are kept |
SEGUE_MPV |
mpv |
The mpv executable to launch |
Keeping all state under one directory means segue can be run alongside vlcraptor (or a second copy of itself,
with a different SEGUE_HOME) without the two fighting over the same queue.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests.
You can also run bin/console for an interactive prompt that will allow you to experiment.
The mpv IPC client is covered by specs that talk to a fake mpv over a unix socket, so the test suite does not require mpv to be installed.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update
the version number in version.rb, and then run bundle exec rake release, which will create a git tag for
the version, push git commits and the created tag, and push the .gem file to
rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/markryall/segue.