cyanreg/cyanrip

Bule-ish CD ripper

C

419

504 commits

updated Oct 16, 2026

See the code

README

cyanrip

Fully featured CD ripping program able to take out most of the tedium. Fully accurate, has advanced features most rippers don't, yet has no bloat and is cross-platform.

Features

Installation

Alpine Linux

apk add cyanrip

Archlinux

pacaur -S cyanrip

Or use your favorite AUR installation method.

Debian (and derivatives)

apt install cyanrip

OpenSUSE

zypper install cyanrip

Void Linux

xbps-install -S cyanrip

FreeBSD

pkg install cyanrip

Or via ports: cd /usr/ports/audio/cyanrip && make install clean.

NixOS

nix-env -iA nixos.cyanrip

Docker

docker pull ep76/cyanrip

Automated Windows builds Windows CI

Latest release Windows build

Latest Windows build

If the latest build is broken, you can find older ones in the nightly release page

Compiling

Complete list of dependencies:

  • FFmpeg (at least 4.0, libavcodec, libswresample, libavutil, libavformat, libavfilter)
  • libcdio-paranoia
  • libmusicbrainz5
  • libcurl

Optional dependencies:

  • libqrencode (to print MusicBrainz submission URLs as scannable QR codes)
  • libchromaprint (to fingerprint tracks for AcoustID)

All are available on any up-to-date Linux distribution's package repositories. To compile and install on any *NIX platform:

meson build

ninja -C build

sudo ninja -C build install

cyanrip can be also built and ran under Windows using MinGW

Flatpak

You can build and install with flatpak. The first 2 steps only need to be done once.

flatpak install -y flathub org.flatpak.Builder

flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo

flatpak run --command=flathub-build org.flatpak.Builder --install com.github.cyanreg.cyanrip.yaml

flatpak run com.github.cyanreg.cyanrip

CLI

Arguments are optional, except -s. By default cyanrip will rip all tracks from the default CD drive, output to flac only, enables all cd-paranoia error checking, performs a MusicBrainz lookup, and downloads and embeds the cover art if one is found.

ArgumentDescription
Ripping options
-d stringThe path or name for a specific device, otherwise uses the default device
-s intSpecifies the CD drive offset in samples (same as EAC, default is 0)
-r intSpecifies how many times to retry a frame/ripping if it fails, (default is 10)
-Z intRips tracks until their checksums match <int> number of times. For very damaged CDs.
-S intSets the drive speed if possible (default is unset, usually maximum)
-p number=stringSpecifies what to do with the pregap, syntax is described below
-P intSets the paranoia level, default is max, 0 disables checking completely
-OOverread into lead-in/lead-out areas, if unsupported by drive may freeze ripping
-HEnable HDCD decoding, read below for details
-EForce CD deemphasis, for CDs mastered with preemphasis without actually signalling it
-WDisable automatic CD deemphasis. Read below for details.
-KDisable ReplayGain tag generation. Read replaygain for details.
-XSkip data tracks rather than ripping them, read below for details
Output options
-o listComma separated list of output formats (encodings). Use "help" to list all. Default is flac
-b intBitrate in kbps for lossy formats, 256 by default
-D stringDirectory naming scheme, see below
-F stringFile naming scheme, see below
-L stringLog naming scheme, see below
-M stringCUE file naming scheme, see below
-l listComma separated list of track numbers to rip, (default is it rips all)
-T stringFilename sanitation, default is unicode, see below
Metadata options
-IOnly print CD metadata and information, will not rip or eject the CD
-a stringAlbum metadata, syntax is described below
-t number=stringTrack metadata, syntax is described below
-R int or stringSets the MusicBrainz release to use, as an index from 1 or an ID, read below
-c int/intTag multi-disc albums as such, syntax is disc/totaldiscs, read below
-C path or urlSets cover image to embed into each track, syntax is described below
-NDisables MusicBrainz lookup and ignores lack of manual metadata to continue
-ADisables AccurateRip database query and comparison
-BDisables AcoustID fingerprinting, read below for details
-k stringAcoustID user API key, to submit fingerprints of verified rips, read below
-UDisables Cover art DB database query and retrieval
-mLookup cover art with max size: 250, 500, 1200, -1 (no limit, default)
-GDisables embedding of cover art images
-JOnly generate and print a CUE sheet, without ripping. Incompatible with -I
Misc. options
-QEject CD tray if ripping has been successfully completed
-Y fileVerify that a rip log's checksum matches its contents
-vPrint version
-hPrint usage (this)
-fFind drive offset (requires a disc with an AccuRip DB entry)

Metadata

If the disc is on MusicBrainz under several releases, cyanrip lists them, and -R picks one, by its index in the list or its ID.

-R also takes the ID of a release the disc isn't attached to, such as a release whose disc isn't on MusicBrainz yet, or a pseudo-release with translated titles. The release's tracks are then matched to the disc's in order. Of a multi-disc release, the disc with as many tracks as this one is used, or the one given via -c. Fingerprints of such rips are never submitted to AcoustID, as nothing ties the disc to the release.

In case the MusicBrainz database doesn't contain the disc information, is incomplete, or incorrect, you can manually add metadata via the -a argument for album metadata and -t argument for track metadata:

-a album="Name":album_artist="Artist":date="2018":random_tag="Value"

-t 1=artist="Track Artist":lyrics="Name":random_tag="Value" -t 3=artist="Someone Else"

All key=value pair tags must be separated by :. For track tags, the syntax is -t track_number=key=value:key=value. You need to specify the -t argument separately for each track. To use : or = inside a value, escape it with a backslash: -t "1=title=One\: Two".

For convenience, if any of the first 2 metadata tags of tracks are missing a key, such as with -t 2=some_title:some_artist:key=value, cyanrip will automatically prepend title= and artist= such that it becomes -t title=some_title:artist=some_artist:key=value. A missing key in tag 1 is always considered a title while a missing key in tag 2 is always considered artist, so either can be skipped with no effect.

The same goes for album tags, with album= and album_artist= being omitable.

For album tags, if either artist or album_artist are unset, their values will be mirrored if one is available.

The precedence of tags is Track tags > Album tags > MusicBrainz tags.

Output

The output encoding(s) can be set via the -o option as a comma-separated list. Currently, the following formats are available:

Format nameDescriptionExtensionCover art embeddingNotes
flacStandard FLAC files.flac✔️Always uses maximum compression
ttaTTA (True Audio) files.tta⬜Always uses maximum compression
opusStandard Opus files (in an Ogg container).opus⬜VBR, use -b to adjust the bitrate, default is 256 (kbps)
aacStandard AAC files.aac⬜Use -b to adjust the bitrate, default is 256 (kbps)
wavpackStandard lossless WavPack files.wv⬜Always uses maximum compression
alacStandard ALAC files.alac⬜Always uses maximum compression
mp3Standard MP3 files.mp3✔️VBR, use -b to adjust the bitrate, default is 256 (kbps)
vorbisStandard Ogg/Vorbis files (in an OGG container).ogg⬜Use -b to adjust the bitrate, default is 256 (kbps)
wavStandard WAV files.wav⬜16-bit little endian signed audio, or 32-bit in HDCD mode
alac_mp4Standard MP4 files (with ALAC encoding).mp4✔️Always uses maximum compression
aac_mp4Standard MP4 files (with AAC encoding).mp4✔️Use -b to adjust the bitrate, default is 256 (kbps)
opus_mp4Standard MP4 files (with Opus encoding).mp4✔️Use -b to adjust the bitrate, default is 256 (kbps)
pcmRaw audio, 16-bits, two channel, little-endian.raw⬜

For example, to make both FLAC and MP3 files simultaneously, use -o flac,mp3. Encodings are done in parallel during ripping, so adding more does not slow down the process.

To adjust the directories and filenames, read the naming scheme section below.

Pregap handling

By default, track 1 pregap is ignored, while any other track's pregap is merged into the previous track. This is identical to EAC's default behaviour.

You can override what's done with each pregap on a per-track basis using the -p track_number=action argument. This argument must be specified separately for each track.

actionDescription
defaultMerge into previous track, drop on track 1
dropDrop the pregap entirely
mergeMerge into current track
trackSplit into a new track before the current

If the pregap offset isn't available for a given track, this argument will do nothing.

Splitting off track 1's pregap, the hidden track of discs which have one, gives it its own file as track 0. As CUE sheets have no track 0, the sheet gives that file as track 1's INDEX 00.

cyanrip guarantees that there will be no discontinuities between tracks, unless the drop action is used to delete a pregap.

Data tracks

Mixed mode CDs and Enhanced CDs (CD-Extra) carry one or more data tracks alongside the audio. cyanrip rips those too, as raw 2352 byte sectors written to a .bin file next to the audio tracks, and references them from the generated CUE sheet, as MODE1/2352, or MODE2/2352 for the CD-ROM XA tracks of Enhanced CDs. Sectors are read whole, with their sync pattern, header and EDC/ECC intact, so the result is what a disc image would contain rather than just the 2048 bytes of user data per sector.

Data tracks are read directly rather than through cd-paranoia, which only knows how to read audio. There is no drive offset correction: a data sector is addressed by its own header, so unlike audio it is never off by a fraction of a sector. Damaged sectors are retried as many times as -r allows, and a sector that never reads is written out as zeroes and counted as an error. Every sector is also checked against its EDC, as some drives return damaged sectors without reporting an error, and the log says how many matched. One that never does is kept as read, and counted as an error.

A data track's own pregap is dropped by default, as it holds no user data. Pass -p track_number=merge to prepend it to the .bin instead, which the CUE sheet will reflect. The pregap handling section covers the rest.

Pass -X to skip data tracks entirely. The CUE sheet will still describe them, so it will reference a .bin that was never written.

Cover art embedding

cyanrip supports embedding album and track cover art.

To embed cover art for the whole album, specify it with the -C path or -C destination=path parameter. path can be a URL, in which case it will be automatically downloaded.

If destination is a number, the cover art will be embedded only for the track with that number. Otherwise, destination should be a descriptor like Front or Back or Disc. If destination is omitted, Front, then Back will be used.

Cover arts which are not attached to a track will be copied to each output directory as destination with an autodetected extension.

