diff --git a/apps/desktop/electron/link-title-window.cjs b/apps/desktop/electron/link-title-window.cjs
new file mode 100644
index 00000000000..80b3af3976e
--- /dev/null
+++ b/apps/desktop/electron/link-title-window.cjs
@@ -0,0 +1,42 @@
+'use strict'
+
+// Hidden BrowserWindow used by tier-2 link-title resolution: when curl can't
+// read a page
(bot walls, JS-rendered pages), we briefly load the URL
+// in an offscreen window and read its title. That window loads arbitrary
+// user-linked pages — including YouTube/`watch` URLs that autoplay — so it must
+// never be allowed to emit sound.
+
+function linkTitleWindowOptions(partitionSession) {
+ return {
+ show: false,
+ width: 1280,
+ height: 800,
+ webPreferences: {
+ backgroundThrottling: false,
+ contextIsolation: true,
+ javascript: true,
+ nodeIntegration: false,
+ sandbox: true,
+ session: partitionSession,
+ webSecurity: true
+ }
+ }
+}
+
+// Create the offscreen title-fetch window and immediately mute it. Without the
+// mute, autoplaying media on the loaded page (e.g. a YouTube link) leaks ~2s of
+// audio every time a session containing such links is re-rendered. See #49505.
+function createLinkTitleWindow(BrowserWindow, partitionSession) {
+ const window = new BrowserWindow(linkTitleWindowOptions(partitionSession))
+
+ try {
+ window.webContents.setAudioMuted(true)
+ } catch {
+ // webContents may be unavailable in degraded/headless environments; muting
+ // is best-effort and the window is destroyed within a few seconds anyway.
+ }
+
+ return window
+}
+
+module.exports = { createLinkTitleWindow, linkTitleWindowOptions }
diff --git a/apps/desktop/electron/main.cjs b/apps/desktop/electron/main.cjs
index 0a4f8eec8ad..b4ba88a243c 100644
--- a/apps/desktop/electron/main.cjs
+++ b/apps/desktop/electron/main.cjs
@@ -34,6 +34,7 @@ const {
SESSION_WINDOW_MIN_WIDTH
} = require('./session-windows.cjs')
const { canImportHermesCli, verifyHermesCli } = require('./backend-probes.cjs')
+const { createLinkTitleWindow } = require('./link-title-window.cjs')
const { probeGatewayWebSocket } = require('./gateway-ws-probe.cjs')
const { adoptServedDashboardToken } = require('./dashboard-token.cjs')
const { waitForDashboardPort } = require('./backend-ready.cjs')
@@ -2980,20 +2981,7 @@ function runRenderTitleJob(rawUrl) {
}
try {
- window = new BrowserWindow({
- show: false,
- width: 1280,
- height: 800,
- webPreferences: {
- backgroundThrottling: false,
- contextIsolation: true,
- javascript: true,
- nodeIntegration: false,
- sandbox: true,
- session: partitionSession,
- webSecurity: true
- }
- })
+ window = createLinkTitleWindow(BrowserWindow, partitionSession)
} catch {
return finish('')
}