chape

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2025 License: MIT Imports: 24 Imported by: 0

README

Chape

Test Status Coverage Status MIT License PkgGoDev

Chape is a powerful command-line tool for editing MP3 metadata using YAML format. It provides an intuitive way to manage ID3v2 tags, chapters, and artwork in MP3 files.

asciicast

Features

  • YAML-based metadata editing: Edit MP3 metadata using familiar YAML syntax
  • Chapter support: Manage chapter markers for audiobooks and podcasts
  • Artwork management: Handle embedded artwork with support for local files, URLs, and data URIs
  • Interactive editing: Built-in editor support for seamless workflow

Usage

Basic Commands

Interactive editing with your EDITOR:

chape audio.mp3

Dump metadata to YAML:

chape dump audio.mp3 > metadata.yaml

Apply YAML metadata to MP3:

chape apply audio.mp3 < metadata.yaml
Options
  • -y: Skip confirmation prompts (useful for automation)
  • --artwork <path>: Override artwork with local file path or HTTP/HTTPS URL
Examples

Edit metadata interactively:

chape my-audiobook.mp3

Edit metadata with custom artwork:

chape --artwork cover.jpg my-audiobook.mp3

Batch processing with automation:

chape apply -y audio.mp3 < batch-metadata.yaml

YAML Format

Chape uses a structured YAML format for metadata:

title: "My Audiobook"
subtitle: "Unabridged Edition"
artist: "Author Name"
album: "Book Series"
albumArtist: "Publisher"
grouping: "Volume 1: The Beginning"
date: "2024"
track: "1/12"
disc: "1/2"
genre: "Audiobook"
comment: "A great book"
composer: "Author Name"
publisher: "Publisher Name"
copyright: "© 2024 Publisher Name"
language: "eng"
bpm: 120
artwork: "cover.jpg"
lyrics: |
  Chapter content here...
chapters:
- 0:00 Introduction
- 5:30 Chapter 1: Getting Started
- 15:45 Chapter 2: Advanced Topics
- 28:20 Chapter 3: Conclusion
Metadata Fields
Field Description ID3v2 Tag
title Song/track title (podcast: episode title) TIT2
subtitle Subtitle/description refinement TIT3
artist Primary artist (podcast: host name) TPE1
album Album title (podcast: show name) TALB
albumArtist Album artist (podcast: network/publisher) TPE2
grouping Content group (e.g., work/movement, season) TIT1
date Recording date TDRC
track Track number (podcast: episode number) TRCK
disc Disc number (podcast: season number) TPOS
genre Music genre (podcast: "Podcast" or category) TCON
comment Comments (podcast: episode description) COMM
composer Composer (podcast: producer) TCOM
publisher Publisher (podcast: network/platform) TPUB
copyright Copyright message TCOP
language Language code (e.g., "eng", "jpn") TLAN
bpm Beats per minute TBPM
artwork Artwork (file path, URL, or data URI) APIC
lyrics Lyrics text (podcast: transcript) USLT
chapters Chapter markers with timestamps CHAP
Date Format

The date field supports ISO 8601 format with varying precision:

  • 2024 (year only)
  • 2024-03 (year-month)
  • 2024-03-15 (year-month-day)
  • 2024-03-15T14:30 (with time)
  • 2024-03-15T14:30:45 (with seconds)
Chapter Format

Chapters use WebVTT-style time format with titles:

chapters:
- 0:00 Introduction
- 1:05:30 Long chapter (over 1 hour)
- 1:23.500 Chapter with milliseconds
Artwork Sources

Chape supports multiple artwork sources:

  1. Local file paths: artwork: "cover.jpg"
  2. HTTP/HTTPS URLs: artwork: "https://example.com/cover.jpg"
  3. Data URIs: artwork: "data:image/jpeg;base64,/9j/4AAQ..."

When you specify an artwork path that doesn't exist, Chape will:

  1. Check if the MP3 has embedded artwork
  2. Automatically extract and save it to the specified path
  3. Update the metadata to reference the new file

Advanced Features

Interactive Editor Integration

Chape integrates with your preferred text editor for seamless metadata editing:

# Uses $EDITOR environment variable
export EDITOR=nano
chape audio.mp3
Automation and Scripting

Use the -y flag for non-interactive batch processing:

#!/bin/bash
for file in *.mp3; do
    echo "title: $(basename "$file" .mp3)" | chape apply -y "$file"
done
Artwork Management

Extract artwork from MP3 files:

# This will extract artwork to cover.jpg if it doesn't exist
echo 'artwork: cover.jpg' | chape apply audio.mp3

Override artwork source:

chape --artwork https://example.com/new-cover.jpg audio.mp3

Installation

% brew install Songmu/tap/chape

# Install the latest version. (Install it into ./bin/ by default).
% curl -sfL https://raw.githubusercontent.com/Songmu/chape/main/install.sh | sh -s

# Specify installation directory ($(go env GOPATH)/bin/) and version.
% curl -sfL https://raw.githubusercontent.com/Songmu/chape/main/install.sh | sh -s -- -b $(go env GOPATH)/bin [vX.Y.Z]

