package services // Audiobook ingestion (handoff item 3, Batch A). The m4b path is // SIDECAR-FIRST: Libation (and Audiobookshelf-compatible tools) write a // metadata.json next to the file carrying narrators/series/ASIN/chapters; // ffprobe is the fallback (and the filler) for duration, codec profile, // bitrate and embedded chapters. ffprobe is an OPTIONAL dependency — when // absent the book still ingests (filename/folder metadata, no chapters // until a rescan runs with ffprobe present). // // The chapters array written into media_items.audio_metadata IS the // format abstraction: embedded m4b chapters, folder-as-book files and // zip-of-audio books all produce {index, title, start, end} entries, so // the locator {chapter, offset_seconds} and the /chapters endpoint never // learn which file model produced them. // // Multi-file books (layout "folder" | "zip", see // media_scanner_audio_multifile.go) additionally carry a tracks array: // one entry per playable file, with its global-seconds start/end and the // path the /audio/:trackIndex streaming endpoint resolves. Single-file // books leave layout and tracks empty — the