Skip to content

Phone audio: next song starts with the screen locked on Android, plus lock-screen controls - #76

Closed
dev8edss wants to merge 2 commits into
ShowPilotFPP:mainfrom
dev8edss:lockscreen-audio
Closed

dev8edss wants to merge 2 commits into
ShowPilotFPP:mainfrom
dev8edss:lockscreen-audio

Conversation

@dev8edss

Copy link
Copy Markdown

Two changes to the Listen on Phone player (public/rf-compat.js), one commit each.

  • Bug fix: On Android, the next song now starts while the phone's screen is off or locked. Before, it didn't start until the screen was turned back on.
  • Feature update: Listen on Phone now shows a media notification and lock-screen controls with the song's title, artist, cover and the show name, a progress bar, and Play and Pause.

Why the next song didn't start

Chrome on Android slows or pauses the code of a page you can't see once the tab stops playing sound, and the silent gap between songs counts as not playing. The code that starts the next song (the 1 s poll, the live song-change messages and their timers) then doesn't run until the screen comes back on.

The player already plays a constant -80 dBFS DC level on Android, to keep the speaker stream open between songs. That level is below what Chrome counts as sound (about -72 dBFS), so it doesn't keep the page running.

What changed

Keep awake (first commit)

  • While the player is open and not paused, the existing keep-alive ConstantSourceNode is raised to -60 dBFS. That's still a steady DC level that no speaker can reproduce, but it's enough for Chrome to keep the page running.
  • It drops back to -80 dBFS on Pause and 10 minutes after the show stops, so a phone left on the page can sleep.
  • It's on by default on Android only. ?keepawake=0 turns it off and ?keepawake=1 turns it on elsewhere.
  • Small fix along the way: a second startup() on the same audio context now stops the earlier keep-alive source. Before, it added a second one.

Media Session (second commit)

  • Browsers only show a media notification and lock-screen controls for a playing <audio>/<video> element, and the player's sound comes from Web Audio, which doesn't count.
  • While listening, a looping <audio> element of pure silence (a 10 s, 8 kHz WAV made in the page) plays alongside the music, and navigator.mediaSession gets the song details and Play/Pause. Seek and skip are turned off because it's a live show.
  • The silent element carries no music, so sync is unchanged. It follows the keep-awake state, and the notification is cleared when the player closes.
  • Pause from the lock screen also works in the gap between songs. The Pause button's own check would read that gap as "not playing" and start playback instead, so this sets the paused state directly.
  • It's on by default wherever the browser supports Media Session, except iPhone and iPad (not tested there yet). It does nothing inside the ShowPilot app. ?mediasession=0 turns it off and ?mediasession=1 turns it on anywhere.

The rf-compat.js cache-buster goes to v=155, one above the highest used on main (154) and beta (152).

Testing

  • node --check passes on both changed files.
  • The keep-awake fix has been running on a live show server: on Android Chrome, the next song now starts with the screen locked.
  • The keep-awake and Media Session helpers were run on their own against stand-ins for the browser (Web Audio, <audio>, navigator.mediaSession), and all checks passed. They covered:
    • the levels for listening, Pause and after the show stops
    • the silent WAV header
    • the handlers, including Pause between songs
    • the song details and progress bar
    • which devices it's on for by default, and the switches
  • Not yet tested on a real phone: Media Session (Android Chrome, Samsung Internet), and any iPhone behaviour with ?mediasession=1.

Main only (audio).

🤖 Generated with Claude Code

dev8edss and others added 2 commits November 14, 2026 21:47
On Android, Chrome slows or pauses the code of a page you can't see once
the tab stops playing sound, and the silent gap between songs counts as
not playing. The code that starts the next song then didn't run until the
screen was turned back on.

The player already plays a constant -80 dBFS DC level on Android to keep
the speaker stream open, but that is below the level Chrome counts as
sound (about -72 dBFS). While the player is open and not paused, the same
level is now raised to -60 dBFS: still a steady DC level no speaker can
reproduce, but enough for Chrome to keep the page running. It drops back
to -80 dBFS on Pause and 10 minutes after the show stops, so a phone left
on the page can sleep. ?keepawake=0 turns it off; ?keepawake=1 turns it
on off Android.

Also: a second startup() on the same audio context now stops the earlier
keep-alive source instead of adding another one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Browsers only show a media notification and lock-screen controls for a
playing <audio>/<video> element, and the player's sound comes from Web
Audio, which doesn't count. While listening, a looping <audio> element of
pure silence (a 10 s, 8 kHz WAV made in the page) now plays alongside the
music, and navigator.mediaSession carries the song's title, artist and
cover, the show name, a progress bar that follows the song, and Play and
Pause (seek and skip are off for a live show). The silent element carries
no music, so sync is unchanged. It follows the keep-awake state: playing
while listening, paused on Pause, 10 minutes after the show stops and when
the player closes.

On by default where the browser has Media Session, except iPhone and iPad
(not tested there yet); off inside the ShowPilot app. ?mediasession=0
turns it off; ?mediasession=1 turns it on anywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ShowPilotFPP pushed a commit that referenced this pull request Nov 14, 2026
… plus lock-screen controls

- Bug fix: On Android, the next song now starts while the phone's screen is off or locked. Before, it waited until the screen was turned back on.
- Feature update: Listen on Phone now shows a media notification and lock-screen controls with the song's title, artist, cover and the show name, a progress bar, and Play and Pause. (Not on iPhone/iPad yet.)

Main only (audio).

Source: #76

Co-authored-by: dev8edss <77666361+dev8edss@users.noreply.github.com>

---
_Generated by [Claude Code](https://claude.ai/code/session_01PJcoKLr2bhdUTsNw524TXK)_
@github-actions

Copy link
Copy Markdown

Shipped in v0.33.284-master.4 (via #77). Thank you for the contribution!

@github-actions github-actions Bot closed this Nov 14, 2026

Copy link
Copy Markdown
Owner

Thanks @dev8edss, this is a great contribution. It's shipped as v0.33.284-master.4 on the Master channel, with you credited as co-author on the commit and in the changelog.

I reviewed it before shipping. It applied cleanly on current main, everything it relies on in the player is there, the cache-buster number was correct, and the in-app player is left alone. The explanation of why Chrome was stalling between songs (the -80 dBFS level sitting under Chrome's "is this tab playing" threshold) was spot on, and raising the existing keep-alive source instead of adding a new one is a nice, small fix. Catching the stacked keep-alive source on a second startup() was a good find too.

One thing to keep an eye on: as you noted, the lock-screen controls haven't been tried on a real phone yet. If you get a chance to test them on Android Chrome or Samsung Internet, especially over Bluetooth or in a car, please report back.

Closing this since it's shipped. Thanks again!


Generated by Claude Code

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