Skip to content

jeeftor/audiobook-organizer

Repository files navigation

Audiobook Organizer

codecov Coverage Status

docs/logo.png

CLI tool to organize audiobooks based on EITHER metadata.json files OR embedded metadata in .epub, .mp3, and .m4b files.

Features

  • Organizes audiobooks by author/series/title structure
  • Handles multiple authors
  • Preserves spaces by default
  • Optional space replacement with custom character
  • Dry-run mode to preview changes
  • Interactive prompt mode for reviewing moves
  • Undo functionality
  • Colored output
  • Operation logs for recovery
  • Separate input/output directory support
  • NEW: Extract metadata directly from EPUB, MP3, and M4B files
  • NEW: Process files in a flat directory structure
  • NEW: Flexible directory layout options (author/series/title, author/title, author-only)
  • NEW: Special handling for MP3 files with non-standard metadata structure

Pre-requirements

In order for this tool to operate you need to configure audiobookshelf to store metadata.json files in the same directories as your books. When this setting is toggled whenver metadata is generated a copy will be stored inside the directory - this is what will be used to rename the books.

Settings - metadata.json

Post-requirements

Because this software is not modifying the internal databse (due to time constraints) upon running the software you may end up with a good nubmer of Missing books as audiobookshelf. I believe the setting Enable folder watcher for library in your library config may inhibit this from happening - but - if it does occur you will see an error like this:

issue

To resolve these issues simply click on the Issues button

remove button

next use the Remove All x Books button to clean up the errors.

Installation

There are various ways to install this - I actually haven't tested the Docker install - but it should work :)

Ubuntu/Debian

# Install required dependencies
sudo apt-get install -y jq curl wget

