Bule-ish CD ripper

Overview

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

Archlinux

pacaur -S cyanrip

Or use your favorite AUR installation method.

FreeBSD

pkg install cyanrip

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

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

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

CLI

Arguments are optional. By default cyanrip will rip all tracks from the default CD drive, output to flac only, enables all cd-paranoia error checking and performs a MusicBrainz lookup.

Argument Description
Ripping options
-d string The path or name for a specific device, otherwise uses the default device
-s int Specifies the CD drive offset in samples (same as EAC, default is 0)
-r int Specifies how many times to retry reading a frame if it fails, (default is 25)
-S int Sets the drive speed if possible (default is unset, usually maximum)
-p number=string Specifies what to do with the pregap, syntax is described below
-P int Sets the paranoia level to use, by default its max, 0 disables all checking completely
-O Overread into lead-in/lead-out areas, if unsupported by drive may freeze ripping
-H Enable HDCD decoding, read below for details
Metadata options
-I Only print CD metadata and information, will not rip or eject the CD
-a string Album metadata, syntax is described below
-t number=string Track metadata, syntax is described below
-R int or string Sets the MusicBrainz release to use, either as an index starting from 1 or an ID string
-c int/int Tag multi-disc albums as such, syntax is disc/totaldiscs, read below
-C path or url Sets cover image to embed into each track, syntax is described below
-N Disables MusicBrainz lookup and ignores lack of manual metadata to continue
-A Disables AccurateRip database query and comparison
-U Disables Cover art DB database query and retrieval
Output options
-l list Comma separated list of track numbers to rip, (default is it rips all)
-D string Directory naming scheme, see below
-F string File naming scheme, see below
-L string Log naming scheme, see below
-T string Filename sanitation, default is unicode, see below
-o list Comma separated list of output formats, "help" to list all, default is flac
-b int Bitrate in kbps for lossy formats
Misc. options
-E Eject CD tray if ripping has been successfully completed
-V Print version
-h Print usage (this)
-f Find drive offset (requires a disc with an AccuRip DB entry)

Metadata

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.

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.

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.

action Description
default Merge into previous track, drop on track 1
drop Drop the pregap entirely
merge Merge into current track
track Split into a new track before the current

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

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

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 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.

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.

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 01 - Title.flac if there's a single CD, or 1.01 - Title.flac if there are more than 1 CDs and you're ripping the first one.

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

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.

