Visitar URL original
Linux AppImage ships no AAC decoder — all audio is silent (gstreamer1.0-libav missing from the release runner) · Issue #8615 · phase-rs/phase · GitHub
Skip to content

Linux AppImage ships no AAC decoder — all audio is silent (gstreamer1.0-libav missing from the release runner) #8615

Closed

Description

@alicewonderland-dev

Summary

The Linux AppImage plays no sound at all. bundleMediaFramework (added in #8348) bundles a GStreamer plugin set that contains no AAC decoder, and 29 of the app's 33 audio assets are AAC-in-MP4. Because every SFX file is AAC, the frontend latches audio off entirely, so the four .mp3 music tracks never play either — even though their decoder is bundled.

Only the AppImage is affected. The .deb declares gstreamer1.0-libav in bundle.linux.deb.depends and is fine.

Environment

  • Phase-Desktop-Linux-x86_64.appimage, shell-v1.0.12, app v0.75.0
  • Nobara / Fedora 44 (host has libgstlibav.so, but the AppImage cannot use it — see below)

Evidence

The app's own preflight already names the culprit exactly, on stderr at launch:

phase.rs: GStreamer plugins needed for audio are missing. Audio will be unavailable; the app still starts.
  libgstlibav.so — provides avdec_aac (the .m4a codec every bundled track uses) — Debian/Ubuntu package: gstreamer1.0-libav

followed by 14 × :

** (WebKitWebProcess): WARNING **: Error: 12, Your GStreamer installation is missing a plug-in.
no suitable plugins found:
Missing decoder: MPEG-4 AAC (audio/mpeg, mpegversion=(int)4, ...)

Confirmed against the extracted AppDir:

  • 105 bundled plugins in usr/lib/gstreamer-1.0 — gst-plugins-base + gst-plugins-good only
  • Scanning every bundled .so for an AAC decoder element (avdec_aac, faad, fdkaacdec): zero hits
  • qtdemux (libgstisomp4.so) and aacparse (libgstaudioparsers.so) are present — only the decoder is missing
  • client/public/audio/: 29 .m4a (AAC, verified with ffprobe) and 4 .mp3. Every SFX file is AAC.

Why all audio dies, not just AAC

libgstmpg123.so is bundled, so the four .mp3 music tracks are decodable. But preloadSfx() only loads SFX, all of which are AAC, so it returns "none". ensurePreload then treats that as a hard failure and latches audio off for the session:

audioManager.disable();
useAudioHealthStore.getState().setUnavailable("media-unavailable");

The volume control correctly shows the muted state. The behaviour is right given the input — the input is just wrong.

Root cause

.github/workflows/shell-release.yml:236 installs only:

libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

with --no-install-recommends. gstreamer1.0-libav is a Recommends of libwebkit2gtk-4.1-0, so it never lands on the runner — and linuxdeploy-plugin-gstreamer can only copy plugins that are installed at build time. The runner happens to have plugins-base and plugins-good, which is exactly the set that shipped.

The AppRun hook pins the search path to the bundle, so the host's own plugins cannot fill the gap:

export GST_PLUGIN_SYSTEM_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0"
export GST_PLUGIN_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0"

Dropping the host's libgstlibav.so into the bundle does not work either: the bundled GStreamer core is 1.24.2 and this host's is 1.28.6 — the version mismatch that caused #6744 in the first place.

Why CI didn't catch it

#8348 originally included a release smoke check that verified the shipped AppImage's plugin set actually registers avdec_aac and friends. It was removed before merge and is tracked in #8357. That check would have caught this exactly.

Suggested fix

  1. Install the plugin packages in the Linux job before tauri-action runs, so linuxdeploy has them to copy:
    gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-libav
    
    (these need to bypass --no-install-recommends, or be listed explicitly as above)
  2. Land Move the Linux release smoke probe into a no-secret job #8357's element-registration probe so a missing decoder fails the release rather than shipping silently.

Optionally, re-encoding the SFX to Vorbis or Opus would make the app's audio depend only on gst-plugins-base, which is always present — a belt to go with the braces.

Note

This does not affect playability, only sound. The AppImage also has an unrelated CPU regression from the same investigation — see #8614.


Diagnosed with Claude Code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions