[PR #5191] [CLOSED] Add Download by Chapters tool for audiobooks #4456

Closed
opened 2026-04-25 00:50:51 +02:00 by adam · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/advplyr/audiobookshelf/pull/5191
Author: @vdaluz
Created: 4/15/2026
Status: Closed

Base: masterHead: feature/chapter-download


📝 Commits (1)

  • 640c2f9 Add "Download by Chapters" tool for audiobooks

📊 Changes

5 files changed (+347 additions, -1 deletions)

View changed files

📝 client/components/modals/item/tabs/Tools.vue (+66 -1)
📝 client/strings/en-us.json (+4 -0)
📝 server/controllers/LibraryItemController.js (+152 -0)
📝 server/routers/ApiRouter.js (+1 -0)
📝 test/server/controllers/LibraryItemController.test.js (+124 -0)

📄 Description

Summary

  • Adds a Download by Chapters tool in the item tools tab for audiobooks with chapters. The main motivation for this feature is to improve the audiobook user experience in limited players such as the Shokz OpenSwim which are intended for music and have limited or non existent seek/resume functionality.
  • Splits the selected audio file into per-chapter files using ffmpeg -c copy (no re-encoding) and packages them as a ZIP download
  • When a book has multiple audio files (e.g. both .m4b and .mp3), a dropdown lets the user choose which file to split

How it works

Backend (GET /api/items/:id/download-chapters)

  • Accepts an optional ?fileIno= query param to identify which audio file to split; defaults to the first included audio file
  • The endpoint computes each file's start offset (sum of durations of preceding files, ordered by index), filters chapters to those belonging to the selected file, and converts timestamps to file-relative before splitting
  • Splits all chapters in parallel using ffmpeg -c copy (one process per chapter — no re-encoding, fast) into a temporary directory under MetadataPath/cache/items/:id/chapter-split-:timestamp
  • The timestamp suffix prevents collisions between concurrent requests
  • Streams the result as a ZIP (archiver, no compression — audio files are already compressed)
  • Cleans up temp files in a finally block regardless of success or failure
  • Chapter files are named 01 - Chapter Title.ext, 02 - Chapter Title.ext, etc., zero-padded based on total chapter count

Frontend (Tools.vue)

  • New card visible when the book has chapters, the user has download permission, and at least one audio file is present
  • Dropdown to select audio file when more than one is available
  • Button shows "Preparing..." state while the request is in-flight; uses $nextTick + requestAnimationFrame to ensure the state is painted before the (blocking) anchor click

Testing

  1. Open any audiobook with chapters
  2. Go to item detail → Tools tab
  3. "Download by Chapters" card should appear below "Embed Metadata"
  4. If the book has multiple audio files, a dropdown allows selecting which to split
  5. Click "Download ZIP" — button shows "Preparing..." immediately
  6. ZIP downloads containing one file per chapter, named and ordered correctly

Screenshots

image image

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/advplyr/audiobookshelf/pull/5191 **Author:** [@vdaluz](https://github.com/vdaluz) **Created:** 4/15/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `feature/chapter-download` --- ### 📝 Commits (1) - [`640c2f9`](https://github.com/advplyr/audiobookshelf/commit/640c2f98b8b8ae4687dc3754bc8d20429fc2f8d4) Add "Download by Chapters" tool for audiobooks ### 📊 Changes **5 files changed** (+347 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `client/components/modals/item/tabs/Tools.vue` (+66 -1) 📝 `client/strings/en-us.json` (+4 -0) 📝 `server/controllers/LibraryItemController.js` (+152 -0) 📝 `server/routers/ApiRouter.js` (+1 -0) 📝 `test/server/controllers/LibraryItemController.test.js` (+124 -0) </details> ### 📄 Description ## Summary - Adds a **Download by Chapters** tool in the item tools tab for audiobooks with chapters. The main motivation for this feature is to improve the audiobook user experience in limited players such as the Shokz OpenSwim which are intended for music and have limited or non existent seek/resume functionality. - Splits the selected audio file into per-chapter files using `ffmpeg -c copy` (no re-encoding) and packages them as a ZIP download - When a book has multiple audio files (e.g. both `.m4b` and `.mp3`), a dropdown lets the user choose which file to split ## How it works **Backend (`GET /api/items/:id/download-chapters`)** - Accepts an optional `?fileIno=` query param to identify which audio file to split; defaults to the first included audio file - The endpoint computes each file's start offset (sum of durations of preceding files, ordered by `index`), filters chapters to those belonging to the selected file, and converts timestamps to file-relative before splitting - Splits all chapters in parallel using `ffmpeg -c copy` (one process per chapter — no re-encoding, fast) into a temporary directory under `MetadataPath/cache/items/:id/chapter-split-:timestamp` - The timestamp suffix prevents collisions between concurrent requests - Streams the result as a ZIP (`archiver`, no compression — audio files are already compressed) - Cleans up temp files in a `finally` block regardless of success or failure - Chapter files are named `01 - Chapter Title.ext`, `02 - Chapter Title.ext`, etc., zero-padded based on total chapter count **Frontend (`Tools.vue`)** - New card visible when the book has chapters, the user has download permission, and at least one audio file is present - Dropdown to select audio file when more than one is available - Button shows "Preparing..." state while the request is in-flight; uses `$nextTick` + `requestAnimationFrame` to ensure the state is painted before the (blocking) anchor click ## Testing 1. Open any audiobook with chapters 2. Go to item detail → Tools tab 3. "Download by Chapters" card should appear below "Embed Metadata" 4. If the book has multiple audio files, a dropdown allows selecting which to split 5. Click "Download ZIP" — button shows "Preparing..." immediately 6. ZIP downloads containing one file per chapter, named and ordered correctly ## Screenshots <img width="873" height="773" alt="image" src="https://github.com/user-attachments/assets/d4c2d3ae-5b20-46c9-b4a1-1f9a72d1e069" /> <img width="645" height="676" alt="image" src="https://github.com/user-attachments/assets/e2659fb6-2e43-4ba0-9d6b-e77fb9da2f41" /> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2026-04-25 00:50:51 +02:00
adam closed this issue 2026-04-25 00:50:54 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf#4456