Streambert源码导读:index.js主进程如何管理窗口、会话与生命周期
【免费下载链接】streambertA cross-platform Electron Desktop App to stream and download any Movie, TV Series or Anime in the World. Zero Ads and Tracking项目地址: https://gitcode.com/GitHub_Trending/st/streambert
Streambert 是一款跨平台的 Electron 桌面应用,可以在线播放并下载电影、剧集和动漫,全程零广告零追踪。本文带你逐段导读它的入口文件 index.js——这个约 500 行的主进程脚本负责窗口创建、双会话隔离、广告拦截、m3u8 流地址捕获、弹窗小窗播放器以及应用生命周期管理,是理解整个项目的最佳起点。
主进程性能调优:启动时的隐藏开关
Electron 应用最容易出现的毛病是内存越用越大。Streambert 在 index.js#L15-L31 开头就集中做了一组"性能手术":
- 限制 V8 堆内存:通过
--max-old-space-size=256把渲染进程堆上限压在 256MB,并开放--expose-gc允许手动触发垃圾回收; - 压缩进程数量:开启
NetworkServiceInProcess2,把网络栈并入浏览器进程,少养一个 utility 进程; - 限流渲染进程:
renderer-process-limit设为 3,配合 80MB 磁盘缓存上限,防止多页导航时内存持续膨胀; - 禁用无关特性:关闭硬件媒体键、媒体会话服务等,减少后台开销。
代码里还特意用_bench()函数(index.js#L33-L36)打印各阶段启动耗时,方便开发者观察"app ready → 窗口创建 → 渲染进程加载完成"每个环节的毫秒数。
单实例锁:应用生命周期的第一道关卡
在文件末尾(index.js#L490-L512)可以看到完整的生命周期骨架:
app.requestSingleInstanceLock()保证同一时刻只有一个实例。如果用户重复启动,第二次启动直接退出,而已有窗口会被恢复并聚焦;app.whenReady()后调用createWindow()创建主窗口;window-all-closed时退出应用(macOS 上activate事件会重新建窗);before-quit时调用discordRpc.shutdown(),优雅关闭 Discord 状态集成。
这是 Electron 应用的经典生命周期模式:锁实例 → 等 ready → 建窗口 → 关窗即退。
创建主窗口:BrowserWindow 与 preload 桥
createWindow()(index.js#L206-L313)是整个应用的核心。几个值得注意的细节:
- 跨平台标题栏:macOS 用
hiddenInset,Windows 用无边框hidden样式,配合渲染层自绘的标题栏组件 src/components/WindowTitlebar.jsx; - 安全配置:
contextIsolation: true+nodeIntegration: false,渲染进程拿不到 Node 能力,所有系统操作必须走 preload.js 里contextBridge暴露的白名单 API; - 加载构建产物:
mainWindow.loadFile("dist/index.html"),即 Vite 打包后的 React 界面(src/pages/HomePage.jsx 等页面组件); - TMDB 图片长效缓存:对
image.tmdb.org的图片强制注入 7 天cache-control头,首页的海报因此几乎不用重复下载。
双会话隔离:广告拦截与 m3u8 捕获的秘密
这是 index.js 最精彩的部分。应用把网络流量分成两个独立会话(session),在setupSession()(index.js#L109-L204)中配置:
| 会话分区 | 用途 | 拦截策略 |
|---|---|---|
persist:player | 播放器 webview | 拦截广告域名 +放行并上报 m3u8/vtt 流地址 |
persist:trailer | 预告片播放 | 仅拦截广告域名 |
具体手法有三招:
- 头部剥离:用
webRequest.onHeadersReceived删掉响应里的X-Frame-Options和Content-Security-Policy,这是让第三方流媒体站点能嵌进<webview>的关键; - 广告黑名单:约 50 条 BLOCKED_HOSTS 通配规则,命中即
cancel: true,并由 src/ipc/blockStats.js 累计拦截统计; - 流地址嗅探:
m3u8(HLS 播放列表)和vtt(字幕)请求不拦截,而是转发m3u8-found/subtitle-found事件给渲染进程——这就是 Streambert 能"找到下载链接"的底层机制。
会话配置是懒加载的:只在第一个 webview 挂载(did-attach-webview,index.js#L252-L275)或弹出小窗时初始化一次,避免不必要的启动开销。
关闭保护与内存回收:让下载和内存都不"泄漏"
两个针对实际痛点的细节设计:
关闭确认(index.js#L288-L307):点击关闭按钮时,主进程先查询 src/ipc/downloads.js 中状态为downloading的任务;若存在,阻止关闭并向渲染进程发送confirm-close事件,弹出确认框。用户确认后调用killAllDownloads()清理子进程再销毁窗口——下载进行到一半被误关的情况就此杜绝。
播放器停播清理(player-stopped,index.js#L332-L367):页面离开时,主进程按 ID 逐个静音并销毁跟踪中的播放器 WebContents,随后清空 player 会话的 HTTP 与 shader 缓存,最后对主进程和渲染进程各发一次gc()提示。三步组合拳保证了"看完一部片再换一部"不会让内存阶梯式上涨。
弹出式画中画:pipWindow 的一生
open-pip-window(index.js#L386-L461)负责那个可以拖到屏幕任意角落、始终置顶的 640×360 迷你播放器窗口:
- 复用
persist:player分区,因此广告拦截规则同样生效; - 加载 popout-preload.js 注入自定义标题栏,其最小化/最大化/关闭按钮通过
popout-window-*系列 IPC 通道与主进程通信; - 用
setWindowOpenHandler拒绝一切弹出子窗口,安全加固; - 关闭时向主窗口发
pip-window-closed事件,主窗口随即停掉重复的流。
单例管理很克制:再次调用open-pip-window时直接让已有窗口loadURL + focus,不会创建第二个小窗。
IPC 模块速查:重逻辑都住在 src/ipc/
index.js 本身刻意保持"薄",真正的业务逻辑拆在 src/ipc/ 下,注册代码集中在 index.js#L315-L330:
- src/ipc/storage.js:基于系统钥匙串的加密存储与定时备份;
- src/ipc/downloads.js:下载队列、子进程管理与进度推送;
- src/ipc/subtitles.js:字幕下载与语言识别;
- src/ipc/player.js:播放器视频注入与设备恢复;
- src/ipc/allmanga.js:动漫剧集解析;
- src/ipc/discordRpc.js:Discord 在线状态;
- src/ipc/blockStats.js:广告拦截统计。
小结
读完 index.js 可以归纳出 Streambert 主进程的三条设计主线:性能上用启动开关与内存回收守住资源,安全上用 contextIsolation + preload 白名单 + 弹窗全禁守住边界,体验上用双会话、m3u8 嗅探和关闭保护支撑起"零广告 + 可下载"的核心卖点。如果你想深入某项功能,从 preload.js 暴露的通道名入手,顺着src/ipc/里对应的模块读下去即可。
项目入口与构建配置详见 package.json,主进程入口声明在
"main": "index.js"。
【免费下载链接】streambertA cross-platform Electron Desktop App to stream and download any Movie, TV Series or Anime in the World. Zero Ads and Tracking项目地址: https://gitcode.com/GitHub_Trending/st/streambert
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考