If multiple cover arts are present and no track cover art is specified, only the cover art with Front destination will be embedded, or the first cover art specified if no Front exists. Otherwise, only the specified track cover art will be embedded.

Cover art downloading

If a release ID is specified or detected, and no Front or Back cover arts were specified, a query will be made to the Cover Art Archive and if found, the archive cover art will be downloaded and used.

Multi-disc albums

cyanrip supports ripping multi-disc albums in the same output folder. To enable this manually, specify the -c argument followed by disc/totaldiscs (/totaldiscs is optional), otherwise it'll be done automatically if the MusicBrainz tags indicate so.

The track filenames will be disc.track - title.ext. The logfile will be Album name CD<disc>.log.

As well as using the -c argument, you can also specify the disc=number:totaldiscs=number in the album/track metadata.

If each disc has a title, you should use the discname tag if you're manually setting tags, which is what MusicBrainz will set if available.

HDCD decoding

cyanrip can decode and detect HDCD encoded discs. To check if a suspected disc contains HDCD audio, rip a single track using the -l 1 argument and look at the log. A non-HDCD encoded disc will have:

HDCD detected: no

If the CD does contain HDCD audio something similar to the following will be printed:

HDCD detected: yes, peak_extend: never enabled, max_gain_adj: 0.0 dB, transient_filter: not detected, detectable errors: 0

Should a track be detected as HDCD, it would be safe to proceed decoding all of the disc. The resulting encoded files will have a bit depth of at least 24 bits.

Deemphasis

Old (and not so old) CDs may require deeemphasis. cyanrip is able to detect such discs (using both the TOC and track subcode) and will apply a correction filter automatically. To check whether the CD contains emphasised audio, you can simply run cyanrip -I and read the printout.

Preemphasis:      <status> <action>

for each track.

status can be either none detected or present (TOC) or present (subcode).