# Download and install the latest release
LATEST_RELEASE=$(curl -s https://api.github.com/repos/jeeftor/audiobook-organizer/releases/latest | jq -r '(.assets[].browser_download_url | select(. | contains("_amd64.deb")))')
wget "$LATEST_RELEASE" -O audiobook-organizer.deb
sudo dpkg -i audiobook-organizer.deb

# Install any missing dependencies
sudo apt-get install -f -y

# Clean up
rm audiobook-organizer.deb

Redhat

curl -s https://api.github.com/repos/jeeftor/audiobook-organizer/releases/latest | \
grep "browser_download_url.*rpm" | \
cut -d : -f 2,3 | \
tr -d \" | \
wget -qi -

Alpine

# Download the latest .apk package
curl -s https://api.github.com/repos/jeeftor/audiobook-organizer/releases/latest | \
  grep "browser_download_url.*apk" | \
  cut -d : -f 2,3 | \
  tr -d \" | \
  wget -qi -

# Install the package
sudo apk add --allow-untrusted ./audiobook-organizer_*.apk

# Clean up
rm audiobook-organizer_*.apk

Install the package

sudo rpm -i audiobook-organizer_*.rpm

Clean up

rm audiobook-organizer_*.rpm

Homebrew (macOS/Linux)

# Add the tap repository
brew tap jeeftor/tap

# Install the application
brew install audiobook-organizer

Go Install

go install github.com/jeeftor/audiobook-organizer@latest

Docker

docker pull jeffsui/audiobook-organizer:latest

Usage

Basic organization:

# Organize in place
audiobook-organizer --dir=/path/to/audiobooks

# Organize to separate output directory
audiobook-organizer --dir=/path/to/source/audiobooks --out=/path/to/organized/audiobooks

Options:

  • --dir: Base directory to scan (required)
  • --input: same as --dir
  • --out: Output directory for organized files (optional, defaults to --dir if not specified)
  • --output: same as --out
  • --replace_space: Character to replace spaces (optional)
  • --dry-run: Preview changes without moving files
  • --verbose: Show detailed progress
  • --undo: Restore files to original locations
  • --prompt: Review and confirm each book move interactively
  • --remove-empty: Remove empty directories after moving files and during initial scan
  • --use-embedded-metadata: Use metadata embedded in EPUB, MP3, and M4B files if metadata.json is not found
  • --flat: Process files in a flat directory structure (automatically enables --use-embedded-metadata)
  • --layout: Directory structure layout (options: author-series-title, author-title, author-only)
  • --use-series-as-title: Use Series field as the main title directory (useful for MP3 files where Series contains the book title)

Docker Usage Examples

Basic usage with single directory:

# Process current directory
docker run -v $(pwd):/books \
  jeffsui/audiobook-organizer --dir=/books

# Process specific directory
docker run -v /path/to/audiobooks:/books \
  jeffsui/audiobook-organizer --dir=/books

Separate input and output directories:

# Mount source and destination directories
docker run \
  -v /path/to/source:/input:ro \
  -v /path/to/destination:/output \
  jeffsui/audiobook-organizer --dir=/input --out=/output

# Use current directory as source, output to specific directory
docker run \
  -v $(pwd):/input:ro \
  -v /path/to/organized:/output \
  jeffsui/audiobook-organizer --dir=/input --out=/output

Interactive mode with input/output:

# Interactive prompt mode with separate directories
docker run -it \
  -v /path/to/source:/input:ro \
  -v /path/to/destination:/output \
  jeffsui/audiobook-organizer --dir=/input --out=/output --prompt

Dry run with verbose output:

# Preview changes without moving files
docker run \
  -v /path/to/source:/input:ro \
  -v /path/to/destination:/output \
  jeffsui/audiobook-organizer --dir=/input --out=/output --dry-run --verbose

Docker Volume Mounting Notes

  • Use :ro for read-only access to source directories
  • The container paths must match the --dir and --out parameters
  • Use -it flag when running with --prompt for interactive mode
  • Multiple directories can be mounted for source/destination separation
  • Source and destination can be the same directory if desired
  • Log files will be written to the output directory

Interactive Mode

Using the --prompt flag will show each book's details and proposed move location:

Book found:
  Title: The Book Title
  Authors: Author One, Author Two
  Series: Amazing Series #1

Proposed move:
  From: /input/original/path/book
  To: /output/Author One,Author Two/Amazing Series #1/The Book Title

Proceed with move? [y/N]

Metadata Sources

The tool can obtain metadata from two sources:

1. metadata.json Files

The tool primarily looks for metadata.json files in the same directory as your audiobook files. These files should have the following structure:

{
  "authors": ["Author Name"],
  "title": "Book Title",
  "series": ["Series Name #1"]
}

2. Embedded EPUB, MP3, and M4B Metadata

When using the --use-embedded-metadata flag (which is automatically enabled with --flat), the tool can extract metadata directly from EPUB, MP3, and M4B files. This is useful when:

  • No metadata.json file exists
  • Processing a flat directory of EPUB, MP3, or M4B files
  • Working with EPUBs, MP3s, or M4Bs that contain their own metadata

The tool will extract author, title, and series information from the EPUB's, MP3's, or M4B's internal metadata structure.

Directory Structure

Standard Layout (--layout=author-series-title)

Without series:

/output/Author Name/Book Title/

With series:

/output/Author Name/Series Name #1/Book Title/

Author-Title Layout (--layout=author-title)

/output/Author Name/Book Title/

Author-Only Layout (--layout=author-only)

/output/Author Name/

Using Series as Title (--use-series-as-title)

For MP3 files where the Series field contains the actual book title and Title contains chapter info:

/output/Author Name/Series Name/

Multiple Authors

/output/Author One,Author Two/Book Title/

Space Replacement (--replace_space=".")

/output/Author.Name/Series.Name.#1/Book.Title/

Recovery

Operations are logged to .abook-org.log in the output directory. Use --undo to restore files to their original locations:

# Undo with same input/output configuration
docker run \
  -v /path/to/source:/input \
  -v /path/to/destination:/output \
  jeffsui/audiobook-organizer --dir=/input --out=/output --undo

Configuration

The audiobook organizer supports multiple ways to configure its behavior:

Configuration File

You can create a YAML configuration file in either:

  • Your home directory: ~/.audiobook-organizer.yaml
  • The current directory: .audiobook-organizer.yaml
  • Or specify a custom location: --config /path/to/config.yaml

Example configuration file:

# Input directory (use either dir/input)
dir: "/path/to/audiobooks"
# or
input: "/path/to/audiobooks"

# Output directory (use either out/output)
out: "/path/to/organized/audiobooks"
# or
output: "/path/to/organized/audiobooks"

replace_space: "_"
verbose: true
dry-run: false
prompt: true
remove-empty: true  # Remove empty directories
use-embedded-metadata: true # Use metadata embedded in EPUB, MP3, and M4B files
flat: false  # Process files in a flat directory structure
layout: "author-series-title"  # Directory structure layout options: author-series-title, author-title, author-only
use-series-as-title: false  # Use Series field as the main title directory for MP3 files

Environment Variables

All options can be set using environment variables with either the prefix AO_ or AUDIOBOOK_ORGANIZER_:

# Input directory (use any)
export AO_DIR="/path/to/audiobooks"
export AO_INPUT="/path/to/audiobooks"
export AUDIOBOOK_ORGANIZER_DIR="/path/to/audiobooks"
export AUDIOBOOK_ORGANIZER_INPUT="/path/to/audiobooks"


# Output directory (use any)
export AO_OUT="/path/to/output"
export AO_OUTPUT="/path/to/output"
export AUDIOBOOK_ORGANIZER_OUT="/path/to/output"
export AUDIOBOOK_ORGANIZER_OUTPUT="/path/to/output"

# Other settings (use either prefix)
export AO_REPLACE_SPACE="_"
export AO_VERBOSE=true
export AO_REMOVE_EMPTY=true
export AO_USE_EMBEDDED_METADATA=true
export AO_LAYOUT="author-series-title"  # Options: author-series-title, author-title, author-only
export AO_USE_SERIES_AS_TITLE=false

# or
export AUDIOBOOK_ORGANIZER_REPLACE_SPACE="_"
export AUDIOBOOK_ORGANIZER_VERBOSE=true
export AUDIOBOOK_ORGANIZER_REMOVE_EMPTY=true
export AUDIOBOOK_ORGANIZER_USE_EMBEDDED_METADATA=true
export AUDIOBOOK_ORGANIZER_LAYOUT="author-series-title"
export AUDIOBOOK_ORGANIZER_USE_SERIES_AS_TITLE=false

Command Line Flags

Command line flags take precedence over configuration files and environment variables. The input and output directories can be specified using either of their respective aliases:

# Using --dir and --out
audiobook-organizer \
  --dir=/path/to/audiobooks \
  --out=/path/to/output \
  --replace_space=_ \
  --verbose \
  --use-embedded-metadata

# Or using --input and --output
audiobook-organizer \
  --input=/path/to/audiobooks \
  --output=/path/to/output \
  --replace_space=_ \
  --verbose \
  --use-embedded-metadata

Configuration Precedence

The configuration values are loaded in the following order (later sources override earlier ones):

  1. Default values
  2. Configuration file (~/.audiobook-organizer.yaml or specified with --config)
  3. Environment variables
  4. Command line flags

For the input and output directories, both aliases (--dir/--input and --out/--output) are treated equally, with the last specified value taking precedence.

About

Audiobookshelf Organizer

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages