Skip to content

fix(backend): correct M4A embedded cover extraction and validation#3705

Merged
gantoine merged 3 commits into
rommapp:masterfrom
VoidHandler:fix/m4a-cover-extract
Jul 9, 2026
Merged

fix(backend): correct M4A embedded cover extraction and validation#3705
gantoine merged 3 commits into
rommapp:masterfrom
VoidHandler:fix/m4a-cover-extract

Conversation

@VoidHandler

@VoidHandler VoidHandler commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description
When uploading a soundtrack in .m4a format, the embedded cover doesn't show up because has error extracting the cover.

This PR Fixes embedded soundtrack cover handling for .m4a and other audio formats.

  1. Broken M4A extraction_extract_picture_from_mp4 referenced a non-existent MP4.Cover attribute, causing cover extraction to fail on valid M4A files. Cover MIME is now derived from the actual image bytes instead of broken or unreliable container metadata.
  2. Mislabeled cover bytes — non-JPEG/PNG covers (e.g. GIF, or entries with missing/wrong format metadata) were persisted as image/jpeg with a .jpg extension, so clients could not render them. Embedded cover bytes are now validated via magic-byte sniffing; only JPEG and PNG are accepted.
  3. Silent cover drops — when has_embedded_cover was true but extraction or persistence failed, the track was saved with missing cover art and incorrect metadata. Upload and scan callers now log the failure and set has_embedded_cover=False.

Checklist

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Screenshots (if applicable)

N/A (backend-only fix)


AI assistance disclosure

This PR was developed with Cursor AI assistance (writing unit tests and MIME type detection).
I verified the fix against real M4A, FLAC, MP3, OGG and WAV files.

MP4Cover.FORMAT_PNG was referenced via a non-existent MP4.Cover attribute,
breaking cover extraction for m4a files. Add unit tests and guard
extract_embedded_cover so failures do not abort the upload path.
@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes embedded audio cover extraction and persistence. The main changes are:

  • MP4 cover MIME detection now uses image bytes instead of container metadata.
  • Embedded cover data is limited to JPEG and PNG by magic-byte checks.
  • Upload and scan paths clear has_embedded_cover when cover persistence returns no path.
  • Tests cover MP4 extraction, MIME sniffing, unsupported covers, and persistence failure handling.

Confidence Score: 4/5

This is close, but the cover failure path should be fixed before merging.

  • MP4 MIME detection and JPEG/PNG validation address the mislabeled-cover path.
  • Extraction failures are still returned as None, which callers treat as no embedded cover.
  • Tracks can still be saved with incorrect cover metadata after a real extraction failure.

backend/utils/audio_tags.py

Important Files Changed

Filename Overview
backend/utils/audio_tags.py Adds JPEG/PNG cover validation and updates extractors, but still turns extraction failures into the no-cover result.
backend/endpoints/roms/soundtrack.py Clears embedded-cover metadata when upload cover persistence returns no path.
backend/handler/scan_handler.py Clears embedded-cover metadata when scan cover persistence returns no path.
backend/tests/utils/test_audio_tags.py Adds focused tests for MP4 cover extraction, MIME sniffing, and persistence failure behavior.

Fix All in Claude Code

Reviews (2): Last reviewed commit: "fix(backend): validate embedded cover fo..." | Re-trigger Greptile

Comment thread backend/utils/audio_tags.py Outdated
Comment thread backend/utils/audio_tags.py Outdated
@VoidHandler VoidHandler marked this pull request as draft July 8, 2026 03:14
…ailures

Restrict extracted audio cover bytes to JPEG/PNG via magic-byte sniffing
instead of trusting the declared MP4 imageformat, so a GIF (or missing
format) is no longer mislabeled and persisted as image/jpeg.
@VoidHandler VoidHandler changed the title fix(backend): correct M4A embedded cover extraction fix(backend): correct M4A embedded cover extraction and validation Jul 8, 2026
@VoidHandler VoidHandler marked this pull request as ready for review July 8, 2026 05:17
Comment on lines +328 to +330
try:
cover = extract_embedded_cover(audio_full_path)
except Exception as exc:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Cover Errors Still Drop

When extract_embedded_cover raises after the tag scan reported an embedded cover, this catch returns None, the same value used for a file with no cover. The upload and scan paths then set has_embedded_cover=False, so a track with an unreadable or unexpectedly failing embedded cover is still saved successfully with the cover removed from metadata. That keeps the extraction-failure case indistinguishable from the no-cover case for callers.

Fix in Claude Code

@gantoine gantoine self-requested a review July 9, 2026 03:25
@gantoine gantoine merged commit bbb5c45 into rommapp:master Jul 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants