Encore for YouTube Music: a tiny (4 MB) Windows app to listen together. Listen along with friends in sync, Discord status with a Listen along button, mini player.
翻译准备中
正在加载完整 README。
查看完整 README ↗Independent open-source project, not affiliated with or endorsed by Google, YouTube or Discord. YouTube Music is a trademark of Google LLC. Encore shows the official music.youtube.com website; it doesn't download music or block ads.
Written in Go with Wails v3 on Windows' built-in WebView2 (Edge) runtime: the installer is about 4 MB and the installed app about 13 MB, where Chrome-based apps are about 100 MB.
0–100 volume that remembers its level across launches; scroll over it to change it (Shift: steps of 5).Download the installer from the download page and run it. It installs for your Windows account only (no administrator rights) and replaces earlier "YouTube Music" versions of this app, keeping your settings and sign-in.
The installer isn't code-signed yet (free signing for open-source projects has been requested), so Windows may say "Windows protected your PC": select More info → Run anyway. Releases are built by GitHub Actions from this repository; see the code signing policy and privacy details.
go run .
Needs go-winres (go install github.com/tc-hib/go-winres@latest) and NSIS (winget install NSIS.NSIS).
.\build.ps1 -Version 0.2.0
This runs the tests, then writes dist\Encore.exe, dist\Encore-Setup-0.2.0.exe and dist\latest.yml. The installer is per-user, installs to %LOCALAPPDATA%\Programs\Encore and replaces an earlier install named "YouTube Music" (Go 0.2.x or Electron 0.1.x), whose settings in %USERPROFILE%\.youtube-music carry over. Pushing a v* tag builds and publishes a release from GitHub Actions.
| Path | Contents |
|---|---|
%USERPROFILE%\.youtube-music\settings.json | App settings (shared with the Electron releases) |
%USERPROFILE%\.youtube-music\webview2\ | YouTube sign-in and site data |
%USERPROFILE%\.youtube-music\app.log | Log for troubleshooting (capped at 1 MB; the previous one is kept as app.log.1) |
main.go, windowstate.go | Windows, layout, window position |
messages.go, state.go, playback.go | Page messages, settings state, playback hub, tray and taskbar controls |
presence.go, internal/discord | Discord Rich Presence (local IPC, no secret) |
listenalong.go, internal/listen | Listen along (encrypted relay protocol) |
internal/taskbar | Taskbar thumbnail buttons |
internal/audiosession | Name and remembered volume in the Windows volume mixer |
frontend/player.js | Script injected into music.youtube.com |
frontend/shell.html, frontend/settings.html, frontend/mini.html | Title bar, settings and mini player pages |
site/ | Download page, code signing policy and the listen-along join page, published with GitHub Pages |
The title bar is its own window. The YouTube Music and settings webviews are attached below it as Win32 child windows, so the site's own layout is never modified. Window moving and edge resizing are handled by the title-bar page itself (Wails' own drag/resize script only loads into pages served by its asset server, and these pages are built from strings): it asks the app to start the native move or resize. While the window is not maximised a 6 px frame of that page stays visible around the YouTube view, which is what makes the window resizable from its sides and bottom.
The app stores the player engine level (#movie_player.getVolume(), what you actually hear) and applies it with #movie_player.setVolume, which exists in both of YouTube Music's current player UIs. Before playback starts it seeds YouTube's own PREF cookie (volume=N, on the old slider curve) and reloads once, so the player starts at the saved level from its first frame. If YouTube changes the level on its own it is put back; a change you make in the page (slider, keyboard) is followed and saved. The app never mutes, pauses or plays media and never writes the <video> element's volume.
In the Windows volume mixer the sound appears as Encore. It is played by a WebView2 helper process (msedgewebview2.exe), which Windows would otherwise list as "Microsoft Edge WebView2" and whose volume it remembers per WebView2 install: shared with other WebView2 apps and forgotten when the runtime updates or the helper restarts. internal/audiosession names the app's sessions and keeps the level set for Encore in the mixer (mixerVolume in settings.json), restoring it whenever a new session starts.
go test ./...
Covers settings migration, the volume curve, the Discord IPC protocol (against a fake Discord) and update throttling, update verification, listen-along codes, encryption and sync rules, taskbar buttons, and invariants of the injected script (never mutes or forces playback on its own; reloads only once at startup).
Tests against the real services are opt-in:
go test -tags live -run Live ./internal/listen/
For a live check, start the app with a loopback debugging port, play something, and run the end-to-end script (requires Node.js):
$env:YTM_DEBUG_PORT = 9233; go run .
node scripts\live-test.mjs
It verifies the starting level, title bar → page, a YouTube-initiated change being reverted, an in-page change being saved, and a track change, then restores the original level.
While your Discord status is on, Encore keeps a session running so friends can click Listen along on your status (turn this off under Settings → Discord → “Listen along” button). You can also open Settings → Listen along → Start hosting and share the code or link; friends with this app paste it under Join a friend or open the link. Their player then follows yours: song, position, pauses, seeks and skips. A guest can leave at any time; when the host stops, guests are told the session ended.
Sync messages go through the public ntfy.sh relay on a random topic. Every message is AES-256-GCM encrypted with a key that only exists in the code, so the relay cannot read what you play, and messages not sealed with the room's key are ignored. Anyone you give the code to can listen until you stop hosting. The host publishes only real changes (about one message per song) to stay well within ntfy.sh's limits for anonymous use (250 messages a day per IP). The always-on session for the Discord button publishes only while someone listens: a guest sends an encrypted check-in when it joins and every 10 minutes, sealed so it can never be mistaken for playback, and the host answers with its current state and keeps publishing for 25 minutes after the last check-in. Quitting announces the end of the session only if someone was listening, with a 2-second limit so quitting is never held up; if the relay ever rate-limits, listeners catch up a minute later. Join links use the ytm-desktop:// link type, which the installer registers.
Select the Discord icon in the title bar and enable Rich Presence. No Discord application ID or client secret needs to be entered; the app talks only to the Discord desktop client running on the same PC. The status shows the song with its artwork, an Encore badge, and Listen along and Get Encore buttons (Discord shows buttons to other people, not to you).
Encore is free software under the GNU General Public License v3.0: you may use, share and change it, and anything you distribute based on it must be shared under the same license with its source code. Copyright © lilcham1.