Documentation updates: - All docs/ files: Update project references - Bruno API collection: Update collection name and tests - Device setup guides: Update all examples - Implementation plan: Update database schema examples - README files: Update project references Part of project rename to Bookhoard.
6.9 KiB
EPUB to KEPUB Conversion Service
Overview
The Conversion Service provides on-the-fly EPUB to KEPUB conversion with dual hash storage to ensure cross-device book matching continues to work after format conversion.
Key Features
- On-Demand Conversion: Converts EPUB to KEPUB when requested via OPDS with
?format=kepub - Dual Hash Storage: Stores both original EPUB hash AND converted KEPUB hash in
media_item_formatstable - Conversion Caching: Caches converted files for 24 hours (configurable) to avoid re-conversion
- Hash Preservation: After conversion, both hashes remain queryable for book matching
- Format Integrity: Ensures converted KEPUB maintains all reading progress markers
Architecture
User requests book via OPDS with ?format=kepub
↓
Check media_item_formats table for existing KEPUB
↓
If KEPUB exists and is recent (< 24 hours):
→ Serve pre-converted file
→ Set X-Bookhoard-KEPUB-SHA256 header
↓
If KEPUB doesn't exist or is stale:
→ Convert EPUB→KEPUB on-the-fly
→ Calculate SHA-256 of converted KEPUB
→ Store in media_item_formats (with converted_from_format_id)
→ Serve converted file
→ Set X-Bookhoard-KEPUB-SHA256 header
↓
Device downloads book with hash in response header
↓
Device syncs progress using hash for matching
Configuration
Environment Variables
Add these to your .env file or system_config table:
# Conversion service configuration
BOOKHOARD_CONVERSION_CACHE_DIR=/var/bookhoard/cache/kepub
BOOKHOARD_CONVERSION_TOOL=/usr/bin/kepubify # or /usr/bin/ebook-convert
BOOKHOARD_CONVERSION_CACHE_TTL=24h
Dockerfile Updates
If using kepubify (recommended for Kobo):
# Install kepubify for EPUB→KEPUB conversion
RUN wget -O /usr/bin/kepubify https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-64bit \
&& chmod +x /usr/bin/kepubify
Or install Calibre for ebook-convert:
# Install Calibre for ebook-convert
RUN apt-get update && apt-get install -y calibre
API Usage
Download KEPUB via OPDS
GET /opds/devices/{deviceId}/download/{bookId}?format=kepub
Response Headers:
Content-Type: application/vnd.kobo+xml+zipContent-Disposition: attachment; filename="book.kepub.epub"X-Bookhoard-UUID: uuid-123X-Bookhoard-KEPUB-SHA256: abc123... (KEPUB-specific hash)
Database Schema
media_item_formats Table
CREATE TABLE media_item_formats (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
format_type VARCHAR(10) NOT NULL, -- 'epub', 'kepub', 'pdf', 'cbz'
file_path VARCHAR(500),
file_sha256 CHAR(64), -- Hash for THIS format version
file_size_bytes BIGINT,
mime_type VARCHAR(100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
converted_from_format_id UUID REFERENCES media_item_formats(id), -- Track conversion chain
UNIQUE(media_item_id, format_type)
);
Example Data:
Row 1: media_item_id=uuid-123, format_type='epub', file_sha256='abc123...'
Row 2: media_item_id=uuid-123, format_type='kepub', file_sha256='xyz789...', converted_from_format_id=Row1.id
Implementation Details
Service Methods
ConvertEPUBToKEPUB
Converts an EPUB file to KEPUB format with hash storage.
Parameters:
ctx context.Context: Request contextmediaItemID pgtype.UUID: ID of the media itemepubPath string: Path to the source EPUB file
Returns:
*ConvertedKEPUB: Contains path, SHA256 hash, and cached statuserror: Conversion error if any
Behavior:
- Checks cache for existing KEPUB (recent conversions are reused)
- Performs EPUB→KEPUB conversion using kepubify or ebook-convert
- Calculates SHA-256 hash of converted file
- Stores format record in database with dual hash
- Returns converted file path and hash
Conversion Tools
The service tries conversion tools in this order:
-
kepubify (recommended): Purpose-built KEPUB converter
- Faster and more reliable for Kobo devices
- Download: https://github.com/pgaskin/kepubify/releases
-
ebook-convert (fallback): Part of Calibre suite
- More versatile but slower
- Requires full Calibre installation
Cache Invalidation
Converted KEPUB files are cached for 24 hours by default. This TTL is configurable via:
- Environment variable:
BOOKHOARD_CONVERSION_CACHE_TTL - Code:
conversionCacheTTLfield inConversionService
Testing
Unit Tests
go test ./internal/services/... -v
Manual Testing with Bruno
Use the provided Bruno test:
bruno/opds/Download Book KEPUB (On-the-fly Conversion).bru
This test verifies:
- KEPUB hash header is present
- Hash is 64 characters (SHA-256 format)
- Bookhoard UUID header is present
- Content-Type is correct for KEPUB
Troubleshooting
Conversion Failures
Problem: KEPUB conversion fails Solution:
- Check if kepubify or ebook-convert is installed
- Verify EPUB file is valid and accessible
- Check cache directory permissions:
/var/bookhoard/cache/kepub - Review conversion logs for specific error messages
Cache Issues
Problem: Converted files not being cached Solution:
- Verify cache directory exists and is writable
- Check
BOOKHOARD_CONVERSION_CACHE_DIRenvironment variable - Ensure database can create media_item_formats records
Hash Mismatches
Problem: Progress sync fails after conversion Solution:
- Verify dual hash storage: both EPUB and KEPUB hashes should exist in
media_item_formats - Check
X-Bookhoard-KEPUB-SHA256header in response - Ensure
converted_from_format_idlinks KEPUB to source EPUB
Performance Considerations
First Conversion
- Time: 2-5 seconds per book (depends on file size)
- CPU: Medium (single-threaded conversion)
- I/O: Read EPUB, write KEPUB to cache
Cached Conversions
- Time: < 100ms (database lookup + file serve)
- CPU: Minimal
- I/O: Read cached KEPUB file
Storage Requirements
- Cache Size: ~1.1x original EPUB size (KEPUB is slightly larger)
- Database: ~200 bytes per converted format record
- Recommendation: 10 GB cache per 1000 books
Security
File Access
- Conversion service only processes files from library folders
- Converted files are stored in secure cache directory
- Original files are never modified
Input Validation
- All file paths are validated before conversion
- Media item IDs are verified against database
- User access permissions are checked via OPDS handler
Future Enhancements
Potential improvements:
- Async Conversion: Queue conversions for background processing
- Batch Conversion: Pre-convert entire libraries during off-hours
- Format Variants: Support PDF→EPUB, CBZ→EPUB, etc.
- Quality Settings: Configurable conversion quality/size tradeoffs
- Distributed Caching: Share cache across multiple server instances