Skip to content

fix: flatpak mpv can no longer hang or outlive TTS_ka - #23

Merged
DavidTbilisi merged 1 commit into
masterfrom
fix/flatpak-mpv-robustness
Oct 23, 2026
Merged

DavidTbilisi merged 1 commit into
masterfrom
fix/flatpak-mpv-robustness

Conversation

@DavidTbilisi

@DavidTbilisi DavidTbilisi commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

An MCP speak left a flatpak mpv running for 8 hours, and only SIGKILL stopped it. The investigation found five problems, all fixed here.

  1. Stopping mpv didn't reach a flatpak mpv. The PID Popen holds is bwrap, not mpv, and SIGKILL to it leaves mpv-bin running. mpv is now started with start_new_session=True and stopped with the new mpv_ipc.kill_process_group. That covers MpvIpc.close() and StreamingAudioPlayer.stop().
  2. No timeout when mpv never starts playing. MpvIpc.wait_done now raises if no appended entry starts within START_TIMEOUT (10 s), instead of waiting forever.
  3. Headless mpv loaded all user and system scripts. Flatpak mpv's bundled mpris plugin blocks forever without DBUS_SESSION_BUS_ADDRESS, for example when an MCP server is started by stdio_client without env=. mpv then answers IPC but never plays and ignores SIGTERM and quit. Headless mpv (both the IPC and the stdin-playlist launch) now gets --load-scripts=no. Windowed mpv keeps the user's scripts.
  4. MpvIpc.start() could leak mpv. If mpv connected but didn't answer observe_property, start() raised without closing it. It now closes mpv first.
  5. False success. Chunk errors are now recorded in StreamingAudioPlayer.playback_error. A blocking speak raises ToolError with the reason, instead of answering "played in 0.7s" after mpv reported "audio output initialization failed".

Test plan

  • 11 new test cases plus one extended existing test (the stdin-playlist mpv now gets its own session). On the old code, 10 of the new ones and the extended one fail. The other new one checks that windowed mpv still loads scripts, which this PR leaves unchanged. One test kills a real sh wrapper's process group and checks that its child dies too.
  • Full pytest suite passes; no new mypy or flake8 findings
  • Manual: MCP speak (blocking) through a plain flatpak mpv, started by stdio_client with its default minimal env:
    • As shipped: fails in 2.4 s with "playback failed: audio output initialization failed", and no mpv is left. Before: hung for over 120 s and left mpv running.
    • With --load-scripts=no stripped out to force the mpris hang: fails after the 10 s start timeout with "mpv did not start playing within 10s", and the stuck mpv is killed through its process group.

🤖 Generated with Claude Code

A flatpak mpv broke playback cleanup in three ways:

- The PID Popen holds is bwrap, not mpv. Killing it, as close() and stop()
  did, left mpv-bin running. mpv is now started with start_new_session=True
  and stopped with the new mpv_ipc.kill_process_group.
- Its bundled mpris plugin blocks forever when DBUS_SESSION_BUS_ADDRESS is
  unset (e.g. an MCP server launched by stdio_client without env=). mpv then
  answers IPC but never plays and ignores SIGTERM and quit. Headless mpv
  (IPC and stdin playlist) now gets --load-scripts=no, and MpvIpc.wait_done
  raises if no appended entry starts within START_TIMEOUT instead of waiting
  forever.
- MpvIpc.start() left mpv running when it connected but observe_property got
  no answer. It now closes mpv before raising.

Chunk errors are recorded in StreamingAudioPlayer.playback_error, and a
blocking MCP `speak` raises ToolError with that reason instead of answering
"played in 0.7s" when mpv said "audio output initialization failed".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DavidTbilisi
DavidTbilisi merged commit 79b74ad into master Oct 23, 2026
6 checks passed
@DavidTbilisi
DavidTbilisi deleted the fix/flatpak-mpv-robustness branch October 23, 2026 13:22
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.

1 participant