# In alpine linux (as it does not come with curl by default)
% wget -O - -q https://raw.githubusercontent.com/Songmu/chape/main/install.sh | sh -s [vX.Y.Z]

# go install
% go install github.com/Songmu/chape/cmd/chape@latest

Author

Songmu

Documentation

Index

Constants

View Source
const Version = "0.0.3"

Variables

View Source
var Revision = "HEAD"

Functions

This section is empty.

Types

type Chape

type Chape struct {
	// contains filtered or unexported fields
}

func New

func New(audio string, artwork ...string) *Chape

func (*Chape) Apply

func (c *Chape) Apply(input io.Reader, yes bool) error

func (*Chape) Dump

func (c *Chape) Dump(output io.Writer) error

func (*Chape) Edit

func (c *Chape) Edit(yes bool) error

type Chapter

type Chapter struct {
	Title string        `json:"title"`
	Start time.Duration `json:"start"`
}

Chapter represents a single chapter with start time and title

func (*Chapter) MarshalYAML

func (c *Chapter) MarshalYAML() ([]byte, error)

MarshalYAML marshals the chapter to YAML format

func (*Chapter) String

func (c *Chapter) String() string

String returns the chapter as a string in WebVTT format

func (*Chapter) UnmarshalYAML

func (c *Chapter) UnmarshalYAML(b []byte) error

UnmarshalYAML unmarshals the chapter from YAML format

type Metadata

type Metadata struct {
	Title       string       `yaml:"title"`                 // TIT2 tag (Title/songname/content description)
	Subtitle    string       `yaml:"subtitle,omitempty"`    // TIT3 tag (Subtitle/Description refinement)
	Artist      string       `yaml:"artist"`                // TPE1 tag (Lead performer(s)/Soloist(s))
	Album       string       `yaml:"album"`                 // TALB tag (Album/Movie/Show title)
	AlbumArtist string       `yaml:"albumArtist,omitempty"` // TPE2 tag (Band/orchestra/accompaniment)
	Grouping    string       `yaml:"grouping,omitempty"`    // TIT1 tag (Content group description)
	Date        *Timestamp   `yaml:"date,omitempty"`        // TDRC tag for ID3v2.4 (Recording time)
	Track       *NumberInSet `yaml:"track,omitempty"`       // TRCK tag (Track number/Position in set)
	Disc        *NumberInSet `yaml:"disc,omitempty"`        // TPOS tag (Part of a set)
	Genre       string       `yaml:"genre,omitempty"`       // TCON tag (Content type/Genre)
	Comment     string       `yaml:"comment,omitempty"`     // COMM tag (Comments)
	Composer    string       `yaml:"composer,omitempty"`    // TCOM tag (Composer)
	Publisher   string       `yaml:"publisher,omitempty"`   // TPUB tag (Publisher)
	Copyright   string       `yaml:"copyright,omitempty"`   // TCOP tag (Copyright message)
	Language    string       `yaml:"language,omitempty"`    // TLAN tag (Language(s))
	BPM         int          `yaml:"bpm,omitempty"`         // TBPM tag (BPM - Beats per minute)
	Chapters    []*Chapter   `yaml:"chapters,omitempty"`    // CHAP tag (Chapter frames)
	Artwork     string       `yaml:"artwork,omitempty"`     // APIC tag (Attached picture)
	Lyrics      string       `yaml:"lyrics,omitempty"`      // USLT tag (Unsynchronised lyric/text transcription)
}

Metadata represents the metadata of an MP3 file

type NumberInSet

type NumberInSet struct {
	Current int
	Total   int
}

NumberInSet represents a current/total number pair in ID3v2 format (e.g., "3/10", "1/2")

func (*NumberInSet) MarshalYAML

func (n *NumberInSet) MarshalYAML() ([]byte, error)

MarshalYAML marshals number in set to YAML format

func (*NumberInSet) String

func (n *NumberInSet) String() string

String returns number in set in ID3v2 format

func (*NumberInSet) UnmarshalYAML

func (n *NumberInSet) UnmarshalYAML(b []byte) error

UnmarshalYAML unmarshals number in set from YAML format

type Precision

type Precision int

Precision represents the precision level of the timestamp

const (
	PrecisionYear Precision = iota
	PrecisionMonth
	PrecisionDay
	PrecisionHour
	PrecisionMinute
	PrecisionSecond
)

type Timestamp

type Timestamp struct {
	time.Time
	Precision Precision
}

Timestamp wraps time.Time for ID3v2 timestamp format as defined in ID3v2.4.0-structure. The timestamp fields are based on a subset of ISO 8601 and can have varying levels of precision. All time stamps are UTC. Valid formats: yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm, yyyy-MM-ddTHH:mm:ss

func (*Timestamp) MarshalYAML

func (t *Timestamp) MarshalYAML() ([]byte, error)

MarshalYAML marshals timestamp to YAML format

func (*Timestamp) String

func (t *Timestamp) String() string

String returns timestamp in ID3v2 format

func (*Timestamp) UnmarshalYAML

func (t *Timestamp) UnmarshalYAML(b []byte) error

UnmarshalYAML unmarshals timestamp from YAML format

Directories

Path Synopsis
cmd
chape command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL