Version: abogen 1.3.1 (web UI) Platform: Windows 11, Python 3.12 mutagen: 1.48.1 (installed, as required by mutagen>=1.47.0)
Summary
Every m4b conversion logs this warning:
Unable to write MP4 chapter atoms because mutagen is not installed.
mutagen is installed. The ImportError being caught is not a missing package - it is a missing symbol. mutagen.mp4.MP4Chapter (singular) does not exist in any released version of mutagen, so _apply_m4b_chapters_with_mutagen() can never run, and the message points at the wrong cause.
The output audio is not affected - ffmpeg has already written the chapter data by this point (see "Impact" below). This is a diagnostics bug plus some dead code, not a corruption bug. But the warning is alarming for anyone checking whether their audiobook is properly chaptered.
Reproduce
$ python -c "from mutagen.mp4 import MP4, MP4Chapter"
ImportError: cannot import name 'MP4Chapter' from 'mutagen.mp4'
$ python -c "import mutagen.mp4 as m; print([n for n in dir(m) if 'hap' in n])"
['Chapter', 'MP4Chapters']
Convert anything to m4b and the warning appears in the job log.
Root cause
abogen/webui/conversion_runner.py, _apply_m4b_chapters_with_mutagen() (line 1365):
try:
from fractions import Fraction
from mutagen.mp4 import MP4, MP4Chapter # line 1375 - MP4Chapter does not exist
except ImportError:
job.add_log(
"Unable to write MP4 chapter atoms because mutagen is not installed.",
level="warning",
)
return False
The except ImportError handler assumes the only possible cause is a missing package, so a missing symbol is reported as a missing install.
Two further problems make this function unreachable even if the import were fixed, so it is effectively dead code:
mutagen's chapter support is read-only. MP4Chapters subclasses Sequence and only parses the moov.udta.chpl box. There is no documented API to create or modify chapters. (https://mutagen.readthedocs.io/en/latest/api/mp4.html)
MP4 has no settable .chapters attribute, so line 1420 (mp4.chapters = cast(Any, chapter_objects)) would attach an attribute that save() ignores.
So the code targets an API that mutagen does not provide - possibly a proposed or planned one (cf. quodlibet/mutagen#295).
Impact: none on output
Worth stating explicitly, since the warning implies otherwise. ffmpeg writes the full set of chapter structures before this function is reached, verified on a generated file:
$ ffprobe -v error -show_chapters test_book.m4b # 4 chapters, correct titles
$ # raw atom scan: chpl: True chap: True tref: True text: True
chpl - Nero-style chapter list
chap + tref - QuickTime chapter track reference
a timed-text track carrying the titles
That is everything players need, so the mutagen pass is redundant as well as broken.
Suggested fix
The cleanest fix is probably to drop _apply_m4b_chapters_with_mutagen() entirely along with its call site, since mutagen cannot write chapters and ffmpeg already covers this. That removes ~60 lines of unreachable code.
If you would rather keep it in place pending a future mutagen release that adds write support, the minimal change is to distinguish the two failure modes and stop crying wolf:
- except ImportError:
-
-
"Unable to write MP4 chapter atoms because mutagen is not installed.",
-
-
-
- except ImportError as exc:
-
-
import mutagen # noqa: F401
-
-
-
"Unable to write MP4 chapter atoms because mutagen is not installed.",
-
-
-
-
# mutagen is installed but this release has no writable chapter API
-
# (1.48 exposes read-only Chapter/MP4Chapters, not MP4Chapter).
-
# ffmpeg has already written the chpl/chap atoms and the timed-text
-
# chapter track, so the output is fully chaptered either way.
-
-
"Skipping the mutagen chapter pass: installed mutagen "
-
f"({getattr(mutagen, 'version_string', 'unknown')}) has no writable "
-
f"chapter API ({exc}). Chapters written by ffmpeg are already in place.",
-
-
-
This keeps the genuine "mutagen missing" warning for the case it was written for, and demotes the expected case to debug with an accurate explanation.
I went with the second option locally (lower risk of touching working behaviour), but the first is likely the better upstream change - happy to open a PR for either.
Version: abogen 1.3.1 (web UI) Platform: Windows 11, Python 3.12 mutagen: 1.48.1 (installed, as required by mutagen>=1.47.0)
Summary
Every m4b conversion logs this warning:
Unable to write MP4 chapter atoms because mutagen is not installed.
mutagen is installed. The ImportError being caught is not a missing package - it is a missing symbol. mutagen.mp4.MP4Chapter (singular) does not exist in any released version of mutagen, so _apply_m4b_chapters_with_mutagen() can never run, and the message points at the wrong cause.
The output audio is not affected - ffmpeg has already written the chapter data by this point (see "Impact" below). This is a diagnostics bug plus some dead code, not a corruption bug. But the warning is alarming for anyone checking whether their audiobook is properly chaptered.
Reproduce
$ python -c "from mutagen.mp4 import MP4, MP4Chapter"
ImportError: cannot import name 'MP4Chapter' from 'mutagen.mp4'
$ python -c "import mutagen.mp4 as m; print([n for n in dir(m) if 'hap' in n])"
['Chapter', 'MP4Chapters']
Convert anything to m4b and the warning appears in the job log.
Root cause
abogen/webui/conversion_runner.py, _apply_m4b_chapters_with_mutagen() (line 1365):
The except ImportError handler assumes the only possible cause is a missing package, so a missing symbol is reported as a missing install.
Two further problems make this function unreachable even if the import were fixed, so it is effectively dead code:
mutagen's chapter support is read-only. MP4Chapters subclasses Sequence and only parses the moov.udta.chpl box. There is no documented API to create or modify chapters. (https://mutagen.readthedocs.io/en/latest/api/mp4.html)
MP4 has no settable .chapters attribute, so line 1420 (mp4.chapters = cast(Any, chapter_objects)) would attach an attribute that save() ignores.
So the code targets an API that mutagen does not provide - possibly a proposed or planned one (cf. quodlibet/mutagen#295).
Impact: none on output
Worth stating explicitly, since the warning implies otherwise. ffmpeg writes the full set of chapter structures before this function is reached, verified on a generated file:
$ ffprobe -v error -show_chapters test_book.m4b # 4 chapters, correct titles
$ # raw atom scan: chpl: True chap: True tref: True text: True
chpl - Nero-style chapter list
chap + tref - QuickTime chapter track reference
a timed-text track carrying the titles
That is everything players need, so the mutagen pass is redundant as well as broken.
Suggested fix
The cleanest fix is probably to drop _apply_m4b_chapters_with_mutagen() entirely along with its call site, since mutagen cannot write chapters and ffmpeg already covers this. That removes ~60 lines of unreachable code.
If you would rather keep it in place pending a future mutagen release that adds write support, the minimal change is to distinguish the two failure modes and stop crying wolf:
This keeps the genuine "mutagen missing" warning for the case it was written for, and demotes the expected case to debug with an accurate explanation.
I went with the second option locally (lower risk of touching working behaviour), but the first is likely the better upstream change - happy to open a PR for either.