A comprehensive audiobook management toolkit for converting Audible files and browsing your audiobook collection.
| Version | Status | Release |
|---|---|---|
| Latest patch | v4.0.3 | |
| Prior patch | v4.0.2 | |
| Prior patch | v4.0.1 | |
| Prior tweak | v4.0.0.2 | |
| Prior tweak | v4.0.0.1 | |
| Prior major | v4.0.0 | |
| Prior minor | v3.11.2 | |
| Prior patch | v3.11.1 | |
| Prior patch | v3.11.0 | |
| Prior patch | v3.9.8 | |
| Prior tweak | v3.9.7.1 |
Badge Color Convention
Each segment: brightgreen → darkgreen → green → yellow (current) / brightred → darkred → red → orange (prior)
This project uses OGG/OPUS as the exclusive audio format. While the included AAXtoMP3 converter supports other formats (MP3, M4A, M4B, FLAC), the library browser, web UI, Docker container, and all tooling are designed and tested only with OGG/OPUS files.
OPUS offers superior audio quality at lower bitrates compared to MP3, making it ideal for audiobooks. I chose this format for my personal library and have no plans to support other formats.
What would need to change for other formats?
- Scanner: Update file extension detection (
.opus→.mp3, etc.) - Database schema: Potentially add format-specific metadata fields
- Web UI: Update MIME types in audio player, file extension filters
- Cover art handling: Different embedding methods per format
- Docker entrypoint: Update file discovery patterns
- API: Modify file serving and content-type headers
Pull requests welcome if you need this functionality.
This project includes a personal fork of AAXtoMP3 (v2.2) for converting Audible AAX/AAXC files to OGG/OPUS format. The original project by KrumpetPirate has been archived, and this fork includes essential fixes for modern AAXC file handling.
Note: While AAXtoMP3 supports multiple output formats (MP3, M4A, M4B, FLAC, OPUS), this toolkit is configured exclusively for OPUS output. See the converter's FORK_README.md for full documentation.
Fork modifications from original AAXtoMP3
Bug Fixes:
- Fixed
tmp_chapter_file: unbound variablecrash when chapter files are missing - Fixed cover extraction for AAXC files (was using hardcoded
-activation_bytesinstead of${decrypt_param}) - Made audible-cli chapter/cover files optional instead of required
New Features:
- Opus cover art embedding via Python mutagen library (FFmpeg cannot embed covers in OGG/Opus)
- Enhanced fallback handling - extracts metadata directly from AAXC when audible-cli files are missing
- Improved logging and user feedback during conversion
Dependencies Added:
mutagen(optional) - Required for Opus cover art embedding
See converter/CHANGELOG.md for version history.
Web-based audiobook library browser with:
- Vintage library-themed interface
- Built-in audio player with playback position saving
- Resume from last position
- Full-text search across titles, authors, and narrators
- Author/Narrator autocomplete with letter group filters (A-E, F-J, K-O, P-T, U-Z)
- Collections sidebar for browsing by category (Fiction, Nonfiction, Mystery, Sci-Fi, etc.)
- Comprehensive sorting: title, author/narrator first/last name, duration, publish date, acquired date, series with sequence, edition
- Smart duplicate detection by title/author/narrator or SHA-256 hash
- Cover art display with automatic extraction
- PDF supplement support (course materials, maps, etc.)
- Genre sync from Audible library export with 250+ genre categories
- Narrator metadata sync from Audible library export
- Production-ready HTTPS server with reverse proxy
# Launch the web interface (production mode)
cd library
./launch-v3.sh
# Opens https://localhost:8443 in your browser
# HTTP requests to port 8081 are automatically redirected to HTTPS
# Uses Waitress WSGI server for production-ready performance
# Or use legacy launcher (development mode)
./launch-v2.sh # Opens http://localhost:8090Note: Your browser will show a security warning (self-signed certificate). Click "Advanced" → "Proceed to localhost" to continue.
# Convert to OPUS (recommended, default for this project)
./converter/AAXtoMP3 --opus --single --use-audible-cli-data input.aaxc
# Interactive mode
./converter/interactiveAAXtoMP3cd library/scanner
python3 scan_audiobooks.py
cd ../backend
python3 import_to_db.pycd library
# Generate file hashes (sequential)
python3 scripts/generate_hashes.py
# Generate hashes in parallel (uses all CPU cores)
python3 scripts/generate_hashes.py --parallel
# Generate with specific worker count
python3 scripts/generate_hashes.py --parallel 8
# View hash statistics
python3 scripts/generate_hashes.py --stats
# Verify random sample of hashes
python3 scripts/generate_hashes.py --verify 20
# Find duplicates
python3 scripts/find_duplicates.py
# Remove duplicates (dry run)
python3 scripts/find_duplicates.py --remove
# Remove duplicates (execute)
python3 scripts/find_duplicates.py --executeSome Audible audiobooks include supplemental PDFs (course materials, maps, reference guides).
# Scan supplements directory and link to audiobooks
cd library/scripts
python3 scan_supplements.py --supplements-dir /path/to/supplements
# In Docker, supplements are scanned automatically on startupBooks with supplements show a red "PDF" badge in the UI. Click to download.
Narrator information is often missing from converted audio files. Sync from your Audible library:
# Export your Audible library metadata (requires audible-cli authentication)
audible library export -f json -o /path/to/Audiobooks/library_metadata.json
# Update database with narrator information (dry run first)
cd library/scripts
python3 update_narrators_from_audible.py
# Apply changes
python3 update_narrators_from_audible.py --executeGenre information enables the Collections sidebar for browsing by category. Sync genres from your Audible library export:
# Export your Audible library metadata (if not already done)
audible library export -f json -o /path/to/Audiobooks/library_metadata.json
# Preview genre matches (dry run)
cd library/scripts
python3 populate_genres.py
# Apply changes
python3 populate_genres.py --executeThe script matches books by ASIN, exact title, or fuzzy title matching (85% threshold). This populates the genres table and enables collection-based filtering in the web UI.
⚠️ EXPERIMENTAL / NOT FULLY TESTED - USE AT YOUR OWN RISKMulti-source audiobook support (Google Play, Chirp, Librivox, etc.) is disabled by default. The only fully tested and verified format is Audible's AAXC.
Known Issues with non-AAXC formats:
- Metadata extraction may be incomplete or incorrect
- Chapter detection/ordering may fail for some sources
- Cover art extraction is unreliable for many formats
- Multi-reader audiobooks (e.g., Librivox) may not be handled correctly
The
audiobooks-multiformatservice and related scripts are disabled. To enable at your own risk, uncomment the watch directories inwatch-multiformat-sources.sh.PRs welcome if you want to improve multi-source support. See: Roadmap Discussion
Multi-source scripts (click to expand)
Import audiobooks from sources beyond Audible (Google Play, Librivox, Chirp, etc.):
# Process Google Play audiobook (ZIP or M4A files)
cd library/scripts
python3 google_play_processor.py /path/to/audiobook.zip --import-db --execute
# Process directory of MP3/M4A chapter files
python3 google_play_processor.py /path/to/chapters/ --import-db --execute
# Enrich metadata from OpenLibrary API
python3 populate_from_openlibrary.py --execute
# Download free audiobooks from Librivox
python3 librivox_downloader.py --search "pride and prejudice"
python3 librivox_downloader.py --id 12345 # Download by Librivox IDThe Google Play processor:
- Accepts ZIP files, directories of chapters, or single audio files (MP3/M4A/M4B)
- Merges chapters into a single OPUS file at 64kbps (optimal for speech)
- Extracts and embeds cover art
- Enriches metadata from OpenLibrary (title, author, subjects)
- Calculates SHA-256 hash automatically
- Imports directly to database with
--import-db
Extract author/narrator names and series info for enhanced sorting:
cd library/scripts
# Preview changes
python3 populate_sort_fields.py
# Apply changes
python3 populate_sort_fields.py --executeThis extracts:
- Author first/last name from full name (handles "J.R.R. Tolkien", "John le Carré", etc.)
- Narrator first/last name
- Series sequence numbers from titles ("Book 1", "#2", "Part 3", Roman numerals)
- Edition information ("20th Anniversary Edition", "Unabridged", etc.)
- Acquired date from file modification time
Install the latest release without cloning the repository:
# One-line installer
curl -sSL https://github.com/greogory/Audiobook-Manager/raw/main/bootstrap-install.sh | bash
# Or download and install manually
wget https://github.com/greogory/Audiobook-Manager/releases/latest/download/audiobooks-*.tar.gz
tar -xzf audiobooks-*.tar.gz
cd audiobooks-*
./install.shClone the repository and run the interactive installer:
git clone https://github.com/greogory/Audiobook-Manager.git
cd Audiobook-Manager
./install.shYou'll be presented with a menu to choose:
- System Installation - Installs application to
/opt/audiobooks, commands to/usr/local/bin, config to/etc/audiobooks(requires sudo). Services are automatically enabled and started. - User Installation - Installs to
~/.local/binand~/.config/audiobooks(no root required) - Exit - Exit without changes
./install.sh --system # Skip menu, system install
./install.sh --user # Skip menu, user install
./install.sh --data-dir /path # Specify data directory
./install.sh --uninstall # Remove installation
./install.sh --no-services # Skip systemd servicesThe installer automatically checks if the required ports (5001, 8443, 8080) are available before installation. If a port is in use, you'll see options to:
- Choose an alternate port
- Continue anyway (if you plan to stop the conflicting service)
- Abort installation
The installer automatically detects storage types (NVMe, SSD, HDD) and warns if performance-critical components would be placed on slow storage:
| Component | Recommended | Why |
|---|---|---|
| Database (audiobooks.db) | NVMe/SSD | High random I/O; 100x faster queries |
| Index files (.index/) | NVMe/SSD | Frequently accessed during operations |
| Audio Library (Library/) | HDD OK | Sequential streaming works well on HDD |
If the database path is on HDD, you'll see a warning with the option to cancel and adjust paths. See docs/ARCHITECTURE.md for detailed recommendations.
If your /tmp directory is mounted as tmpfs (RAM-based filesystem), you'll need to ensure required directories are recreated on each boot. This is a common configuration to reduce SSD/NVMe wear.
Why tmpfs is recommended for /tmp:
- Reduces write wear on SSDs/NVMes (especially important for high-write workloads)
- Faster I/O since it's RAM-backed
- Auto-cleans on reboot
Required /tmp directories:
| Directory | Purpose | Created By |
|---|---|---|
/tmp/audiobook-staging |
In-progress conversions and downloads | tmpfiles.d |
/tmp/audiobook-triggers |
Inter-service signaling | tmpfiles.d |
Setup: The installer configures /etc/tmpfiles.d/audiobooks.conf to recreate these directories on boot. If you're experiencing issues with services failing after reboot, verify:
# Check tmpfiles.d config exists
cat /etc/tmpfiles.d/audiobooks.conf
# Manually recreate directories if needed
sudo systemd-tmpfiles --create /etc/tmpfiles.d/audiobooks.conf
# Verify directories exist
ls -la /tmp/audiobook-staging /tmp/audiobook-triggersSymptoms of missing directories:
- Services fail with "No such file or directory" errors
- Converter reports files stuck in queue but shows "idle"
- Mover service fails silently
See docs/ARCHITECTURE.md for detailed tmpfs architecture.
Both installation modes:
- Create configuration files
- Generate SSL certificates
- Install systemd services
- Set up Python virtual environment
After installation, use these commands:
audiobook-api # Start API server
audiobooks-web # Start web server (HTTPS)
audiobooks-scan # Scan audiobook library
audiobooks-import # Import to database
audiobooks-config # Show configuration
⚠️ IMPORTANT: v3.5.x End of Lifev3.5.x has reached end-of-life and is no longer supported. All users must upgrade to v3.7.0 or later.
- v3.5.x: ⛔ END OF LIFE - No security patches or updates
- v3.6.x: Modular Flask Blueprint architecture required
- v3.7.0+: Current supported release
If upgrading from v3.5.x with the legacy monolithic API, migrate first:
./migrate-api.sh --to-modular --target /opt/audiobooks
Docker installations upgrade by pulling a new image:
# Pull latest image and recreate container
docker-compose pull
docker-compose up -d
# Or with docker directly
docker pull greogory/Audiobook-Manager:latest
docker stop audiobooks && docker rm audiobooks
docker run -d --name audiobooks ... greogory/Audiobook-Manager:latest
# Check running version
docker exec audiobooks cat /app/VERSIONYour data persists in mounted volumes (/audiobooks, /app/data).
Upgrade your installation directly from GitHub releases:
# Upgrade to latest version
audiobook-upgrade
# Upgrade to specific version
audiobook-upgrade --version 3.2.0
# Check for updates without installing
audiobook-upgrade --checkIf you have the repository cloned locally:
# From within the project directory
./upgrade.sh --target /opt/audiobooks
# Or specify both source and target
./upgrade.sh --from-project /path/to/repo --target /opt/audiobooksSwitch between monolithic and modular Flask architectures:
# Check current architecture
./migrate-api.sh --status
# Switch to modular (Flask Blueprints)
./migrate-api.sh --to-modular --target /opt/audiobooks
# Switch to monolithic (single file)
./migrate-api.sh --to-monolithic --target /opt/audiobooks
# Dry run (show what would be done)
./migrate-api.sh --to-modular --dry-runNote: Migration automatically stops services before switching and restarts them after.
Configuration is loaded from multiple sources in priority order:
- System config:
/etc/audiobooks/audiobooks.conf - User config:
~/.config/audiobooks/audiobooks.conf - Environment variables
| Variable | Description |
|---|---|
AUDIOBOOKS_DATA |
Root data directory |
AUDIOBOOKS_LIBRARY |
Converted audiobook files |
AUDIOBOOKS_SOURCES |
Source AAXC files |
AUDIOBOOKS_SUPPLEMENTS |
PDF supplements |
AUDIOBOOKS_HOME |
Application installation directory |
AUDIOBOOKS_DATABASE |
SQLite database path |
AUDIOBOOKS_COVERS |
Cover art cache |
AUDIOBOOKS_CERTS |
SSL certificate directory |
AUDIOBOOKS_LOGS |
Log files directory |
AUDIOBOOKS_STAGING |
Temporary staging directory for conversions (default: /tmp/audiobook-staging) |
AUDIOBOOKS_VENV |
Python virtual environment path |
AUDIOBOOKS_CONVERTER |
Path to AAXtoMP3 converter script |
AUDIOBOOKS_API_PORT |
API server port (default: 5001) |
AUDIOBOOKS_WEB_PORT |
HTTPS web server port (default: 8443) |
AUDIOBOOKS_BIND_ADDRESS |
Server bind address (default: 0.0.0.0) |
AUDIOBOOKS_HTTP_REDIRECT_PORT |
HTTP→HTTPS redirect port (default: 8081) |
AUDIOBOOKS_HTTP_REDIRECT_ENABLED |
Enable HTTP redirect server (default: true) |
AUDIOBOOKS_HTTPS_ENABLED |
Enable HTTPS for web server (default: true) |
AUDIOBOOKS_USE_WAITRESS |
Use Waitress WSGI server for production (default: true) |
AUDIOBOOKS_LIBRARY=/mnt/nas/audiobooks ./launch.shaudiobooks-configAudiobooks/
├── etc/
│ └── audiobooks.conf.example # Config template
├── lib/
│ └── audiobook-config.sh # Config loader (shell)
├── install.sh # Unified installer (interactive)
├── install-user.sh # User installation (standalone)
├── install-system.sh # System installation (standalone)
├── install-services.sh # Legacy service installer
├── launch.sh # Quick launcher
├── converter/ # AAXtoMP3 conversion tools
│ ├── AAXtoMP3 # Main conversion script
│ └── interactiveAAXtoMP3
├── library/ # Web library interface
│ ├── config.py # Python configuration module
│ ├── backend/
│ │ ├── api_server.py # Flask server launcher
│ │ ├── api_modular/ # Modular Flask Blueprints
│ │ │ ├── __init__.py
│ │ │ ├── audiobooks.py # Audiobook endpoints
│ │ │ ├── metadata.py # Metadata endpoints
│ │ │ ├── search.py # Search endpoints
│ │ │ ├── stats.py # Statistics endpoints
│ │ │ ├── operations.py # Background operations
│ │ │ └── utilities.py # Utility endpoints
│ │ ├── import_to_db.py # Database importer
│ │ ├── schema.sql # Database schema
│ │ └── operation_status.py # Operation tracking
│ ├── scanner/
│ │ └── scan_audiobooks.py # Metadata extraction from audio files
│ ├── scripts/
│ │ ├── generate_hashes.py # SHA-256 hash generation (parallel)
│ │ ├── find_duplicates.py # Duplicate detection & removal
│ │ ├── scan_supplements.py # PDF supplement scanner
│ │ ├── populate_sort_fields.py # Extract name/series/edition info
│ │ ├── populate_genres.py # Sync genres from Audible export
│ │ ├── populate_from_openlibrary.py # Enrich from OpenLibrary API
│ │ ├── update_narrators_from_audible.py # Sync narrator metadata
│ │ ├── google_play_processor.py # Process multi-source audiobooks
│ │ ├── librivox_downloader.py # Download free Librivox audiobooks
│ │ ├── cleanup_audiobook_duplicates.py # Database cleanup
│ │ ├── fix_audiobook_authors.py # Author metadata repair
│ │ └── utils/
│ │ └── openlibrary_client.py # OpenLibrary API client
│ └── web-v2/
│ ├── index.html # Main web interface
│ ├── js/library.js # Frontend JavaScript
│ ├── css/library.css # Vintage library styling
│ ├── proxy_server.py # HTTPS reverse proxy
│ └── redirect_server.py # HTTP→HTTPS redirect
├── Dockerfile # Docker build file
├── docker-compose.yml # Docker Compose config
└── README.md
After system installation, files are organized as follows:
/opt/audiobooks/ # Application installation (AUDIOBOOKS_HOME)
├── scripts/ # Canonical script location
│ ├── audiobook-convert
│ ├── download-new-audiobooks
│ ├── move-staged-audiobooks
│ ├── cleanup-stale-indexes # Remove deleted files from indexes
│ ├── build-conversion-queue # Build/rebuild conversion queue
│ ├── upgrade.sh
│ └── ...
├── library/ # Python application
│ ├── backend/ # Flask API
│ ├── scanner/ # Metadata extraction
│ ├── web-v2/ # Web interface
│ └── venv/ # Python virtual environment
├── converter/ # AAXtoMP3
└── VERSION
/usr/local/bin/ # Symlinks for PATH accessibility
├── audiobook-api # Wrapper script
├── audiobooks-convert -> /opt/audiobooks/scripts/audiobook-convert
├── audiobooks-download -> /opt/audiobooks/scripts/download-new-audiobooks
├── audiobooks-move-staged -> /opt/audiobooks/scripts/move-staged-audiobooks
└── ...
${AUDIOBOOKS_DATA}/ # User data directory (e.g., /srv/audiobooks)
├── Library/ # Converted audiobooks (AUDIOBOOKS_LIBRARY)
├── Sources/ # Original AAXC files (AUDIOBOOKS_SOURCES)
├── Supplements/ # PDF supplements
├── .covers/ # Cover art cache (AUDIOBOOKS_COVERS)
├── .index/ # Index files for tracking
│ ├── source_checksums.idx # MD5 checksums of source files
│ ├── library_checksums.idx # MD5 checksums of library files
│ ├── source_asins.idx # ASIN tracking for sources
│ ├── converted.idx # Converted title tracking
│ ├── converted_asins.idx # Converted ASIN tracking
│ └── queue.txt # Conversion queue
└── logs/ # Application logs
/var/lib/audiobooks/ # Database (on fast storage)
└── db/
└── audiobooks.db # SQLite database (AUDIOBOOKS_DATABASE)
/etc/audiobooks/ # System configuration
├── audiobooks.conf # Main config file
└── certs/ # SSL certificates
/tmp/ # Runtime directories (tmpfs recommended)
├── audiobook-staging/ # In-progress conversions (cleared on reboot)
│ └── [author]/[title]/ # Working directories per audiobook
└── audiobook-triggers/ # Inter-service signaling
└── conversion-complete # Signals mover when batch done
Note: If
/tmpis a tmpfs (RAM-based), these directories are recreated on boot via/etc/tmpfiles.d/audiobooks.conf. See tmpfs Considerations for setup details.
Architecture Notes:
- Scripts are installed to
/opt/audiobooks/scripts/(canonical location) - Symlinks in
/usr/local/bin/point to canonical scripts, so upgrades automatically update commands - Wrapper scripts source from
/opt/audiobooks/lib/audiobook-config.sh(canonical path) - Backward-compat symlink:
/usr/local/lib/audiobooks→/opt/audiobooks/lib/ - User data (
${AUDIOBOOKS_DATA}) is separate from application code (/opt/audiobooks/) - Database is placed in
/var/lib/for fast storage (NVMe/SSD recommended) - Services are automatically enabled and started after installation
Browse your library by curated categories:
- Toggle button: Click "Collections" in the results bar to open the sidebar
- Categories: Special (The Great Courses), Main Genres (Fiction, Nonfiction), Nonfiction (History, Science, Biography, Memoir), Subgenres (Mystery & Thriller, Science Fiction, Fantasy, Romance)
- Active filter badge: Shows current collection on toggle button
- Close options: × button, click overlay, or press Escape
- Full-text search: Search across titles, authors, and narrators
- Author filter: Autocomplete dropdown with A-E, F-J, K-O, P-T, U-Z letter groups
- Narrator filter: Autocomplete dropdown with book counts and letter groups
- Collection filter: Browse by category via Collections sidebar
- Clear button: Reset all filters with one click
| Sort By | Description |
|---|---|
| Title (A-Z/Z-A) | Alphabetical by title |
| Author Last Name | Sort by author's last name (Smith, King, etc.) |
| Author First Name | Sort by author's first name |
| Author Full Name | Sort by full author name as displayed |
| Narrator Last Name | Sort by narrator's last name |
| Narrator First Name | Sort by narrator's first name |
| Duration | Longest or shortest first |
| Recently Acquired | By file modification date |
| Newest/Oldest Published | By publication year |
| Series (A-Z with sequence) | Groups series together, ordered by book number |
| Edition | Sort by edition type |
Four detection methods available in the Back Office Duplicates tab:
- By Title/Author/Narrator: Finds books with matching metadata (may be different files)
- By SHA-256 Hash: Finds byte-identical Library files using cryptographic hashes (from database)
- Source File Checksums: Fast MD5 partial checksums to find duplicate .aaxc files in Sources folder
- Library File Checksums: Fast MD5 partial checksums to find duplicate .opus files in Library folder
- Play/pause with progress bar
- Skip forward/back 30 seconds
- Adjustable playback speed (0.5x - 2.5x)
- Volume control
- Position saving: Automatically saves playback position per book
- Resume playback: Click any book to resume from last position
- Audible cloud sync: Bidirectional position sync with Audible (see below)
Seamlessly switch between listening on Audible's apps and your self-hosted library. When you pause a book on your phone, resume at the exact same position in your browser.
- Bidirectional sync: Positions flow both ways between local and Audible cloud
- "Furthest ahead wins": The more advanced position always takes precedence (you never lose progress)
- Automatic player sync: Web player saves positions every 15 seconds to both localStorage and API
- Batch sync: Sync hundreds of books in a single operation
# 1. Install and authenticate audible-cli
pip install audible-cli
audible quickstart
# 2. Store credential for position sync (one-time)
cd /opt/audiobooks/rnd
python3 position_sync_test.py list
# Enter your audible.json password when prompted
# 3. Populate ASINs (matches local books to Audible library)
python3 populate_asins.py --dry-run # Preview
python3 populate_asins.py # Apply
# 4. Run initial sync
python3 position_sync_test.py batch-sync# Check sync status
curl -s http://localhost:5001/api/position/status | python3 -m json.tool
# Should return:
# {
# "audible_available": true,
# "credential_stored": true,
# "auth_file_exists": true
# }The web player automatically saves positions to the API. For comprehensive sync with Audible cloud:
# Manual sync all books
python3 position_sync_test.py batch-sync
# Or use API
curl -X POST http://localhost:5001/api/position/sync-allFor detailed instructions, see docs/POSITION_SYNC.md.
The library exposes a REST API on port 5001:
| Endpoint | Method | Description |
|---|---|---|
/api/audiobooks |
GET | List audiobooks with pagination, search, filtering, sorting |
/api/audiobooks/<id> |
GET | Get single audiobook details |
/api/audiobooks/<id> |
PUT | Update audiobook metadata |
/api/audiobooks/<id> |
DELETE | Delete audiobook from library |
/api/collections |
GET | List available collections with book counts |
/api/stats |
GET | Library statistics (counts, total hours) |
/api/filters |
GET | Available filter options (authors, narrators, genres) |
/api/narrator-counts |
GET | Narrator names with book counts |
/api/stream/<id> |
GET | Stream audio file (supports range requests) |
/covers/<filename> |
GET | Get cover art image |
/health |
GET | API health check |
| Endpoint | Method | Description |
|---|---|---|
/api/duplicates |
GET | List all duplicates |
/api/duplicates/by-title |
GET | Find duplicates by title/author/narrator |
/api/duplicates/delete |
POST | Delete duplicate files |
/api/duplicates/verify |
POST | Verify duplicate detection |
/api/hash-stats |
GET | Hash generation statistics |
| Endpoint | Method | Description |
|---|---|---|
/api/supplements |
GET | List all supplements |
/api/supplements/stats |
GET | Supplement statistics |
/api/supplements/<id>/download |
GET | Download PDF supplement |
/api/supplements/scan |
POST | Scan for new supplements |
| Endpoint | Method | Description |
|---|---|---|
/api/audiobooks/bulk-update |
POST | Update multiple audiobooks |
/api/audiobooks/bulk-delete |
POST | Delete multiple audiobooks |
/api/audiobooks/missing-narrator |
GET | List books without narrator |
/api/audiobooks/missing-hash |
GET | List books without hash |
| Endpoint | Method | Description |
|---|---|---|
/api/utilities/add-new |
POST | Add new audiobooks (incremental scan) |
/api/utilities/rescan |
POST | Full library rescan |
/api/utilities/rescan-async |
POST | Async full library rescan |
/api/utilities/reimport |
POST | Reimport metadata to database |
/api/utilities/reimport-async |
POST | Async reimport metadata |
/api/utilities/generate-hashes |
POST | Generate SHA-256 hashes |
/api/utilities/generate-hashes-async |
POST | Async hash generation |
/api/utilities/generate-checksums-async |
POST | Async MD5 checksum generation (Sources + Library) |
/api/utilities/vacuum |
POST | Vacuum database |
/api/utilities/export-db |
GET | Export SQLite database |
/api/utilities/export-json |
GET | Export as JSON |
/api/utilities/export-csv |
GET | Export as CSV |
| Endpoint | Method | Description |
|---|---|---|
/api/utilities/check-audible-prereqs |
GET | Check for library_metadata.json |
/api/utilities/sync-genres-async |
POST | Sync genres from Audible export |
/api/utilities/sync-narrators-async |
POST | Update narrators from Audible |
/api/utilities/populate-sort-fields-async |
POST | Generate author_sort/title_sort |
/api/utilities/download-audiobooks-async |
POST | Download new audiobooks |
/api/utilities/rebuild-queue-async |
POST | Rebuild conversion queue |
/api/utilities/cleanup-indexes-async |
POST | Remove stale index entries |
Note: All sync endpoints accept
{"dry_run": true}(default) for preview mode. Set{"dry_run": false}to apply changes.
| Endpoint | Method | Description |
|---|---|---|
/api/operations/status/<id> |
GET | Get operation status |
/api/operations/active |
GET | List active operations |
/api/operations/all |
GET | List all operations |
/api/operations/cancel/<id> |
POST | Cancel running operation |
| Endpoint | Method | Description |
|---|---|---|
/api/system/version |
GET | Get installed version |
/api/system/services |
GET | Get status of all services |
/api/system/services/<name>/start |
POST | Start a service |
/api/system/services/<name>/stop |
POST | Stop a service |
/api/system/services/<name>/restart |
POST | Restart a service |
/api/system/services/start-all |
POST | Start all services |
/api/system/services/stop-all |
POST | Stop processing services |
/api/system/upgrade |
POST | Start upgrade (async) |
/api/system/upgrade/status |
GET | Get upgrade progress |
/api/system/projects |
GET | List available project dirs |
Note: Service control and upgrades use a privilege-separated helper service pattern. The API writes requests to
/var/lib/audiobooks/.control/which triggers a root-privileged helper via systemd path unit.
| Endpoint | Method | Description |
|---|---|---|
/api/position/<id> |
GET | Get playback position for audiobook |
/api/position/<id> |
PUT | Update local playback position |
/api/position/sync/<id> |
POST | Sync single book with Audible (furthest ahead wins) |
/api/position/sync-all |
POST | Batch sync all books with ASINs |
/api/position/syncable |
GET | List all syncable audiobooks |
/api/position/history/<id> |
GET | Get position history for audiobook |
/api/position/status |
GET | Check if position sync is available |
Note: Position sync requires the
audiblePython library and stored credentials via system keyring. Runrnd/position_sync_test.pyto set up initial authentication.
page- Page number (default: 1)per_page- Items per page (default: 50, max: 200)search- Full-text search queryauthor- Filter by author namenarrator- Filter by narrator namecollection- Filter by collection slug (e.g.,fiction,mystery-thriller,great-courses)sort- Sort field (title, author, author_last, narrator_last, duration_hours, acquired_date, published_year, series, edition)order- Sort order (asc, desc)
The SQLite database stores audiobook metadata with the following key fields:
| Field | Type | Description |
|---|---|---|
id |
INTEGER | Primary key |
title |
TEXT | Audiobook title |
author |
TEXT | Full author name |
author_last_name |
TEXT | Extracted last name for sorting |
author_first_name |
TEXT | Extracted first name for sorting |
narrator |
TEXT | Full narrator name(s) |
narrator_last_name |
TEXT | Extracted last name for sorting |
narrator_first_name |
TEXT | Extracted first name for sorting |
series |
TEXT | Series name (if part of series) |
series_sequence |
REAL | Book number in series (e.g., 1.0, 2.5) |
edition |
TEXT | Edition info (e.g., "20th Anniversary Edition") |
duration_hours |
REAL | Duration in hours |
published_year |
INTEGER | Year of publication |
acquired_date |
TEXT | Date added to library (YYYY-MM-DD) |
file_path |
TEXT | Full path to audio file |
file_size_mb |
REAL | File size in megabytes |
sha256_hash |
TEXT | SHA-256 hash for duplicate detection |
cover_path |
TEXT | Path to extracted cover art |
asin |
TEXT | Amazon Standard Identification Number |
isbn |
TEXT | International Standard Book Number |
source |
TEXT | Audiobook source (audible, google_play, librivox, chirp, etc.) |
content_type |
TEXT | Audible content classification (Product, Podcast, Lecture, etc.) |
Additional tables: supplements (PDF attachments), audiobook_genres, audiobook_topics, audiobook_eras
Additional views: library_audiobooks (filters to standard audiobook content types)
Run the library in Docker for easy cross-platform deployment. The Docker container automatically initializes the database on first run - just mount your audiobooks and start the container.
# Pull and run with a single command
docker run -d \
--name audiobooks \
-p 8443:8443 \
-p 8080:8080 \
-v /path/to/your/audiobooks:/audiobooks:ro \
-v audiobooks_data:/app/data \
-v audiobooks_covers:/app/covers \
ghcr.io/greogory/Audiobook-Manager:latest
# Access the web interface
open https://localhost:8443On first run, the container automatically:
- Detects mounted audiobooks
- Scans and indexes your library
- Imports metadata into the database
- Starts the web and API servers
# Set your audiobooks directory
export AUDIOBOOK_DIR=/path/to/your/audiobooks
# Optional: Set supplements directory for PDFs
export SUPPLEMENTS_DIR=/path/to/supplements
# Build and run
docker-compose up -d
# Access the web interface
open https://localhost:8443# Build the image
docker build -t audiobooks .
# Run with your audiobook directory
docker run -d \
--name audiobooks \
-p 8443:8443 \
-p 8080:8080 \
-v /path/to/audiobooks:/audiobooks:ro \
-v audiobooks_data:/app/data \
-v audiobooks_covers:/app/covers \
audiobooks| Variable | Default | Description |
|---|---|---|
AUDIOBOOK_DIR |
/audiobooks |
Path to audiobooks inside container |
DATABASE_PATH |
/app/data/audiobooks.db |
SQLite database path |
COVER_DIR |
/app/covers |
Cover art cache directory |
SUPPLEMENTS_DIR |
/supplements |
PDF supplements directory |
WEB_PORT |
8443 |
HTTPS web interface port |
API_PORT |
5001 |
REST API port |
| Volume | Purpose |
|---|---|
audiobooks_data |
Persists SQLite database across container restarts |
audiobooks_covers |
Persists cover art cache |
If you need to manually rescan or update your library:
# Rescan audiobook directory
docker exec -it audiobooks python3 /app/scanner/scan_audiobooks.py
# Re-import to database
docker exec -it audiobooks python3 /app/backend/import_to_db.py
# View README inside container
docker exec -it audiobooks cat /app/README.mdThe container includes a health check that verifies the API is responding:
# Check container health
docker inspect --format='{{.State.Health.Status}}' audiobooks# View container logs
docker logs audiobooks
# Check running processes
docker exec -it audiobooks ps aux
# Access container shell
docker exec -it audiobooks /bin/bash
# Restart container (re-runs initialization)
docker restart audiobooks- Python 3.8+
- ffmpeg 4.4+ (with ffprobe)
- Flask (CORS handled natively since v3.2.0)
- openssl (for SSL certificate generation)
# Create virtual environment and install dependencies
cd library
python3 -m venv venv
source venv/bin/activate
pip install flask
# Scan your audiobooks
cd scanner
python3 scan_audiobooks.py
# Import to database
cd ../backend
python3 import_to_db.pyAll services use the audiobooks-* naming convention for easy management.
| Service | Description | Type |
|---|---|---|
audiobook-api |
Flask REST API (Waitress) on localhost:5001 | always running |
audiobook-proxy |
HTTPS reverse proxy on 0.0.0.0:8443 | always running |
audiobook-converter |
AAXC → OPUS conversion | always running |
audiobook-mover |
Move converted files from tmpfs to storage | always running |
audiobook-downloader.timer |
Download new Audible audiobooks (every 4h) | timer |
audiobooks-library-update.timer |
Update database with new audiobooks | timer |
audiobook-shutdown-saver |
Save staging files before shutdown | on shutdown |
audiobooks-conversion-trigger.path |
Watch for new downloads | path watcher |
audiobooks-database-trigger.path |
Watch for completed conversions | path watcher |
| Service | Description |
|---|---|
audiobooks-multiformat |
Non-AAXC format conversion (Google Play, Chirp, Librivox) |
audiobooks-librivox.timer |
Download from Librivox wishlist |
System services run at boot without requiring login. The installer automatically enables all services.
All audiobook services are grouped under audiobook.target, allowing you to control them all with a single command:
# Start ALL audiobook services at once
sudo systemctl start audiobook.target
# Stop ALL audiobook services at once
sudo systemctl stop audiobook.target
# Restart ALL audiobook services at once
sudo systemctl restart audiobook.target
# Check status of the target (shows all member services)
sudo systemctl status audiobook.targetYou can also manage individual services when needed:
# Check all audiobooks services
sudo systemctl status 'audiobooks-*'
# Restart just the API server
sudo systemctl restart audiobook-api
# View logs for a specific service
journalctl -u audiobook-api -f
# View all audiobook service logs since today
journalctl -u 'audiobooks-*' --since today| Service | Purpose |
|---|---|
audiobook-api |
REST API backend (port 5001) |
audiobook-proxy |
HTTPS reverse proxy (port 8443) |
audiobook-converter |
Continuous AAXC → Opus conversion |
audiobook-mover |
Moves converted files to library |
audiobook-downloader.timer |
Scheduled Audible downloads |
The converter service runs with low CPU and I/O priority to avoid impacting interactive use:
- CPU:
nice -n 19(lowest priority) - I/O:
ionice -c 2 -n 7(best-effort, lowest priority within class)
This ensures audiobook conversion happens in the background without affecting system responsiveness.
If your audiobook library is stored on HDDs, NAS, or network mounts that may not be immediately available at boot, you need to configure the services to wait for those mounts.
Symptom: Services fail at boot with errors like:
Failed at step NAMESPACE spawning /bin/sh: No such file or directory
audiobook-api.service: Failed with result 'exit-code'.
The service typically recovers after a few restart attempts (once the mount is ready), but this can be fixed properly.
Solution: Edit the service file to include your data path in RequiresMountsFor:
# Edit the API service
sudo systemctl edit --full audiobook-api.serviceIn the [Unit] section, add your data path to RequiresMountsFor:
[Unit]
# ... existing directives ...
# Add your data mount path alongside /opt/audiobooks
RequiresMountsFor=/opt/audiobooks /path/to/your/audiobooksCommon scenarios:
| Storage Type | Example Path | Notes |
|---|---|---|
| Secondary HDD | /mnt/data/Audiobooks |
Add to RequiresMountsFor |
| BTRFS subvolume | /raid0/Audiobooks |
Add to RequiresMountsFor |
| NFS mount | /mnt/nas/audiobooks |
Also add After=remote-fs.target |
| CIFS/SMB mount | /mnt/share/audiobooks |
Also add After=remote-fs.target |
For network mounts, also add network dependencies:
[Unit]
After=network-online.target remote-fs.target
Wants=network-online.target
RequiresMountsFor=/opt/audiobooks /mnt/nas/audiobooksAfter editing, reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart audiobook-api.serviceWhy this happens: The audiobook-api service uses ProtectSystem=strict for security hardening, which requires all paths in ReadWritePaths to be available when setting up the service's filesystem namespace. If your data path uses nofail mount options (common for non-critical mounts), systemd won't wait for it by default.
This project would not be possible without the incredible work of many developers and open-source communities. I am deeply grateful to:
-
KrumpetPirate and the 55+ contributors to AAXtoMP3 - The foundation of the converter component. Years of community effort went into building this essential tool for the audiobook community.
-
mkb79 for audible-cli - An indispensable CLI tool for interacting with Audible's API, downloading books, and extracting metadata. This project relies heavily on audible-cli for AAXC decryption and metadata.
-
FFmpeg - The Swiss Army knife of multimedia processing. FFmpeg handles all audio conversion, metadata extraction, and stream processing in this project.
-
Flask by the Pallets Projects team - The lightweight Python web framework powering the REST API.
-
SQLite - The embedded database engine that stores and indexes the audiobook library with remarkable efficiency.
-
mutagen - Python library for handling audio metadata, essential for embedding cover art in Opus files.
-
Claude Code (Anthropic) - AI coding assistant that helped with implementation details, debugging, and documentation throughout development.
-
CachyOS - The Arch-based Linux distribution where this project was developed and tested. CachyOS provides an excellent development environment with up-to-date packages and performance optimizations.
Special thanks to the broader audiobook and self-hosting communities on Reddit (r/audiobooks, r/selfhosted) and various forums for sharing knowledge, workarounds, and inspiration for managing personal audiobook libraries.
This project is a personal tool shared in the hope that others might find it useful. All credit for the underlying technologies belongs to their respective creators and communities.
- CI Fix: Fixed Docker workflow to support 4-digit tweak versions (X.Y.Z.W)
- Documentation Fix: Corrected migration path in CHANGELOG.md (was
migrations/nowlibrary/backend/migrations/)
- BREAKING: Periodicals Feature Removed: The "Reading Room" periodicals subsystem (podcasts, newspapers, meditation) has been extracted to a separate R&D branch (
feature/periodicals-rnd). This simplifies the main codebase to focus on audiobooks only.- Migration
010_drop_periodicals.sqlremoves periodicals tables - To restore periodicals, use tag
v3.11.2-with-periodicals
- Migration
- Podcast Episode Download & Conversion: Full support for downloading and converting podcast episodes from Audible
- Periodicals Orphan Detection: Find and delete episodes whose parent series no longer exists
- Security Fixes: SQL injection prevention, log injection fixes, XSS prevention in library.js
- Periodicals SSE Fix: Fixed Flask request context issue in SSE generator
- Build Queue Fix: Fixed to only process AAX/AAXC files, not MP3 podcasts
- Deploy Fix: Fixed
deploy.shto include root-level management scripts (upgrade.sh,migrate-api.sh) that were being silently skipped during deployment
- Periodicals Sorting: Reading Room supports title, date, subscription, and download status sorting
- Whispersync Position Sync: Periodicals now sync listening positions with Audible
- Auto-Download: Subscribed podcast series automatically queue new episodes
- Podcast Expungement: Complete removal of unsubscribed podcast content
- Test Fixes: Resolved 19 test failures, improved code quality
- Architecture Documentation: Comprehensive ARCHITECTURE.md update with Scanner Module, API Module, Systemd Services, and Scripts Reference sections
- Periodicals Sync: Enhanced parent/child hierarchy support for podcast episodes
- Hardcoded Paths Fix: Fixed 2 hardcoded paths in shell scripts, removed invalid inline comments from systemd files
- BREAKING: Naming Convention Standardization: All service names, CLI commands, and config files now use singular "audiobook-" prefix instead of plural "audiobooks-" to align with project name
- Status Script Enhancement:
audiobook-statusnow displays services and timers in separate sections - Documentation Dates: Updated last-modified dates in ARCHITECTURE.md and POSITION_SYNC.md
- Major Refactoring: Split monolithic
utilities_ops.py(994 lines) into modular package with 5 focused modules - Test Coverage: Added 27 new test files, increased coverage from 77% to 85%
- Code Quality: Removed unused imports, fixed incorrect default paths
- Audit Fixes: PIL rebuilt for Python 3.14, flask-cors removed from install scripts, systemd ConditionPathExists paths fixed
- Upgrade Script Path Bug: Fixed
upgrade-helper-processreferencing wrong path (was/opt/audiobooks/upgrade.sh, now/opt/audiobooks/scripts/upgrade.sh) - Duplicate Finder Endpoint: Fixed JavaScript calling non-existent
/api/duplicates/by-hash(now/api/duplicates) - Upgrade Script Sync: Root-level management scripts now properly sync during upgrades
- Security Hardening: Fix CVE-2025-43859 (h11 HTTP smuggling), enforce TLS 1.2 minimum, add SSRF path validation
- CodeQL Remediation: Fix 30 code scanning alerts (stack trace exposure, empty except handlers, type errors)
- Code Quality: Fix ruff linting errors, add missing type imports, improve error logging
- Version Badges: Multi-segment version badges with hierarchical color scheme
- Documentation: Version history table showing release progression
- Schema Tracking: Database schema now tracked in git (schema.sql)
- Content Filter: Expanded AUDIOBOOK_FILTER to include Lecture, Performance, Speech types
- Reliability: Prevent concurrent queue rebuild processes with flock
- Scripts: Fixed shellcheck warnings in build scripts
- Security: Replace insecure mktemp() with mkstemp() for temp file creation
- Reliability: Add signal trap to converter script for clean FFmpeg shutdown
- Code Quality: Fix missing imports, remove unused variables, add exception logging
- Periodicals (Reading Room): Simplified to flat data schema with skip list support
- Mover Service: Fixed process stampede with flock wrapper
- Periodicals "Reading Room": New subsystem for Audible episodic content
- Manages podcasts, newspapers, meditation series separately from main library
- Real-time sync status via Server-Sent Events (SSE)
- Individual or bulk episode download queuing
- Twice-daily auto-sync via systemd timer (06:00 and 18:00)
- Security Fixes: Patched CVE-2026-21441 (urllib3), CVE-2025-43859 (h11)
- Code Cleanup: Removed deprecated Flask-CORS, dead CSS code
- Position Sync with Audible: Bidirectional playback position synchronization
- "Furthest ahead wins" conflict resolution - you never lose progress
- Seamlessly switch between Audible apps and self-hosted library
- Web player auto-saves every 15 seconds to both localStorage and API
- Batch sync all books with ASINs in a single operation
- Comprehensive Documentation: New
docs/POSITION_SYNC.mdwith setup guides, API reference, troubleshooting
- Position Sync API: Bidirectional playback position synchronization with Audible cloud
- Sync single books or batch sync all audiobooks with ASINs
- "Furthest ahead wins" logic for conflict resolution
- Position history tracking
- Bug Fixes: Service timer control, download path, database vacuum improvements
- Upgrade System: Fixed non-interactive upgrade failures in systemd service
- Fixed bash arithmetic causing exit code 1 with
set -e - Auto-confirm prompts when triggered from web UI
- Fixed bash arithmetic causing exit code 1 with
- UI: Changed dark green text to cream-light for better contrast
- Security: Privilege-separated helper service for system operations
- API now runs with
NoNewPrivileges=yessecurity hardening - Service control and upgrades work via file-based IPC with helper service
- API now runs with
- System Administration API: New
/api/system/*endpoints for service control and upgrades - Web UI: Back Office can now start/stop/restart services and trigger upgrades
- Fixes: Service control from web UI, upgrade from web UI, race conditions
No longer supported. Upgrade to v3.7.0 or later immediately. No security patches or updates will be released for 3.5.x.
- Checksum Tracking: MD5 checksums (first 1MB) generated automatically during download and move operations for fast duplicate detection
- Generate Checksums: New Utilities button to regenerate all checksums for Sources (.aaxc) and Library (.opus) files
- Index Cleanup:
cleanup-stale-indexesscript removes entries for deleted files from all indexes; automatic cleanup on file deletion - Bulk Operations Redesign: Clear step-by-step workflow (Filter → Select → Act) with explanatory intro, descriptive filter options, and use-case examples
- Conversion Queue: Hybrid ASIN + title matching for accurate queue building, real-time index updates after each conversion
- UI Streamlining: Removed redundant Audiobooks tab from Back Office (search available on main page)
- Fixes: Queue builder robustness, mover timing optimization, version display
- Refactoring: Split utilities.py (1067 lines) into 4 focused sub-modules with reduced complexity
- Scanner: New shared
metadata_utils.pymodule, complexity D(24) → A(3) - Quality: Average cyclomatic complexity reduced from D to A (3.7)
- Fixes: Conversion progress accuracy, queue count sync, code cleanup
- Architecture: Comprehensive ARCHITECTURE.md guide with install/upgrade/migrate workflows
- Install: Fixed to use
/opt/audiobooksas canonical location with auto-service start - Migrate: Added service stop/start lifecycle to
migrate-api.sh - Symlinks: Wrapper scripts now source from canonical
/opt/audiobooks/lib/path
- Collections: Per-job conversion stats, sortable active conversions, text-search based genres
- Config: Fixed critical DATA_DIR config reading issue
- Covers: Cover art now stored in data directory (
${AUDIOBOOKS_DATA}/.covers)
- Conversion Monitor: Real-time progress bar, rate calculation, ETA in Back Office
- Upgrade: Auto stop/start services during upgrade
- Docker Build: Added Docker build job to release workflow for automated container builds
- Performance: Increased default parallel conversion jobs from 8 to 12
- Cleanup: Removed redundant config fallbacks from scripts (single source of truth)
- GitHub Releases: Standalone installation via
bootstrap-install.sh - Upgrade System: GitHub-based upgrades with
audiobook-upgrade --from-github - Release Automation: CI/CD workflow and release tarball builder
- Repository Renamed:
audiobook-toolkit→Audiobook-Manager - Removed Flask-CORS: CORS now handled natively by the application
- Cleanup: Removed legacy
api.py(2,244 lines) andweb.legacy/directory - Security: Fixed SQL injection in
generate_hashes.py, Flask blueprint registration
- Fix: RuntimeDirectoryMode changed from 0755 to 0775 for group write access
- Install Manifest:
install-manifest.jsonfor production validation - API Migration: Tools for switching between monolithic and modular architectures
- Modular API: Flask Blueprint architecture (
api_modular/) - Testing: Fixed 7 hanging tests, resolved mock path issues
- Quality: Fixed 13 shellcheck warnings, 18 mypy type errors
- Security: SQL injection fix in genre queries, non-root Docker user
- Docker: Pinned base image to
python:3.11.11-slim - Ports: Standardized to 8443 (HTTPS), 8080 (HTTP redirect)
- Documentation: Added LICENSE, CONTRIBUTING.md, CHANGELOG.md
- The Back Office: New utilities page with vintage library back-office aesthetic
- Database management: stats, vacuum, rescan, reimport, export (JSON/CSV/SQLite)
- Metadata editing: search, view, and edit audiobook metadata
- Duplicate management: find and remove duplicates by title/author or SHA-256 hash
- Bulk operations: select multiple audiobooks, bulk update fields, bulk delete
- API Enhancements: PUT/DELETE endpoints for editing, storage size and database size in stats
- Smart Author/Narrator Sorting: Sort by last name, first name
- Single author: "Stephen King" → sorts as "King, Stephen"
- Co-authored: "Stephen King, Peter Straub" → appears in both K and S letter groups
- Anthologies: "Gaiman (contributor), Martin (editor)" → sorts by editor (Martin)
- Role suffixes stripped: "(editor)", "(translator)", "- editor" handled correctly
- Proxy Server: Added PUT/DELETE method support for utilities operations
- Removed: Find Duplicates dropdown from main Library page (moved to Back Office)
- Metadata Preservation: Import now preserves manually-populated narrator and genre data from Audible exports, preventing data loss on reimport
- Improved Deduplication: Scanner now intelligently deduplicates between main library and
/Library/Audiobook/folder, preferring main library files while keeping unique entries - Security: Updated flask-cors from 4.0.0 to 6.0.0 (fixes CVE-2024-6839, CVE-2024-6844, CVE-2024-6866)
- Multi-source audiobook support (Google Play, Librivox, OpenLibrary)
- Parallel SHA-256 hash generation (24x speedup on multi-core systems)
- Automatic hashing during import
- New
isbnandsourcedatabase fields
- Collections sidebar for browsing by category
- Genre sync from Audible library export
- Author/narrator autocomplete with letter group filters
- Enhanced sorting options (first/last name, series sequence, edition)
- Narrator metadata sync from Audible
- Docker auto-initialization
- Portable configuration system
- Production-ready HTTPS server with Waitress
See GitHub Releases for full version history.
| Issue | Workaround | Status |
|---|---|---|
| Browser security warning for self-signed SSL cert | Click "Advanced" → "Proceed to localhost" | By design |
| Narrator/genre data must be re-synced after adding new books | Run update_narrators_from_audible.py and populate_genres.py after importing |
Planned: Auto-sync on import |
| ✅ Fixed in v3.0 (Back Office) | ||
| ✅ Fixed in v3.0 (Back Office) |
The next major focus is hardening the application with security as a first-class design principle:
- Certificate Authority Integration: Support for Let's Encrypt and other trusted CAs (currently uses self-signed certificates)
- Authentication & Authorization: Optional user authentication for multi-user deployments
- Audit Logging: Track all operations for security compliance
- Input Validation: Comprehensive input sanitization across all endpoints
- Secrets Management: Secure credential storage for Audible API keys and service accounts
- Container Hardening: Read-only filesystems, non-root execution, minimal base images
- Network Security: Rate limiting, CORS policies, CSP headers
A new "Utilities" or "Library Management" section in the webapp for:
Database Management
- View database statistics (total books, storage, duplicates)
- Trigger full library rescan from web UI
- Rebuild search index
- Export/import database backups
Duplicate Management
- Visual duplicate finder with side-by-side comparison
- One-click duplicate removal (keep highest quality)
- Merge duplicate entries (combine metadata from multiple sources)
Audiobook Management
- Delete audiobooks from library (with file deletion option)
- Edit metadata directly in webapp (title, author, narrator, series)
- Bulk operations (delete selected, update metadata)
- Move/reorganize files within library structure
Audible Integration
- Sync library with Audible account (via audible-cli)
- Download missing audiobooks directly
- Remove audiobooks from Audible library (with confirmation)
- Auto-import new Audible purchases
Import Tools
- Drag-and-drop audiobook import
- Bulk conversion from AAX/AAXC
- Multi-source import wizard (Google Play, Librivox, manual)
- Metadata lookup and enrichment
- Chapter navigation
- Bookmarks and notes
- Sleep timer
- Queue/playlist management
- Responsive design improvements
- Progressive Web App (PWA) support
- Offline playback caching
Feature requests and pull requests welcome! See the GitHub Issues page.
See individual component licenses in converter/LICENSE and library/ files.