CopyOfA
CopyOfA is a preservation and forensic toolkit for music collectors. It acquires and maintains trustworthy evidence of recorded audio, then lets collectors analyze, compare, and share what that evidence reveals.
Status
The project is restarting from a clean slate. Its first release, v0.1.0, preserves a
selected file delivery as an Evidence Set and verifies it later. The second, v0.2.0,
describes the audio in a set: each track's format and properties, an Audio Digest for
lossless audio, and a few measurements. The third, v0.3.0, measures how two preserved
tracks relate, across formats and sample rates. The fourth, v0.4.0, shares a
comparison: a Report can leave out where the Evidence Sets are stored, view turns it
into a self-contained HTML page, and validate checks any Report against its
published JSON Schema. The roadmap in the Product Map lists what comes next.
The previous implementation, which archived optical discs bit-exactly with redumper, is
retired. Its last code change is commit 0d04a38 in the Git history. It does not define
the new architecture or release sequence.
Installation
CopyOfA runs on macOS and Linux with Python 3.11 or later. Install it from PyPI with uv:
uv tool install copyofa
Usage
Preserve files you already own, such as a download purchase, as a new Evidence Set:
copyofa import ~/Downloads/Album --to /Volumes/Archive/Album \
--note "Bandcamp purchase" --ref discogs=r123456
- Each source, a file or a directory, goes into the set under its base name.
--tonames a directory that must not exist yet; the set appears there only once every stored copy has been checked against its source.--exclude <pattern>leaves out files and directories by shell-style pattern; operating system metadata files such as.DS_Store, symbolic links, and empty directories are left out too. Every exclusion is recorded with its reason.--noteand--refrecord provenance exactly as given;--refrepeats.--jsonprints the result as JSON. Progress and errors go to stderr.
The command exits 0 when the set is accepted, 1 when the import is refused or fails, 2 for invalid arguments, and 130 when canceled with Ctrl-C. Evidence Set format describes the set and how to check it without CopyOfA.
Later, after moving the set or just to check it, verify it against its Integrity Baseline:
copyofa verify /Volumes/Archive/Album
copyofa verify /Volumes/Archive/Album --json > album-verification.json
Verify reads every preserved file and reports each one as matching, changed, missing,
unavailable, or not checked, and lists unexpected files under data/. Operating
system metadata files that Finder adds while browsing the set are ignored. It writes
nothing into the set. --json prints a verification Report, which
Verification Report format describes.
Verify exits 0 when everything is intact, 1 when it found anything else, 2 when the target is not an Evidence Set or the arguments are invalid, and 130 when canceled.
Describe the audio the set holds:
copyofa inspect /Volumes/Archive/Album
copyofa inspect /Volumes/Archive/Album --json > album-inspection.json
Inspect first checks each preserved file against the Integrity Baseline, then decodes
FLAC (8, 16 or 24 bits), integer PCM WAV and MP3, and reports each track's format,
sample rate, bit depth, channels and duration. Other files are reported as not
interpreted, with the reason. --json prints an inspection Report, which
Inspection Report format describes. For FLAC and WAV it gives an
Audio Digest, which recognizes the same audio after retagging or recompression and
can be reproduced with flac or ffmpeg. MP3 has none, because its decoded samples
depend on the decoder. The Report also gives each track's peak per channel and its
digital silence at each end, and for FLAC whether the audio matches the MD5 signature
its encoder stored.
Inspect exits 0 when every file was decoded or is not a supported format, 1 when a file could not be inspected or decoded or its audio differs from its FLAC MD5 signature, 2 when the target is not an Evidence Set or the arguments are invalid, and 130 when canceled. It writes nothing into the set.
Measure how two preserved tracks relate, such as a FLAC track and the MP3 of the same song from another release:
copyofa compare "/Volumes/Archive/With Teeth/data/04 The Hand That Feeds.flac" \
"/Volumes/Archive/Definitive NIN/data/18 The Hand That Feeds.mp3"
copyofa compare <track-a> <track-b> --json > comparison.json
copyofa compare <track-a> <track-b> --json --omit-locations > shareable.json
Each track is a file under the data/ directory of an Evidence Set. Compare checks
both against their Integrity Baselines and decodes them as inspect does. It then
resamples the one at the higher sample rate to the lower rate, aligns the tracks, and
reports the offset of track B from track A, their overlap, and how B relates to A:
correlation, gain and the residual level left after that gain. When both are
lossless and their Audio Digests are equal, it reports identical audio. It draws no
conclusion such as "same master". --json prints a comparison Report, which
Comparison Report format describes. To share a Report, add
--omit-locations: it leaves out where each Evidence Set is stored, which names your
disks and often your user account, and the Report says that it did.
Compare exits 0 when both tracks were measured, 1 when a track could not be inspected or decoded or is not a supported format, 2 when a track is not inside an Evidence Set or the arguments are invalid, and 130 when canceled. It writes nothing into either set.
Check that a Report, such as one you received, is well formed:
copyofa validate comparison.json
copyofa validate comparison.json --json > comparison-validation.json
Validate parses the file as strict JSON, then checks it against the JSON Schema
published for its Report kind and format version, and reports valid, invalid with
the location of each problem, or unsupported for a kind or version it does not know.
A valid Report is well formed, nothing more: validation does not establish that its
findings are true, who produced it, or anything about the audio. The schemas ship in
the package, so other software can check a Report without CopyOfA. --json prints a
validation result, which Validation result format describes.
Validate exits 0 when the Report is valid, 1 when it is invalid or unsupported or the file cannot be read, 2 when the arguments are invalid, and 130 when canceled. It writes nothing.
Read a comparison Report as a web page, without CopyOfA:
copyofa view comparison.json > comparison.html
View validates the file first, then prints one HTML page that shows every value of the Report with labels and units, each absent value with its reason, and each limitation. It gives the SHA-256 of the Report file it was generated from, so a recipient can check the page against the Report. The page runs no script and loads nothing, so it opens in any browser, offline. It draws no conclusion from the measurements. Comparison Report format describes it.
View exits 0 when it printed the page, 1 when the Report is invalid, unsupported, not a comparison Report, or cannot be read, 2 when the arguments are invalid, and 130 when canceled. It prints nothing on stdout otherwise, and writes no file.
Documents
- Manifesto: vision, target users, principles and non-goals.
- Product Map: capabilities, collector scenarios, core concepts, and the Now / Next / Later roadmap.
- Briefs: the scope and acceptance criteria of planned work.
- Decisions: architecture decision records.
- Formats: the files CopyOfA writes.
GitHub release milestones and their issues will hold the committed work.
Development
just setup # Install dependencies and git hooks
just qa # Run all checks
just test # Run the tests
CONTRIBUTING.md covers the development setup, pull requests and releases; AGENTS.md holds the commands and conventions for contributors and coding agents.
License
CopyOfA is licensed under the Apache License 2.0.
Metadata
Release files for copyofa 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| copyofa-0.4.0.tar.gz | 47.0 kB | With provenance | Details for copyofa-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| copyofa-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for copyofa-0.4.0-py3-none-any.whl |
Total release size: 99.2 kB
Release files / copyofa-0.4.0.tar.gz
| Download URL | copyofa-0.4.0.tar.gz |
|---|---|
| Size | 47.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70ae34917846f784de9424c9166e538d005e51b762fca21be4bba989955030d6
|
|
BLAKE2b-256 checksum How to use checksums |
45dafa5fe3667e31dd8181772a87fd2654e28bf358621da4f1fac327581cf9af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logRelease files / copyofa-0.4.0-py3-none-any.whl
| Download URL | copyofa-0.4.0-py3-none-any.whl |
|---|---|
| Size | 52.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
10631a22d709318212e7d0bd713078716385f198a476f1018a4730f8ae63061f
|
|
BLAKE2b-256 checksum How to use checksums |
ef6deef704922dabea5d956c66171875b517af1bb8978ee58b818c2e6e81931f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logSecurity for copyofa 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for copyofa-0.4.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.