feat(audio): embed cover image in audiobook files#197
Conversation
- Add audio cover embedder - Implement format writers for M4B, M4A, MP3, and FLAC using ffmpeg - Add library settings for audio file writes Closes bookorbit#145
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds audio cover embedding end-to-end: DB fields and migration, DTOs and service defaults, audio format writers and ffmpeg-based embedder, refactored file-write service for multi-target writes, client UI for audio settings, and comprehensive tests. ChangesAudio cover embedding for audiobooks
Sequence Diagram(s)sequenceDiagram
participant Client
participant FileWriteService
participant AudioCoverEmbedder
participant FFmpeg
participant DB
Client->>FileWriteService: request writeToFile(bookId)
FileWriteService->>DB: findFilesForBook(bookId) / findLibraryWriteSettingsForBook
FileWriteService->>FileWriteService: resolveWriteTargets (primary + audio tracks)
FileWriteService->>AudioCoverEmbedder: embedCover(tempAudioPath, coverBytes, format)
AudioCoverEmbedder->>FFmpeg: exec ffmpeg args
FFmpeg-->>AudioCoverEmbedder: exit status
AudioCoverEmbedder-->>FileWriteService: success / error
FileWriteService->>DB: insertTargetLog / updateTargetHash / updateLastWrittenAt
FileWriteService-->>Client: aggregated WriteResult
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@client/src/features/library/components/LibraryCreatorFileWrite.vue`:
- Around line 245-275: The audio embedding controls (fileWriteAudioEnabled
toggle and its Max file size input) must be gated by the cover-write setting to
avoid a no-op configuration; update the template so the audio toggle and the
conditional size input are only visible/usable when fileWriteWriteCover is true
— e.g. wrap the entire audio block or the button+input in a
v-if="fileWriteWriteCover" (or disable the toggle via
:disabled="!fileWriteWriteCover" and similarly disable the size input) and
ensure you reference the existing symbols fileWriteAudioEnabled,
handleAudioToggle, fileWriteAudioMaxFileSizeMb, and onAudioMaxSizeInput so
behavior is preserved while preventing enabling audio when fileWriteWriteCover
is off.
In `@server/src/db/migrations/0012_add_audio_file_write_settings.sql`:
- Around line 1-2: The migration currently adds
libraries.file_write_audio_enabled with DEFAULT true NOT NULL which backfills
existing rows to enabled; change that column's default to DEFAULT false NOT NULL
so existing libraries are not auto-opted-in (keep the
file_write_audio_max_file_size_mb addition as-is), and instead ensure any
desired default-for-new-libraries behavior is implemented in the library
creation flow/UI rather than this migration.
In `@server/src/modules/file-write/formats/audio/audio-cover-embedder.ts`:
- Line 25: The execFile call invoking resolveFfmpegPath() with buildFfmpegArgs
currently only sets maxBuffer and can hang; add a timeout option (e.g., 60000
ms) to the options object passed to execFile so the child process is killed
after the timeout and the promise rejects; update the call that uses
FFMPEG_OUTPUT_MAX_BUFFER_BYTES to pass { maxBuffer:
FFMPEG_OUTPUT_MAX_BUFFER_BYTES, timeout: 60000 } (optionally include killSignal
if desired) so ffmpeg won't block indefinitely.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 991a2df7-b21c-4ae2-bd20-38dcff5dd8dc
📒 Files selected for processing (27)
client/src/features/library/components/LibraryCreatorFileWrite.vueclient/src/features/library/components/LibraryCreatorModal.vueclient/src/features/library/components/__tests__/LibraryCreatorFileWrite.spec.tsclient/src/features/library/composables/__tests__/useLibraryCreator.spec.tsclient/src/features/library/composables/useLibraryCreator.tsclient/src/features/settings/__tests__/LibrariesSettings.spec.tspackages/types/src/library.tsserver/src/db/migrations/0012_add_audio_file_write_settings.sqlserver/src/db/migrations/meta/0012_snapshot.jsonserver/src/db/migrations/meta/_journal.jsonserver/src/db/schema/libraries.tsserver/src/modules/file-write/file-write.constants.tsserver/src/modules/file-write/file-write.module.test.tsserver/src/modules/file-write/file-write.module.tsserver/src/modules/file-write/file-write.repository.test.tsserver/src/modules/file-write/file-write.repository.tsserver/src/modules/file-write/file-write.service.test.tsserver/src/modules/file-write/file-write.service.tsserver/src/modules/file-write/formats/audio/audio-cover-embedder.test.tsserver/src/modules/file-write/formats/audio/audio-cover-embedder.tsserver/src/modules/file-write/formats/audio/audio-format-writer.test.tsserver/src/modules/file-write/formats/audio/audio-format-writer.tsserver/src/modules/library/dto/create-library.dto.tsserver/src/modules/library/dto/update-library.dto.tsserver/src/modules/library/library.dto.test.tsserver/src/modules/library/library.service.test.tsserver/src/modules/library/library.service.ts
Change the default value of file_write_audio_enabled from true to false in the database schema and migrations. Automatically disable audio writing in the UI if cover writing is toggled off. Add a 60-second timeout to the ffmpeg child process to prevent hanging when embedding covers.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
🎉 This PR is included in version 1.9.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
What does this PR do?
This PR introduces the ability to embed cover image files directly into audiobook files.
Key additions and features:
AudioCoverEmbedderto write cover art bytes to audio files usingffmpeg.AudioFormatWriterimplementations to supportM4B,M4A,MP3, andFLACaudio formats.LibraryCreatorFileWrite) to include new settings for enabling audio file writes.0012_add_audio_file_write_settings.sql) to persist audio file write settings for libraries.file-writemodule and service architecture.Closes #145
How did you test this?
AudioCoverEmbedderand all supportedAudioFormatWritersubclasses.LibraryCreatorFileWriteUI changes to ensure audio settings toggle correctly.ffmpegsuccessfully embeds the image into the target files without corrupting metadata.Screenshots
Anything non-obvious in the diff?
0012_add_audio_file_write_settings.sql) and a snapshot update to handle the new audio write settings per library.ffmpegunder the hood (execFile) for safe manipulation of audio metadata across multiple varying formats. Tests mock this interaction to verify arguments.Checklist
.env, personal configs)Summary by CodeRabbit