Action may be either (deemphasis applied), which applies a deemphasis filter to the audio (default), (deemphasis forced) which does the same, even if no preemphasis is signalled (can be activated via the -E flag, or blank, which deactivates automatic deemphasis, preserving audio data as-is (activated via the -W flag).

The -E flag can be useful for some CDs, which may have been mastered with preemphasis, but don't actually signal it via the track substream properties.

An incomplete list of releases mastered with preemphasis can be found at this wiki page.

ReplayGain

cyanrip will automatically compute ReplayGain tags and add them to all files while ripping. Note, that this requires to hold all compressed audio data for the entire CD in RAM while ripping, which may be from 300 to 600 megabytes, depending on the output used. Low-power and low-RAM devices can turn this off via the -K switch, along with AcoustID fingerprinting via -B, which needs the same.

The tags generated are ReplayGain 2.0 compliant, which is backwards-compatible with ReplayGain 1.0. The true peak value is calculated and used.

AcoustID

When built with libchromaprint, cyanrip computes an AcoustID fingerprint of every audio track while ripping. Like fpcalc and MusicBrainz Picard, it fingerprints the first 2 minutes of each track.

If the whole disc checks out, the fingerprints are submitted to AcoustID, each linked to its MusicBrainz recording. Every audio track must be accurately ripped according to AccurateRip, and must have a MusicBrainz recording within 30 seconds of the track's length. Submitting needs your own user API key, found on your AcoustID account page and given via -k. Nothing is submitted without it.

Otherwise, the fingerprints are saved in the files' tags instead, in the same tag Picard uses: ACOUSTID_FINGERPRINT, or TXXX:Acoustid Fingerprint for MP3. Picard submits a fingerprint it finds there, rather than computing it again. MP4 based outputs don't get the tag, as FFmpeg can't write freeform iTunes tags.

Whether to submit or tag is only known once the whole disc is ripped, so like ReplayGain, this holds the compressed audio in RAM until the end. -B disables fingerprinting.

Paranoia level

cyanrip can apply four levels of cdparanoia error detection and correction:

ArgumentDescriptionPurposecdparanoia CLI equivalent
-P 0 or noneDisabledFastest ripping with no error correction-Z
-P 1Overlapped readsCorrect errors when optical drives skip sectors while reading audio discs-Y
-P 2Overlapped and verified readsRe-read sectors to correct for optical drives that supply inconsistent audio datan/a
-P 3 or maxAll paranoia featuresAt present, same as -P 2, but includes future cdparanoia improvementsdefault

Paranoia status count

At the end of the ripping process, cyanrip will print and log a summary of cdparanoia's status during ripping. This can be used to estimate the disc/drive's health.

An idealized disc and drive will only log READ: $number$ and nothing else. This happens while ripping from a file. In general READ/VERIFY/OVERLAP are normal and will happen when ripping a brand new CD with a new drive. FIXUP_EDGE/FIXUP_ATOM usually happen if cdparanoia is somewhat struggling, but both are recoverable and lossless. FIXUP_DROPPED/FIXUP_DUPED indicate more severe errors, but are still recoverable and lossless, though a hard read error will often follow. READERR indicates that cdparanoia gave up after all retries and outputted zeroes for all samples it couldn't recover.

Naming scheme

cyanrip supports highly flexible naming schemes via a custom syntax. You can extensively customize how all files and directories are named.

The default naming scheme for albums is Album name [Format] if the releasecomment tag is empty or Album name (Release comment) [Format] if it isn't. For tracks, its Track number - Track title.Extension if there's a single disc in the album or Disc Number.Track number - Track title.Extension if there are multiple. The log file will be named Album name.log in each of the output folders unless there are multiple CDs in the album, in which case it'll be Album name CD1.log for the first CD and so on.

If you would like something different, read on. If for a one-off you'd like to specify a different directory name, you can just use -D Directory and not read further.

The syntax is as follows: everything not inside { or } tags gets copied as-is unconditionally. Everything inside { or } tags is interpreted: if what's inside the tags matches a metadata key, the tag along with its outer brackets is replaced as-is. Otherwise only the tag brackets are removed and what's inside is copied literally.

Conditions are possible and must follow this syntax: {if #token1# != #token2#album name is |album|}. Condition tokens must be wrapped in # tags, and both must exist. In between the 2 tokens must be either > or < or == or !=. If any of the tokens inside the # tags matches a metadata key, it is replaced with a value, otherwise its taken literally (so if the album tag exists, #album# resolves to the album name, otherwise to just album).

If the condition is a direct comparison (== or !=), then the 2 tokens are compared as strings. If arithmetic comparison is used and the 2 tokens are integers, they're compared arithmetically.

If an arithmetic comparison is used when both tokens are strings, the result of strcmp is used. If only one is a string, its pointer (always above 0, unless the token did not match a metadata key, in which case 0) is used.

If the condition is true, everything after the last token's # is copied, with any metadata tags there wrapped with |. Otherwise, nothing is copied. Braces don't nest: inside a condition, a tag is written as |year|, never as {year}, and cyanrip refuses schemes which try.

Examples are easier to understand, by default the folder value of {album}{if #releasecomment# > #0# (|releasecomment|)} [{format}] is used. This resolves to Album [FLAC] if there's nothing in the releasecomment key, or Album (Release comment) [FLAC] if there is.

The default track file name syntax is: {if #totaldiscs# > #1#|disc|.}{track} - {title}. So this resolves to 1 - Title.flac if there's a single CD, or 1.1 - Title.flac if there are more than 1 CDs and you're ripping the first one.

The track number is only zero-padded to the number of digits the disc's track count needs: 1 on a disc of 9 tracks, but 01 on one of 12. For two digits regardless, use {if #tracktotal# < #10#0}{track}.

A useful example is to have separate directories for each disc: -D "{album}{if #totaldiscs# > #1# CD|disc|} [{format}]" -F "{track} - {title}".

Characters a file name can't hold are replaced in the literal text of a scheme too, except for the drive letter of an absolute Windows path, as in -D "D:/Music/{album}". Use / to separate directories.

Whitespace at the edges of every path component, and between the file name and its extension, is trimmed. Conditional bodies containing spaces (like the example above, when used as its own subdirectory) would otherwise leave dangling spaces on one of their branches.

Besides any tags given via -a and -t, these metadata keys are available:

KeyValue
album, album_artist, date, releasecommentThe release's, from MusicBrainz
yearThe year part of date
label, catalognumber, barcode, country, packaging, releasestatusThe release's, from MusicBrainz
disc, totaldiscs, discnameThe disc's position in the release, and its title if it has one
track, tracktotalThe track's number (padded as described above), and the disc's track count
title, artist, isrcThe track's
mbid, musicbrainz_trackidThe track's MusicBrainz recording ID, the latter being the tag taggers and players read it from
musicbrainz_albumid, musicbrainz_discid, cddb, disc_mcnThe release and disc IDs, and the barcode the disc itself carries
formatThe output format, e.g. FLAC

The ripping log name and location can be modified via the -L argument. By default its set to {album}{if #totaldiscs# > #1# CD|disc|}, which resolves to Album name.log for 1 CD and Album name CD1.log if there are multiple CDs and you're ripping the first.

Filename sanitation

If invalid symbols are found in a file or a folder, such as : or /, the symbol is by default substituted with a unicode lookalike, such as ∶ or ∕ respectively. If this is undesirable, this can be overridden via the -T simple argument. This will replace all invalid symbols with _. In case you're on an operating system with more liberal allowance on filenames, you can use the -T os_unicode option to allow symbols like : not supported on Windows to be passed through. Note that this will make files like these not accessible on Windows, unless renamed, so use this only if you're sure.

CUE sheet

cyanrip will generate a CUE sheet from which a byte-exact duplicate of the disc can be made. By default, pregaps are kept in the CUE sheet as being appended to the previous track (except for the first track, where the pregap is dropped and signalled as silence). This is reffered to as "noncompliant" by hydrogenaudio.

Data tracks are referenced as BINARY files holding MODE1/2352 or MODE2/2352 sectors, unless skipped with -X, in which case the CUE sheet still names a file that isn't there.

Custom changes in the way pregaps are handled will be reflected in the CUE file. For example, dropping a pregap will signal silence in the CUE sheet. Appending a pregap to the track will accordingly mark the track as having two audio indices.

Links

You can talk about the project and get in touch with developers on:

cd
cdparanoia
ffmpeg
flac
musicbrainz

cyanreg/cyanrip

Bule-ish CD ripper

C

419

504 commits

updated Oct 16, 2026

See the code

README

cyanrip

Fully featured CD ripping program able to take out most of the tedium. Fully accurate, has advanced features most rippers don't, yet has no bloat and is cross-platform.

Features

Installation

Alpine Linux

apk add cyanrip

Archlinux

pacaur -S cyanrip

Or use your favorite AUR installation method.

Debian (and derivatives)

apt install cyanrip

OpenSUSE

zypper install cyanrip

Void Linux

xbps-install -S cyanrip

FreeBSD

pkg install cyanrip

Or via ports: cd /usr/ports/audio/cyanrip && make install clean.

NixOS

nix-env -iA nixos.cyanrip

Docker

docker pull ep76/cyanrip

Automated Windows builds Windows CI

Latest release Windows build

Latest Windows build

If the latest build is broken, you can find older ones in the nightly release page

Compiling

Complete list of dependencies:

  • FFmpeg (at least 4.0, libavcodec, libswresample, libavutil, libavformat, libavfilter)
  • libcdio-paranoia
  • libmusicbrainz5
  • libcurl

Optional dependencies:

  • libqrencode (to print MusicBrainz submission URLs as scannable QR codes)
  • libchromaprint (to fingerprint tracks for AcoustID)

All are available on any up-to-date Linux distribution's package repositories. To compile and install on any *NIX platform:

meson build

ninja -C build

sudo ninja -C build install

cyanrip can be also built and ran under Windows using MinGW

Flatpak

You can build and install with flatpak. The first 2 steps only need to be done once.

flatpak install -y flathub org.flatpak.Builder

flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo

flatpak run --command=flathub-build org.flatpak.Builder --install com.github.cyanreg.cyanrip.yaml

flatpak run com.github.cyanreg.cyanrip

CLI

Arguments are optional, except -s. By default cyanrip will rip all tracks from the default CD drive, output to flac only, enables all cd-paranoia error checking, performs a MusicBrainz lookup, and downloads and embeds the cover art if one is found.

ArgumentDescription
Ripping options
-d stringThe path or name for a specific device, otherwise uses the default device
-s intSpecifies the CD drive offset in samples (same as EAC, default is 0)
-r intSpecifies how many times to retry a frame/ripping if it fails, (default is 10)
-Z intRips tracks until their checksums match <int> number of times. For very damaged CDs.
-S intSets the drive speed if possible (default is unset, usually maximum)
-p number=stringSpecifies what to do with the pregap, syntax is described below
-P intSets the paranoia level, default is max, 0 disables checking completely
-OOverread into lead-in/lead-out areas, if unsupported by drive may freeze ripping
-HEnable HDCD decoding, read below for details
-EForce CD deemphasis, for CDs mastered with preemphasis without actually signalling it
-WDisable automatic CD deemphasis. Read below for details.
-KDisable ReplayGain tag generation. Read replaygain for details.
-XSkip data tracks rather than ripping them, read below for details
Output options
-o listComma separated list of output formats (encodings). Use "help" to list all. Default is flac
-b intBitrate in kbps for lossy formats, 256 by default
-D stringDirectory naming scheme, see below
-F stringFile naming scheme, see below
-L stringLog naming scheme, see below
-M stringCUE file naming scheme, see below
-l listComma separated list of track numbers to rip, (default is it rips all)
-T stringFilename sanitation, default is unicode, see below
Metadata options
-IOnly print CD metadata and information, will not rip or eject the CD
-a stringAlbum metadata, syntax is described below
-t number=stringTrack metadata, syntax is described below
-R int or stringSets the MusicBrainz release to use, as an index from 1 or an ID, read below
-c int/intTag multi-disc albums as such, syntax is disc/totaldiscs, read below
-C path or urlSets cover image to embed into each track, syntax is described below
-NDisables MusicBrainz lookup and ignores lack of manual metadata to continue
-ADisables AccurateRip database query and comparison
-BDisables AcoustID fingerprinting, read below for details
-k stringAcoustID user API key, to submit fingerprints of verified rips, read below
-UDisables Cover art DB database query and retrieval
-mLookup cover art with max size: 250, 500, 1200, -1 (no limit, default)
-GDisables embedding of cover art images
-JOnly generate and print a CUE sheet, without ripping. Incompatible with -I
Misc. options
-QEject CD tray if ripping has been successfully completed
-Y fileVerify that a rip log's checksum matches its contents
-vPrint version
-hPrint usage (this)
-fFind drive offset (requires a disc with an AccuRip DB entry)

Metadata

If the disc is on MusicBrainz under several releases, cyanrip lists them, and -R picks one, by its index in the list or its ID.

-R also takes the ID of a release the disc isn't attached to, such as a release whose disc isn't on MusicBrainz yet, or a pseudo-release with translated titles. The release's tracks are then matched to the disc's in order. Of a multi-disc release, the disc with as many tracks as this one is used, or the one given via -c. Fingerprints of such rips are never submitted to AcoustID, as nothing ties the disc to the release.

In case the MusicBrainz database doesn't contain the disc information, is incomplete, or incorrect, you can manually add metadata via the -a argument for album metadata and -t argument for track metadata:

-a album="Name":album_artist="Artist":date="2018":random_tag="Value"

-t 1=artist="Track Artist":lyrics="Name":random_tag="Value" -t 3=artist="Someone Else"

All key=value pair tags must be separated by :. For track tags, the syntax is -t track_number=key=value:key=value. You need to specify the -t argument separately for each track. To use : or = inside a value, escape it with a backslash: -t "1=title=One\: Two".

For convenience, if any of the first 2 metadata tags of tracks are missing a key, such as with -t 2=some_title:some_artist:key=value, cyanrip will automatically prepend title= and artist= such that it becomes -t title=some_title:artist=some_artist:key=value. A missing key in tag 1 is always considered a title while a missing key in tag 2 is always considered artist, so either can be skipped with no effect.

The same goes for album tags, with album= and album_artist= being omitable.

For album tags, if either artist or album_artist are unset, their values will be mirrored if one is available.

The precedence of tags is Track tags > Album tags > MusicBrainz tags.

Output

The output encoding(s) can be set via the -o option as a comma-separated list. Currently, the following formats are available:

Format nameDescriptionExtensionCover art embeddingNotes
flacStandard FLAC files.flac✔️Always uses maximum compression
ttaTTA (True Audio) files.tta⬜Always uses maximum compression
opusStandard Opus files (in an Ogg container).opus⬜VBR, use -b to adjust the bitrate, default is 256 (kbps)
aacStandard AAC files.aac⬜Use -b to adjust the bitrate, default is 256 (kbps)
wavpackStandard lossless WavPack files.wv⬜Always uses maximum compression
alacStandard ALAC files.alac⬜Always uses maximum compression
mp3Standard MP3 files.mp3✔️VBR, use -b to adjust the bitrate, default is 256 (kbps)
vorbisStandard Ogg/Vorbis files (in an OGG container).ogg⬜Use -b to adjust the bitrate, default is 256 (kbps)
wavStandard WAV files.wav⬜16-bit little endian signed audio, or 32-bit in HDCD mode
alac_mp4Standard MP4 files (with ALAC encoding).mp4✔️Always uses maximum compression
aac_mp4Standard MP4 files (with AAC encoding).mp4✔️Use -b to adjust the bitrate, default is 256 (kbps)
opus_mp4Standard MP4 files (with Opus encoding).mp4✔️Use -b to adjust the bitrate, default is 256 (kbps)
pcmRaw audio, 16-bits, two channel, little-endian.raw⬜

For example, to make both FLAC and MP3 files simultaneously, use -o flac,mp3. Encodings are done in parallel during ripping, so adding more does not slow down the process.

To adjust the directories and filenames, read the naming scheme section below.

Pregap handling

By default, track 1 pregap is ignored, while any other track's pregap is merged into the previous track. This is identical to EAC's default behaviour.

You can override what's done with each pregap on a per-track basis using the -p track_number=action argument. This argument must be specified separately for each track.

actionDescription
defaultMerge into previous track, drop on track 1
dropDrop the pregap entirely
mergeMerge into current track
trackSplit into a new track before the current

If the pregap offset isn't available for a given track, this argument will do nothing.

Splitting off track 1's pregap, the hidden track of discs which have one, gives it its own file as track 0. As CUE sheets have no track 0, the sheet gives that file as track 1's INDEX 00.

cyanrip guarantees that there will be no discontinuities between tracks, unless the drop action is used to delete a pregap.

Data tracks

Mixed mode CDs and Enhanced CDs (CD-Extra) carry one or more data tracks alongside the audio. cyanrip rips those too, as raw 2352 byte sectors written to a .bin file next to the audio tracks, and references them from the generated CUE sheet, as MODE1/2352, or MODE2/2352 for the CD-ROM XA tracks of Enhanced CDs. Sectors are read whole, with their sync pattern, header and EDC/ECC intact, so the result is what a disc image would contain rather than just the 2048 bytes of user data per sector.

Data tracks are read directly rather than through cd-paranoia, which only knows how to read audio. There is no drive offset correction: a data sector is addressed by its own header, so unlike audio it is never off by a fraction of a sector. Damaged sectors are retried as many times as -r allows, and a sector that never reads is written out as zeroes and counted as an error. Every sector is also checked against its EDC, as some drives return damaged sectors without reporting an error, and the log says how many matched. One that never does is kept as read, and counted as an error.

A data track's own pregap is dropped by default, as it holds no user data. Pass -p track_number=merge to prepend it to the .bin instead, which the CUE sheet will reflect. The pregap handling section covers the rest.

Pass -X to skip data tracks entirely. The CUE sheet will still describe them, so it will reference a .bin that was never written.

Cover art embedding

cyanrip supports embedding album and track cover art.

To embed cover art for the whole album, specify it with the -C path or -C destination=path parameter. path can be a URL, in which case it will be automatically downloaded.

If destination is a number, the cover art will be embedded only for the track with that number. Otherwise, destination should be a descriptor like Front or Back or Disc. If destination is omitted, Front, then Back will be used.

Cover arts which are not attached to a track will be copied to each output directory as destination with an autodetected extension.

If multiple cover arts are present and no track cover art is specified, only the cover art with Front destination will be embedded, or the first cover art specified if no Front exists. Otherwise, only the specified track cover art will be embedded.

Cover art downloading

If a release ID is specified or detected, and no Front or Back cover arts were specified, a query will be made to the Cover Art Archive and if found, the archive cover art will be downloaded and used.

Multi-disc albums

cyanrip supports ripping multi-disc albums in the same output folder. To enable this manually, specify the -c argument followed by disc/totaldiscs (/totaldiscs is optional), otherwise it'll be done automatically if the MusicBrainz tags indicate so.

The track filenames will be disc.track - title.ext. The logfile will be Album name CD<disc>.log.

As well as using the -c argument, you can also specify the disc=number:totaldiscs=number in the album/track metadata.

If each disc has a title, you should use the discname tag if you're manually setting tags, which is what MusicBrainz will set if available.

HDCD decoding

cyanrip can decode and detect HDCD encoded discs. To check if a suspected disc contains HDCD audio, rip a single track using the -l 1 argument and look at the log. A non-HDCD encoded disc will have:

HDCD detected: no

If the CD does contain HDCD audio something similar to the following will be printed:

HDCD detected: yes, peak_extend: never enabled, max_gain_adj: 0.0 dB, transient_filter: not detected, detectable errors: 0

Should a track be detected as HDCD, it would be safe to proceed decoding all of the disc. The resulting encoded files will have a bit depth of at least 24 bits.

Deemphasis

Old (and not so old) CDs may require deeemphasis. cyanrip is able to detect such discs (using both the TOC and track subcode) and will apply a correction filter automatically. To check whether the CD contains emphasised audio, you can simply run cyanrip -I and read the printout.

Preemphasis:      <status> <action>

for each track.

status can be either none detected or present (TOC) or present (subcode).

Action may be either (deemphasis applied), which applies a deemphasis filter to the audio (default), (deemphasis forced) which does the same, even if no preemphasis is signalled (can be activated via the -E flag, or blank, which deactivates automatic deemphasis, preserving audio data as-is (activated via the -W flag).

The -E flag can be useful for some CDs, which may have been mastered with preemphasis, but don't actually signal it via the track substream properties.

An incomplete list of releases mastered with preemphasis can be found at this wiki page.

ReplayGain

cyanrip will automatically compute ReplayGain tags and add them to all files while ripping. Note, that this requires to hold all compressed audio data for the entire CD in RAM while ripping, which may be from 300 to 600 megabytes, depending on the output used. Low-power and low-RAM devices can turn this off via the -K switch, along with AcoustID fingerprinting via -B, which needs the same.

The tags generated are ReplayGain 2.0 compliant, which is backwards-compatible with ReplayGain 1.0. The true peak value is calculated and used.

AcoustID

When built with libchromaprint, cyanrip computes an AcoustID fingerprint of every audio track while ripping. Like fpcalc and MusicBrainz Picard, it fingerprints the first 2 minutes of each track.

If the whole disc checks out, the fingerprints are submitted to AcoustID, each linked to its MusicBrainz recording. Every audio track must be accurately ripped according to AccurateRip, and must have a MusicBrainz recording within 30 seconds of the track's length. Submitting needs your own user API key, found on your AcoustID account page and given via -k. Nothing is submitted without it.

Otherwise, the fingerprints are saved in the files' tags instead, in the same tag Picard uses: ACOUSTID_FINGERPRINT, or TXXX:Acoustid Fingerprint for MP3. Picard submits a fingerprint it finds there, rather than computing it again. MP4 based outputs don't get the tag, as FFmpeg can't write freeform iTunes tags.

Whether to submit or tag is only known once the whole disc is ripped, so like ReplayGain, this holds the compressed audio in RAM until the end. -B disables fingerprinting.

Paranoia level

cyanrip can apply four levels of cdparanoia error detection and correction:

ArgumentDescriptionPurposecdparanoia CLI equivalent
-P 0 or noneDisabledFastest ripping with no error correction-Z
-P 1Overlapped readsCorrect errors when optical drives skip sectors while reading audio discs-Y
-P 2Overlapped and verified readsRe-read sectors to correct for optical drives that supply inconsistent audio datan/a
-P 3 or maxAll paranoia featuresAt present, same as -P 2, but includes future cdparanoia improvementsdefault

Paranoia status count

At the end of the ripping process, cyanrip will print and log a summary of cdparanoia's status during ripping. This can be used to estimate the disc/drive's health.

An idealized disc and drive will only log READ: $number$ and nothing else. This happens while ripping from a file. In general READ/VERIFY/OVERLAP are normal and will happen when ripping a brand new CD with a new drive. FIXUP_EDGE/FIXUP_ATOM usually happen if cdparanoia is somewhat struggling, but both are recoverable and lossless. FIXUP_DROPPED/FIXUP_DUPED indicate more severe errors, but are still recoverable and lossless, though a hard read error will often follow. READERR indicates that cdparanoia gave up after all retries and outputted zeroes for all samples it couldn't recover.

Naming scheme

cyanrip supports highly flexible naming schemes via a custom syntax. You can extensively customize how all files and directories are named.

The default naming scheme for albums is Album name [Format] if the releasecomment tag is empty or Album name (Release comment) [Format] if it isn't. For tracks, its Track number - Track title.Extension if there's a single disc in the album or Disc Number.Track number - Track title.Extension if there are multiple. The log file will be named Album name.log in each of the output folders unless there are multiple CDs in the album, in which case it'll be Album name CD1.log for the first CD and so on.

If you would like something different, read on. If for a one-off you'd like to specify a different directory name, you can just use -D Directory and not read further.

The syntax is as follows: everything not inside { or } tags gets copied as-is unconditionally. Everything inside { or } tags is interpreted: if what's inside the tags matches a metadata key, the tag along with its outer brackets is replaced as-is. Otherwise only the tag brackets are removed and what's inside is copied literally.

Conditions are possible and must follow this syntax: {if #token1# != #token2#album name is |album|}. Condition tokens must be wrapped in # tags, and both must exist. In between the 2 tokens must be either > or < or == or !=. If any of the tokens inside the # tags matches a metadata key, it is replaced with a value, otherwise its taken literally (so if the album tag exists, #album# resolves to the album name, otherwise to just album).

If the condition is a direct comparison (== or !=), then the 2 tokens are compared as strings. If arithmetic comparison is used and the 2 tokens are integers, they're compared arithmetically.

If an arithmetic comparison is used when both tokens are strings, the result of strcmp is used. If only one is a string, its pointer (always above 0, unless the token did not match a metadata key, in which case 0) is used.

If the condition is true, everything after the last token's # is copied, with any metadata tags there wrapped with |. Otherwise, nothing is copied. Braces don't nest: inside a condition, a tag is written as |year|, never as {year}, and cyanrip refuses schemes which try.

Examples are easier to understand, by default the folder value of {album}{if #releasecomment# > #0# (|releasecomment|)} [{format}] is used. This resolves to Album [FLAC] if there's nothing in the releasecomment key, or Album (Release comment) [FLAC] if there is.

The default track file name syntax is: {if #totaldiscs# > #1#|disc|.}{track} - {title}. So this resolves to 1 - Title.flac if there's a single CD, or 1.1 - Title.flac if there are more than 1 CDs and you're ripping the first one.

The track number is only zero-padded to the number of digits the disc's track count needs: 1 on a disc of 9 tracks, but 01 on one of 12. For two digits regardless, use {if #tracktotal# < #10#0}{track}.

A useful example is to have separate directories for each disc: -D "{album}{if #totaldiscs# > #1# CD|disc|} [{format}]" -F "{track} - {title}".

Characters a file name can't hold are replaced in the literal text of a scheme too, except for the drive letter of an absolute Windows path, as in -D "D:/Music/{album}". Use / to separate directories.

Whitespace at the edges of every path component, and between the file name and its extension, is trimmed. Conditional bodies containing spaces (like the example above, when used as its own subdirectory) would otherwise leave dangling spaces on one of their branches.

Besides any tags given via -a and -t, these metadata keys are available:

KeyValue
album, album_artist, date, releasecommentThe release's, from MusicBrainz
yearThe year part of date
label, catalognumber, barcode, country, packaging, releasestatusThe release's, from MusicBrainz
disc, totaldiscs, discnameThe disc's position in the release, and its title if it has one
track, tracktotalThe track's number (padded as described above), and the disc's track count
title, artist, isrcThe track's
mbid, musicbrainz_trackidThe track's MusicBrainz recording ID, the latter being the tag taggers and players read it from
musicbrainz_albumid, musicbrainz_discid, cddb, disc_mcnThe release and disc IDs, and the barcode the disc itself carries
formatThe output format, e.g. FLAC

The ripping log name and location can be modified via the -L argument. By default its set to {album}{if #totaldiscs# > #1# CD|disc|}, which resolves to Album name.log for 1 CD and Album name CD1.log if there are multiple CDs and you're ripping the first.

Filename sanitation

If invalid symbols are found in a file or a folder, such as : or /, the symbol is by default substituted with a unicode lookalike, such as ∶ or ∕ respectively. If this is undesirable, this can be overridden via the -T simple argument. This will replace all invalid symbols with _. In case you're on an operating system with more liberal allowance on filenames, you can use the -T os_unicode option to allow symbols like : not supported on Windows to be passed through. Note that this will make files like these not accessible on Windows, unless renamed, so use this only if you're sure.

CUE sheet

cyanrip will generate a CUE sheet from which a byte-exact duplicate of the disc can be made. By default, pregaps are kept in the CUE sheet as being appended to the previous track (except for the first track, where the pregap is dropped and signalled as silence). This is reffered to as "noncompliant" by hydrogenaudio.

Data tracks are referenced as BINARY files holding MODE1/2352 or MODE2/2352 sectors, unless skipped with -X, in which case the CUE sheet still names a file that isn't there.

Custom changes in the way pregaps are handled will be reflected in the CUE file. For example, dropping a pregap will signal silence in the CUE sheet. Appending a pregap to the track will accordingly mark the track as having two audio indices.

Links

You can talk about the project and get in touch with developers on:

cd
cdparanoia
ffmpeg
flac
musicbrainz

Significant stargazers

Simon Ser

2,179 followers · starred Oct 2018

Matthaiks

29 followers · starred Sep 2023

Daniel Bast

155 followers · starred Sep 2026

Andrei Kvapil

648 followers · starred Dec 2024