CLI
Commands
djctl provides several commands used to control its general operation. The following section provide an overview of each command and any accompanying flags.
For general djctl usage, the most important command of interest will be the start command.
completion
djctl can generate a shell completion file for bash, fish, powershell, and zsh. For detailed information on how to configure shell completion for a specific shell, please use the help
command.
For example, use the following command for bash instructions:
Example output:
help
Built-in help for commands and flags. Provides help for any command in the application.
Example usage:
Example output:
license
Decodes and displays information about a djctl license.
Example usage:
Example output:
probe
Performs StagelinQ discovery, searching for compatible Denon devices on the network. When discovered, connects to the StateMap service on the device and attempts to dump supported StateMap values.
Example usage:
In the above example, because the --log.file
flag was used, no output appears on the terminal. Instead, after several minutes, the command line prompt will return and the probe.txt
file will contain diagnostic information useful to the developer.
start
Launches djctl in server mode. This is the primary mode of operation.
The following track transition sources are supported:
- Denon
- DJUCED
- Dummy
- Serato (experimental)
Denon is the default source if the --source
flag is not used during launch.
The following “featured track” sinks/destinations are supported:
- Discord
- File
- OSC
- Twitch
- Webhook
- WebSocket
Most users will interact with the WebSocket sink indirectly by way of displaying a built-in “theme” in an OBS browser source window. It is always enabled.
The following section details notable features and flags used to control the behavior of the start
command.
Featured track algorithms (Denon)
The --detection.algorithm
flag allows selecting the Denon featured track detection algorithm. By default, this algorithm defaults to volume
. The other available algorithm is lead
.
The volume
algorithm promotes a track to “featured” state when it is the only audible track present in the mix. Other tracks that may have been playing during a transition must no longer be present in the mix. The volume threshold that defines whether a track is still in the mix is configurable using the --detection.volume.percent
flag. When lowered from its default of 100
, a track can become “featured” even when outgoing faders are still partially up. As long as all the other faders have dropped below a threshold (calculated as a percentage of the loudest track in the mix), a new track can be promoted to “featured.” To use this algorithm, set the --detection.algorithm=volume
flag. Please note that this is the default algorithm.
The lead
algorithm follows the active play state on a deck. A track is lead if you press play and no other track is also in the play state. When you engage play on a new track, this new track doesn’t transition into lead state until the other track has been stopped. To use this algorithm, set the --detection.algorithm=lead
flag.
The altlead
algorithm is similar to the lead
algorithm. It is intended as an experimental approach to support SC players without an X series mixer. To use this algorithm, set the --detection.algorithm=altlead
flag.
Track delay
The --delay
flag provides a delayed “hold” or “queue” mechanism for tracks before publishing to a “featured track” sink.
Set this to a non-zero value in order to avoid momentary track cuts triggering a published track transition event. If you cut the fader to perform “drops” or cut mixing and scratching, you will likely want to adjust this value.
For example, setting delay
to 3
would allow you to rapidly toggle the crossfader back and forth between channels without triggering a track transition. Instead, each new cut between channels preempts the last detected transition and resets the timer. Once no further transitions are detected within the 3 second window, the last detected transition is published to the “featured track” sink(s).
“Clean” metadata extraction (Denon)
djctl can attempt to extract “clean” metadata through the use of regular expression capture groups. This is supported for both the title and artist metadata using the corresponding --extract.regex.title
and --extract.regex.artist
flags.
Regular expressions are an advanced topic which will require non-trivial user effort to master. You have been warned.
When extracting a title, the capture group must be named title
and similarly when extracting an artist, it must be named artist
. No capture group names besides title
and artist
are detected by djctl.
The title
capture group name is expected when using --extract.regex.title
and similarly the artist
capture group name is expected when using --extract.regex.artist
. djctl will not launch if you supply either of these flags without the required capture group name present in the regular expression.
Capture group names are case sensitive. Use all lowercase; for example, ?P<title> and not ?P<Title>.
The following example attempts to extract a “clean” track title by ignoring track number, Camelot key, BPM, and file extension:
Please note the surrounding single quotes; this is important and should prevent the shell from escaping special characters.
The following table illustrates an original title and an extracted title using the aforementioned example regular expression.
Original | Extracted |
---|---|
03. Eli Brown - Escape (Original Mix) - 7A - 127.WAV | Eli Brown - Escape (Original Mix) |
Eli Brown - Escape (Original Mix) - 7A - 127.WAV | Eli Brown - Escape (Original Mix) |
- Escape (Original Mix) - 7A - 127.WAV | - Escape (Original Mix) |
The Space Between Feat. Laura Aqui (Assaf Remix) - 1A - 132 | The Space Between Feat. Laura Aqui (Assaf Remix) |
The Space Between Feat. Laura Aqui (Assaf Remix) - 1A - | The Space Between Feat. Laura Aqui (Assaf Remix) |
The Space Between Feat. Laura Aqui (Assaf Remix) - 1A | The Space Between Feat. Laura Aqui (Assaf Remix) |
The Space Between Feat. Laura Aqui (Assaf Remix) - | The Space Between Feat. Laura Aqui (Assaf Remix) |
The Space Between Feat. Laura Aqui (Assaf Remix) | The Space Between Feat. Laura Aqui (Assaf Remix) |
When developing and testing regular expression capture group extractions, please use the regex101.com web site in Golang mode. This will use the same extraction engine djctl uses internally.
Take caution with this feature as it is difficult to write a regular expression that can handle all possible cases with accuracy. Your time may be better spent fixing the actual track metadata.
Hiding (“DJ AM” mode) (Denon)
djctl supports two modes of track hiding. The simplest and most versatile is using the --hide.color
flag. The second and more advanced method is regular expression matching using the --hide.regex.artist
, --hide.regex.title
, --hide.regex.genre
, and --hide.regex.filename
flags.
Color (Denon)
If you would like the ability to dynamically hide tracks while DJing, use the --hide.color
flag. When the EngineOS deck color matches the specified --hide.color
flag value, djctl will hide the track information. When it no longer matches, the track information is revealed. You can toggle this color change while DJing, forcing a track to dynamically hide and unhide.
You can change the color of a deck using the "Deck Colors" screen within the EngineOS "User Profile" settings.
The following color names are recognized:
- red
- purple
- red
- orange
- yellow
- limegreen
- green
- lightblue
- blue
Regular expression (Denon)
Regular expressions are an advanced topic which will require non-trivial user effort to master. You have been warned.
You can also specify a regular expression to trigger track hiding with the --hide.regex.artist
, --hide.regex.title
, --hide.regex.genre
, and --hide.regex.filename
flags.
For example, you can automatically hide tracks whose track title metadata contains “[ID]” at the beginning with the following flag:
Please note that when any of the --hide.regex.*
flags encounter a match, all track metadata (title, artist, and art) will become hidden.
HTTP listener
The djctl start
command will automatically launch an HTTP listener on port 9090. If you need to change this for any reason, you can use the --http.addr
flag.
By default, the listener will bind to all addresses. You can restrict this to a specific address such as localhost. For example:
This may be preferred when operating on a “hostile” network that isn’t under your full control.
Please see the WebSocket API documentation for more information.
File outputs
djctl can sink featured track information to a file. The --outfile.featured
string should contain the file name destination of the featured track sink. This file will be overwritten each time a track transition event occurs. If this string is empty, no file sink updates will occur. Use the --outfile.featured
flag to enable this feature along with --outfile.format
to control the contents of the featured track file. Please see the substitution variables section for more information about constructing format specifiers.
To output album art, specify an --outfile.art
file location. The album art is always a 256x256 resolution PNG file. When no album art is unavailable, a 1-pixel transparent PNG file is written instead.
To output a historical log of tracks played, use the --history.filename
and --history.format
flags. During each track transition, a line will be appended to the file specified in --history.filename
. Use the --history.filename
flag to enable this feature along with --history.format
to control the contents of the history file. Please see the substitution variables section for more information about constructing format specifiers.
Substitution variables
djctl supports a basic substitution mechanism where variable strings such as $ARTIST$
and $SONG$
are replaced with artist and title metadata respectively. The default behavior uses $ARTIST$ - $SONG$
as the format string for both --outfile.format
and --history.format
flags. With this format string, the song “Just Can’t Get Enough” by the artist “Depeche Mode” outputs Depeche Mode - Just Can't Get Enough
.
The following table describes the substitution variables available for use with the --outfile.format
, --history.format
, --discord.format
, --twitch.format
, and --webhook.format
flags.
Variable | Description | Example output |
---|---|---|
$ARTIST$ | Track artist | Depeche Mode |
$SONG$ | Track title | Just Can’t Get Enough |
$GENRE$ | Track genre | New Wave |
$TIMESTAMP_YEAR$ | Year component of current time | 2022 |
$TIMESTAMP_MONTH$ | Zero-padded month component of current time | 03 |
$TIMESTAMP_DAY$ | Zero-padded day component of current time | 01 |
$TIMESTAMP_HOUR$ | Zero-padded hour component of current time | 09 |
$TIMESTAMP_MINUTE$ | Zero-padded minute component of current time | 22 |
$TIMESTAMP_SECOND$ | Zero-padded second component of current time | 49 |
$ELAPSED$ | Elapsed time since first track in current history | 00:01:24 |
The following table provides example format strings along with example output.
Format string | Example output |
---|---|
$ARTIST$ - $SONG$ | Depeche Mode - Just Can’t Get Enough |
$TIMESTAMP_HOUR$:$TIMESTAMP_MINUTE$:$TIMESTAMP_SECOND$ - $ARTIST$ - $SONG$ | 20:07:43 - Depeche Mode - Just Can’t Get Enough |
Discord
This is an experimental feature.
djctl can sink featured track information to a Discord channel. Use the --discord.token
, --discord.channel
, and --discord.format
flags to configure. This documentation will be updated at a later date with detailed setup instructions.
Twitch
This is an experimental feature available to licensed users only.
Activate the Twitch extension on your Twitch channel.
Please see the Twitch setup section of the documentation for information on acquiring the API key required to configure this integration.
djctl can sink featured track information to the djctl Twitch extension. Use the --twitch.api_key
and --twitch.format
flags to configure.
This documentation will be updated at a later date with detailed setup instructions. Please join the Discord support chat for “white glove” assistance setting this up.
Open Sound Control (OSC)
This is an experimental feature.
Documentation coming soon.
CUE sheet
This is an experimental feature.
To facilitate uploading of track listing data to Mixcloud, djctl can perform CUE sheet generation.
Use --cue.filename
to output a CUE formatted track log to the specified file. To supply CUE header fields, use --cue.header.file
, --cue.header.filetype
, --cue.header.performer
, and --cue.header.title
.
For example, the following flags will generate a CUE sheet file.
The following is an example CUE sheet generated with djctl.
Please note, the 00:00:00 time marker starts when the first featured track is observed.
Spotify
This is an experimental feature available to licensed users only.
For users with access to a Spotify Premium account, djctl can augment track metadata with a Spotify Code. The integration currently leverages the client credentials authentication flow which requires a Client ID and Client Secret to generate authentication tokens. To create a Spotify Client ID and Client Secret, follow these steps:
- Visit https://developer.spotify.com/dashboard/applications.
- Authenticate with your Spotify Premium account.
- Click “Create an app”.
- Enter “djctl” in the “App name” field.
- Enter “dj control” in the “App description” field.
- Select the checkboxes and submit.
Once created, the “Client ID” is displayed. Click on “Show client secret” to reveal the “Client secret” field. These values will need to be passed as parameters to djctl using the --spotify.id
and --spotify.secret
parameters. Both are required to successfully authenticate to the Spotify API.
Treat the client ID and secret as credentials. Never share them with anyone.
The Spotify Code visual format can be customized using the --spotify.barcolor
, --spotify.bgcolor
, and --spotify.width
parameters. The default Spotify Code is a white bar code on a black background. The image width is 256 pixels in order to match the width of the track art. You are free to override these values to match other use cases and aesthetics.
For the --spotify.barcolor
option, either the value white
or black
are valid. The --spotify.bgcolor
option should be specified as a three digit hex representation of an RGB color. Please omit the #
character; for example, the color #0099cc
should be passed as --spotify.bgcolor=0099cc
. The width of the image can also be specified using the --spotify.width
parameter. The height is not configurable and is a fixed ratio based upon the width.
Because the generation of a Spotify Code requires several API calls to remote systems, a default timeout of 4 seconds is enforced. This can be overriden with the --spotify.timeout
parameter.
All Spotify Codes are cached for the duration of the djctl process lifetime. Practically speaking, this allows djctl to avoid excessive requests to the Spotify API. It also means that djctl memory consumption will slowly grow during long DJ sessions as the cache grows. Future versions of djctl may allow expiration of this cache during the process lifetime.
Currently, the SliderSpotify
theme supports display of Spotify Codes. To enable this theme, use the --theme.dir=./themes/SliderSpotify/
option.
Targets (Denon)
If you have multiple Denon devices present on your network, you may wish to use the --target.device
and --target.software
flags to target a specific device. In most cases, you will never find the need to use this flag.
For example, the Denon Prime 4 presents itself as the prime4
device running software JC11
. See the example below for an example of how to target this device when launching djctl.
Device and software names are case sensitive.
Themes
A small number of themes are embedded within the djctl binary. You can switch between them using the --theme.internal
flag. Valid themes included default
, text
, slider
, sliderspotify
, artleft
, artright
, sliderartleft
, and sliderartright
. The HTML, CSS, and Javascript source for each of these themes is included in the examples/themes
directory. To use a customized theme, use the --theme.dir
flag to specify the root of the custom theme directory.
For example, the following command will instruct djctl to serve a custom theme located in the themes/CoolTheme/
directory directly below the current working directory.
By default, djctl will use the default
internal theme (--theme.internal=default
flag). Please note that the presence of --theme.dir
overrides the --theme.internal
flag.
Placeholders
The --placeholder.art.internal
flag allows selection of a “placeholder” track art image to use when art metadata is unavailable. Valid placeholder art names include pixel
and note
. The pixel
image is a 1 pixel transparent PNG while the note
image is a music note.
Webhook
djctl can be configured to send a webhook during track transition events. The following example will configure djctl to send webhooks to http://127.0.0.1:9091/webhook/
after each track transition event:
Please see the Webhook API documentation for more information.
twitch
Twitch-related commands to setup the djctl Twitch extension.
This is an experimental feature available to licensed users only.
Example usage:
When invoking the twitch setup
command, a Twitch OAuth token is obtained and subsequently exchanged for a djctl Twitch extension API key.
Example:
Treat the Twitch API key as a sensitive credential. Never share it with anyone.
version
Shows djctl build and version information.
Example output:
Global flags
All commands provide a common set of global flags as described in the following sections.
Logging
djctl output is entirely composed of diagnostic log messages. You can control the verbosity of these log messages using the --log.level
flag. The following log levels are available:
- debug
- info
- warn
- error
- fatal
By default, djctl runs with a logging verbosity of info
.
Log messages can be output in either plain text format or in a structured JSON format.
The default text log event is semi-structured into key/value pairs. For example:
With the --log.format=json
flag, log messages can be emitted in JSON format. For example:
For diagnostic purposes, you can also include the source code filename and line number information in the logs. This is controlled through the use of the --log.line
flag which by default is not enabled. Notice the _source
field the following example:
Finally, to output logs to a file, use the --log-file
flag to specify a file path. When this flag is used, no output will appear on the terminal screen.
Configuration file
djctl supports the following configuration file formats:
Format | Extension(s) |
---|---|
JSON | json |
TOML | toml |
YAML | yaml, yml |
HCL | hcl, tfvars |
Java config properties | properties, props, prop |
envfile | dotenv, env |
INI | ini |
Please see the example YAML file in the djctl examples/
directory. When crafting a configuration file, the file format will follow the same hierarchy used in the CLI command flags. For example, --log.file=logs.txt
would be expressed as the following YAML:
To instruct djctl to use a configuration file, use the --conf
flag to specify its location. The default behavior of djctl is to search the current working directory for a file named conf
with an extension of the aforementioned configuration file formats. For example, djctl will automatically search for a file named conf.yaml
.
Flags passed via the CLI will override flags found in the configuration file.
License
To use your personal license, please launch djctl with the --license.key
command-line parameter followed by the license key text enclosed in double quotes. For example:
Please see the configuration file section for information on how to create a configuration file where you can permanently place your license key.