audiobookshelf/artifacts/2026-02-12/book-merge.md
2026-02-13 14:15:18 +02:00

5.4 KiB

Specification: Merge Books Feature

Implementation Plan

Merge Books Feature Implementation Plan

Goal Description

Allow users to select multiple books (e.g., individual mp3 files improperly imported as separate books) and "Merge" them into a single book. This involves moving all files to a single folder and updating the database to reflect a single library item containing all files.

Proposed Changes

Backend

[NEW] server/controllers/LibraryItemController.js

  • Implement batchMerge(req, res) method.
    • Validation: Ensure user has update/delete permissions. Check all items belong to the same library and are books.
    • Primary Item Selection: Use the first selected item as the "primary" item (the one that will act as the container).
    • Target Folder: Determine the target folder path.
      • If the primary item is already in a suitable folder (e.g. Author/Title), use it.
      • If the items are in the root or disorganized, create a new folder based on the primary item's metadata (Author/Title).
    • File Operations:
      • Iterate through all other selected items.
      • Move their media files (audio, ebook, cover) to the target folder.
      • Handle filename collisions (append counter if needed).
      • Update LibraryItem entries? No, we will rescind the primary item.
    • Database Updates:
      • Delete the other LibraryItem records from the database.
      • Trigger a rescan of the primary item's folder to pick up the new files and update tracks/chapters.
      • Clean up empty source folders of the moved items.

[MODIFY] server/routers/ApiRouter.js

  • Add POST /items/batch/merge route mapped to LibraryItemController.batchMerge.

Frontend

[MODIFY] client/components/app/Appbar.vue

  • Update contextMenuItems computed property.
  • Add "Merge" option when:
    • User has update/delete permissions.
    • Library is a "book" library.
    • Multiple items are selected (selectedMediaItems.length > 1).
  • Implement batchMerge() method to call the API.
    • Add confirmation dialog explaining what will happen.

Verification Plan

Manual Verification

  1. Setup:
    • Add multiple individual mp3 files to the root of a library (or separate folders) so they show up as separate books.
    • Ensure they have some metadata (Title/Author) or add it manually.
  2. Execution:
    • Go to the library in the web UI.
    • Select the multiple "books" (mp3 files).
    • Click the Multi-select "x items selected" bar if not already open (it opens automatically on selection).
    • Click the Context Menu (3 dots) or find the "Merge" button (to be added).
    • Select "Merge".
    • Confirm the dialog.
  3. Result Validation:
    • Verify that the separate books disappear.
    • Verify that one single book remains.
    • Open the remaining book and check "Files" tab. It should contain all the mp3 files.
    • Check the filesystem: Ensure all mp3 files are now in the same folder.
    • Check metadata: Ensure the book plays correctly.

Walkthrough

Merge Books Feature Walkthrough

I have implemented the "Merge Books" feature, which allows users to combine multiple library items (specifically books) into a single library item. This is particularly useful for fixing issues where individual audio files were imported as separate books.

Changes

Backend

  • server/controllers/LibraryItemController.js: Added batchMerge method.
    • Validates that all items are books and from the same library.
    • Identifies a "primary" item (the first one selected).
    • Creates a new folder for the book if the primary item is a file in the root.
    • Moves all media files from the other selected items into the primary item's folder.
    • Deletes the old library items for the moved files.
    • Triggers a scan of the primary item to update metadata and tracks.
    • Cleans up empty authors and series.
  • server/routers/ApiRouter.js: Added POST /api/items/batch/merge route.

Frontend

  • client/components/app/Appbar.vue: Added "Merge" option to the multi-select context menu.
    • Enabled only when multiple books are selected.
    • Shows a confirmation dialog before proceeding.
    • Automatically navigates to the merged book upon success.
  • client/strings/en-us.json: Added localization strings for the new feature.

Verification

Automated Tests

I created a new test file test/server/controllers/LibraryItemController_merge.test.js to verify the backend logic.

To run the verification test:

npx mocha test/server/controllers/LibraryItemController_merge.test.js --exit

Test Results:

  LibraryItemController Merge
    batchMerge
      ✔ should merge two file-based items into a new folder

  1 passing (113ms)

Manual Verification Steps

  1. Identify Split Books: Find a set of books in your library that should be a single book (e.g., "Chapter 1", "Chapter 2" showing as separate books).
  2. Select Books: Enable multi-select and click on the books you want to merge.
  3. Click Merge: In the top URI bar, click the menu button (3 dots) and select Merge.
  4. Confirm: Accept the confirmation dialog ("Are you sure you want to merge...").
  5. Verify:
    • The separate books should disappear.
    • A single book should remain (based on the first selected book).
    • Open the book and check the "Files" tab. It should contain all the audio files.
    • Play the book to ensure tracks are ordered and playable.