-
Notifications
You must be signed in to change notification settings - Fork 4
Audiobookshelf Organizer
License
jeeftor/audiobook-organizer
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
CLI tool to organize audiobooks based on EITHER metadata.json files OR embedded metadata in .epub, .mp3, and .m4b files.
The audiobook organizer now includes a BETA interactive TUI mode! Launch it with:
audiobook-organizer guiFeatures:
- Interactive Directory Picker: Browse and select input/output directories with keyboard navigation
- Real-time Filtering: Type to filter directories as you browse
- Live Scan Preview: See discovered audiobooks before organizing
- Visual Settings Editor: Configure all options through an interactive interface
- Progress Tracking: Watch files being processed in real-time
The GUI mode is in active development. Feedback and bug reports are welcome!
- 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
The organizer supports two modes of operation, which affect how input files are processed:
- Use Case: When all your audiobook files are in a single directory, each potentially with different metadata.
- Behavior:
- Each file is processed independently based on its embedded metadata.
- Files are organized into
{author}/{title}/structure based on their individual metadata. - Important: Files in the same directory will be grouped ONLY if they share identical metadata (author, title, series).
- Ideal for:
- Collections of single-file audiobooks (e.g.,
.epub,.m4bfiles) - Mixed collections where multiple books might be in the same directory
- Collections of single-file audiobooks (e.g.,
- Use Case: When your files are already organized in a directory structure where each directory represents a single book.
- Behavior:
- Assumes all files in the same directory belong to the same book.
- Processes all files in a directory as a single unit with shared metadata.
- Ideal for:
- Multi-file audiobooks (e.g., split
.mp3files) - Pre-organized collections where files are already grouped by book
- Multi-file audiobooks (e.g., split
Flat Mode with Mixed Content:
Input:
/books/
book1_chapter1.mp3 # Metadata: Author A, Book 1
book1_chapter2.mp3 # Metadata: Author A, Book 1
book2_chapter1.mp3 # Metadata: Author B, Book 2
book3.epub # Metadata: Author C, Book 3
Output (with --layout=author-title):
/books/
Author A/
Book 1/
book1_chapter1.mp3
book1_chapter2.mp3
Author B/
Book 2/
book2_chapter1.mp3
Author C/
Book 3/
book3.epub
Non-Flat Mode:
Input:
/books/
Author A - Book 1/
chapter1.mp3
chapter2.mp3
Author B - Book 2/
part1.m4b
part2.m4b
Output (with --layout=author-title):
/books/
Author A/
Book 1/
chapter1.mp3
chapter2.mp3
Author B/
Book 2/
part1.m4b
part2.m4b
- In flat mode, files are ONLY grouped if they have identical metadata. Two MP3s from different books in the same directory will be treated as separate books.
- For multi-file books in flat mode, ensure all files have consistent metadata to be grouped correctly.
- Non-flat mode is recommended when you have pre-organized collections or multi-file books.
- The
--flatflag only affects how files are discovered, not the output structure. The output structure is always determined by the--layoutflag.
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.
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:
To resolve these issues simply click on the Issues button
next use the Remove All x Books button to clean up the errors.
The audiobook organizer includes a built-in update command to easily check for and install new versions:
# Check for updates without installing
audiobook-organizer update --check
# Update to the latest version
audiobook-organizer updateThe update command will:
- Automatically detect how you installed the tool (Homebrew, APT, binary, etc.)
- Check the latest version available on GitHub
- Download and install the update using the appropriate method
- Homebrew: Runs
brew update && brew upgrade audiobook-organizer - APT (Debian/Ubuntu): Provides instructions for
sudo apt-get update && sudo apt-get install --only-upgrade audiobook-organizer - YUM/DNF (RedHat/Fedora): Provides instructions for
sudo yum update audiobook-organizerorsudo dnf update audiobook-organizer - APK (Alpine): Provides instructions for
sudo apk update && sudo apk upgrade audiobook-organizer - Binary/Go Install: Automatically downloads and installs the latest binary
There are various ways to install this - I actually haven't tested the Docker install - but it should work :)
# 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.debcurl -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 -# 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_*.apksudo rpm -i audiobook-organizer_*.rpm
rm audiobook-organizer_*.rpm
# Add the tap repository
brew tap jeeftor/tap
# Install the application
brew install audiobook-organizergo install github.com/jeeftor/audiobook-organizer@latestdocker pull jeffsui/audiobook-organizer:latestLaunch the interactive TUI for a visual, guided experience:
# Launch GUI without arguments - use directory picker
audiobook-organizer gui
# Launch GUI with pre-selected directories
audiobook-organizer gui --input=/path/to/audiobooks --output=/path/to/organizedGUI Keyboard Shortcuts:
- Directory Picker:
↑/↓orj/k: Navigate directoriesEnter: Open/navigate into directoryCtrl+S: Select current directory- Type to filter directories in real-time
ESC: Clear filterCtrl+B: Go up one levelCtrl+H: Jump to home directoryCtrl+R: Jump to root directoryCtrl+Q: Quit
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/audiobooksOptions:
--dir/--input: Base directory to scan (required)--out/--output: Output directory for organized files (optional, defaults to --dir if not specified)--config: Config file (default is $HOME/.audiobook-organizer.yaml)--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--replace_space: Character to replace spaces (optional)--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-series-title-number, author-title, author-only, series-title, series-title-number)--author-fields: Comma-separated list of fields to try for author (e.g., 'authors,narrators,album_artist,artist')--series-field: Field to use as series (e.g., 'series', 'album')--title-field: Field to use as title (e.g., 'album', 'title', 'track_title')--track-field: Field to use for track number (e.g., 'track', 'track_number')
Controls the directory structure of the organized audiobooks. Available options:
Author-based layouts:
author-series-title(default): Organizes asAuthor/Series/Book Title/author-series-title-number: Organizes asAuthor/Series/#1 - Book Title/(includes series number in title directory)author-title: Organizes asAuthor/Book Title/author-only: Organizes asAuthor/with all files directly in the author directory
Series-based layouts (no author directory):
series-title: Organizes asSeries/Book Title/(useful when organizing by series only)series-title-number: Organizes asSeries/#1 - Book Title/(includes series number, no author directory)
When enabled, this flag modifies the directory structure to use the Series field as the main title directory. This is particularly useful for MP3 files where the Series field contains the actual book title.
Behavior:
- When
--use-series-as-titleis set totrueand a Series is present in the metadata, the Series field will be used as the title in the directory structure. - If no Series is present, the flag is ignored and the Title field is used.
- This flag works in conjunction with the
--layoutflag, modifying its behavior.
-
Default Behavior (
--layout=author-series-title --use-series-as-title=false):- With series:
Author/Series/Book Title/ - Without series:
Author/Book Title/
- With series:
-
Using Series as Title (
--layout=author-series-title --use-series-as-title=true):- With series:
Author/Book Title/(uses Series as the title) - Without series:
Author/Book Title/(falls back to Title field)
- With series:
-
Author-Title Layout (
--layout=author-title --use-series-as-title=true):- With series:
Author/Book Title/(uses Series as the title) - Without series:
Author/Book Title/(uses Title field)
- With series:
-
Flat Mode (
--flat --use-series-as-title=true):- With series:
Author - Book Title.mp3(uses Series as the title) - Without series:
Author - Book Title.mp3(uses Title field)
- With series:
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=/booksSeparate 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=/outputInteractive 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 --promptDry 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- Use
:rofor read-only access to source directories - The container paths must match the
--dirand--outparameters - Use
-itflag when running with--promptfor 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
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]
The tool can obtain metadata from two sources:
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"]
}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.
Without series:
/output/Author Name/Book Title/
With series:
/output/Author Name/Series Name #1/Book Title/
/output/Author Name/Book Title/
/output/Author Name/
Organizes by series without author directory. Books without series fall back to title only.
Without series:
/output/Book Title/
With series:
/output/Series Name/Book Title/
Organizes by series with numbered titles. Books without series fall back to title only.
Without series:
/output/Book Title/
With series and series number:
/output/Series Name/#1 - Book Title/
With series but no number:
/output/Series Name/Book Title/
Includes series number in the title directory for better sorting.
/output/Author Name/Series Name/#1 - Book Title/
For MP3 files where the Series field contains the actual book title and Title contains chapter info:
/output/Author Name/Series Name/
/output/Author One,Author Two/Book Title/
/output/Author.Name/Series.Name.#1/Book.Title/
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 --undoThe audiobook organizer supports multiple ways to configure its behavior:
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-series-title-number, author-title, author-only, series-title, series-title-number
use-series-as-title: false # Use Series field as the main title directory for MP3 files
# Metadata field mapping
author-fields: "authors,narrators,album_artist,artist"
series-field: "series"
title-field: "album,title,track_title"
track-field: "track,track_number"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-series-title-number, author-title, author-only, series-title, series-title-number
export AO_USE_SERIES_AS_TITLE=false
export AO_AUTHOR_FIELDS="authors,narrators,album_artist,artist"
export AO_SERIES_FIELD="series"
export AO_TITLE_FIELD="album,title,track_title"
export AO_TRACK_FIELD="track,track_number"
# 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
export AUDIOBOOK_ORGANIZER_AUTHOR_FIELDS="authors,narrators,album_artist,artist"
export AUDIOBOOK_ORGANIZER_SERIES_FIELD="series"
export AUDIOBOOK_ORGANIZER_TITLE_FIELD="album,title,track_title"
export AUDIOBOOK_ORGANIZER_TRACK_FIELD="track,track_number"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-metadataThe configuration values are loaded in the following order (later sources override earlier ones):
- Default values
- Configuration file (
~/.audiobook-organizer.yamlor specified with--config) - Environment variables
- 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