Issues
  • Metadata query generates a lot of noise

    Metadata query generates a lot of noise

    cyanrip -d /dev/cd0 -s 618 -I

    Checking /dev/cd0 for cdrom...
                    CDROM sensed: BENQ     DVD DD DW1650    BCIC
    
    
    Opening drive...
    Unrecognised disc element: 'offset-list'
    Unrecognised artist attribute: 'type-id'
    Unrecognised release element: 'release-event-list'
    Unrecognised release element: 'cover-art-archive'
    Unrecognised disc element: 'offset-list'
    Unrecognised disc element: 'offset-list'
    Unrecognised disc element: 'offset-list'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised release element: 'release-event-list'
    Unrecognised release element: 'cover-art-archive'
    Unrecognised disc element: 'offset-list'
    Unrecognised disc element: 'offset-list'
    Unrecognised disc element: 'offset-list'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Unrecognised track attribute: 'id'
    Unrecognised artist attribute: 'type-id'
    Multiple releases found in database for DiscID wTkS6G6kcY9_cjK10YVBYSVuzD4-:
        1 (ID: 08dade63-5fa5-4860-9c60-43b445862ccd): Head Over Heels (1995)
        2 (ID: 5a52c85d-2dcc-33cd-83cf-04fa0487177c): Head Over Heels (1995-06-16)
    
    Please specify which release to use by adding the -R argument with an index or ID.
    

    OS: FreeBSD 12.1-RELEASE-p9 Cyanrip master branch, commit fe03e2e libmusicbrainz 5.1.0 (lib)curl 7.72.0 libcdio-paranoia 10.2+2.0.1

    Great software! Keep up the good work!

    opened by diizzyy 5
  • README nitpicks

    README nitpicks

    Hello and first of all, thanks for your project replacing the quite bloated whipper for me.

    I've had some problems while reading the manual tagging section of the README:

    1. The double quotes in the -a or -t examples are actually included in the tag values, which makes the examples pretty misleading, as I'm sure most people don't want that.
    2. In the same examples, tag keys don't follow the Xiph Vorbis comments spec (https://xiph.org/vorbis/doc/v-comment.html) where everything in it is all caps. I now wonder if the automatic tagging uses the right keys (only used one CD that wasn't in the database, sadly).

    Otherwise, no problem to report.

    opened by q3cpma 4
  • [Feature Request] Utilize the Disambiguation information from MusicBrainz.

    [Feature Request] Utilize the Disambiguation information from MusicBrainz.

    Some releases on MusicBrainz include information in a Disambiguation field to denote things like special editions or anniversary re-releases. It appears some rippers just include this information on the end of the album title. Here are examples of some such releases:

    Weezer have released six self-titled albums to date. To differentiate, the traditional addition to the album title has related to the album cover's color. So we have "Weezer (Blue Album)", "Weezer (Green Album)", etc. MusicBrainz stores those extra titles in the albums' respective Disambiguation fields and displays it on the release page in parentheses after the main title. Another extended example of this within Weezer's catalog is something like this, which is the "Deluxe Edition" of the "Blue Album".

    Another example would be the 25th anniversary releases of Paul Simon's Graceland, like this.

    I'm not sure of the best way to handle this information. I personally don't mind including it in the album title, but that is perhaps less "correct". The issue with not including it in the title is that you might have all of the albums titled "Weezer" listed under the same album in a music player. Otherwise, perhaps just pulling in this information and including it in the metadata so it's there would be nice.

    In the meantime, a user can simply override the album title and include this information however they see fit. I just wanted to document this case.

    opened by gnafuthegreat 4
  • aac gets encoded with 96000hz sampling rate

    aac gets encoded with 96000hz sampling rate

    was wondering if this is the intended behaviour. I saw in the code, that you are looking what the specific codec can do and if its above 44.1 you use that maximum, otherwise fall back to 44.1. Now for an audio cd this seems like overkill. I know that for opus encodes everyone tells you to not mess with the 48, but with aac it seems that using 44.1 like you do with flac wouldnt hurt either. Just a suggestion.

    opened by Tupsi 3
  • [Feature Suggestion] Display disc ID when a rip

    [Feature Suggestion] Display disc ID when a rip "fails" due to multiple release IDs.

    When ripping a disc with multiple MusicBrainz release IDs and no release specified, the rip stops and cyanrip helpfully displays the available release IDs. It would be nice if the disc ID was shown as well in the event a user feels none of the current releases match their disc and they want to add it to another release in MusicBrainz.

    Currently, you'd need to specify one of the available release IDs to start a rip long enough to see the discid listed in the opening output.

    opened by gnafuthegreat 3
  • Add MinGW workflow action

    Add MinGW workflow action

    Not sure if uploading the artifact is enough, or if you also want this to create+upload to a release.

    opened by wiiaboo 2
  • Malformed disc ID and submission URL for PlayStation disc with audio tracks.

    Malformed disc ID and submission URL for PlayStation disc with audio tracks.

    I seem to get an invalid disc ID when I try to rip a PlayStation disc with audio tracks at the end. For example, disc one of Lunar gives me this:

    https://musicbrainz.org/cdtoc/attach?toc=1+3+261488+246922+258219&tracks=3&id=.A8KH4tSiiHfbJzXPyWJghuCyOY-

    I also tried running cyanrip on a cdrdao rip of the same disc, and I got a different TOC and disc ID:

    https://musicbrainz.org/cdtoc/attach?toc=1+3+261338+246772+258069&tracks=3&id=buK8JSCWgFudBEX4H6Ye4KxLQ3E-

    Passing -n to get a quick rip going did rip and encode the audio tracks, and I'm attaching the log from that.

    I would consider this very low priority--I'm certainly not planning on ripping the audio tracks from my PlayStation games anytime soon--but I thought it could potentially point to a more serious issue, so I wanted to log it. Here are some pages with release information for this game:

    https://musicbrainz.org/release/a1f8bb08-ec5c-4ae5-af4d-7576b8c4af90

    http://redump.org/disc/2676/

    lunar-d1.log

    opened by gnafuthegreat 2
  • Some discs have more than one

    Some discs have more than one "good" result in AccurateRip database.

    It appears that some discs have more than one "good" result in the AccurateRip database. These seem to be given a confidence rating based on how many people have submitted that particular set of checksums for that particular disc. cyanrip appears to only compare against the result with the highest confidence, where whipper appears to be able to compare against lower confidence results when the highest confidence result doesn't match. That may also be entirely the wrong way to describe what's going on, but it's how I've come to understand it.

    Attached are a couple examples of logs from both cyanrip and whipper to show how they report a different confidence rating and how cyanrip reports "inaccurate" where whipper reports "accurate". You can see the checksums match between the two programs, so they're definitely getting the same results from the disc.

    I'm sure AccurateRip's database isn't the most accessible, so I don't know how complex a "fix" for this would be. I just wanted to log it in the hope that the AccurateRip lookup can be improved in the future. Please let me know if I can provide additional information about specific discs that present this behavior.

    gordon-cyanrip.log gordon-whipper.log

    opened by gnafuthegreat 2
  • Windows version outputs to wrong folder

    Windows version outputs to wrong folder

    Hello. I wonder if there is a problem with my command. This is what I used:

    cyanrip.exe -d D: -D "C:\Users\sduell\Desktop\Converted CD" -t 01 -o mp3 -b 256 -f -n

    When the conversion is complete, I find "C:\Users\sduell\Desktop\Converted CD" is empty, but there is a new folder created called 'Converted CD [MP3]' instead, and the converted file is in there. How can I make cyanrip output only into the folder I specify in the command, rather than into a newly generated one?

    I'm using cyanrip version 0.1-rc2 on a Windows 10 box.

    Thanks for your time.

    opened by steveduell 2
  • Update README.md

    Update README.md

    Minor capitalization and typo fixes.

    opened by gnafuthegreat 1
Releases(v0.7.0)
  • v0.7.0(Nov 1, 2020)

    This project is now feature complete. It does everything I'd like for it to do in order to rip my entire CD collection. There's still some polishing work to optionally do, like read the JSON directly from MBDB and CADB, as it carries more data like release events, and the cover art DB does contain some more images that we don't fetch yet. And no doubt there are a few bugs left to fix, like making PSX game CDs more accurately read.

    This project was originally meant to be also usable as a library for embedding, so maybe if there's some interest to do this work it wouldn't take long to do; the project doesn't have too much bad code and hacks, and the main header isn't as messy as it could have otherwise been.

    Thanks to all contributors and testers.

    Small changelog:

    • Automated CD drive offset finding
    • Verification of partially damaged tracks
    • Tagging usability improvements
    • Even faster ripping
    • Arbitrary directory/file structure
    • Automatic cover art image downloading
    • ...and more
    Source code(tar.gz)
    Source code(zip)
    cyanrip-win64.exe(7.50 MB)
Owner
Lynne
Lynne
The fre:ac audio converter project

fre:ac - free audio converter fre:ac is a free and open source audio converter. It supports audio CD ripping and tag editing and converts between vari

Robert Kausch 619 Sep 24, 2021
Fork of the original rubyripper from code.google.com/p/rubyripper + some bugs fixes

Historical note Introduction Secure rip method How to install MacOS Support FAQ Running all tests Historical note This is an unofficial fork of the or

null 91 Aug 11, 2021