# localplayer **Repository Path**: siwpan/localplayer ## Basic Information - **Project Name**: localplayer - **Description**: 网页版播放器 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-14 - **Last Updated**: 2026-10-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README > 📦 **已归档(Archived — 仅作参考)** > 本仓库已收入归档仓 **players-unified**(代码与完整 git 历史一并迁入,原仓冻结不再开发)。 > 历史分支见归档仓的 `archive/localplayer` 分支;活跃维护请前往 **players-unified**。 > _This repo is archived into players-unified; development continues there. Do not commit here._ # 轻量播放器 · 本地媒体(Chrome / Edge 通用扩展) > 仓库: | 许可:MIT(见 [LICENSE](LICENSE)) 一个以浏览器扩展(Manifest V3)形式分发的轻量本地媒体播放器, 支持视频 / 音频混排播放列表、自动下一曲、音频 / 视频模式自动切换。 Chrome 与 Edge 使用同一套 MV3 规范,本扩展在两者上通用,无需改动。 ## 目录结构 ``` localplayer/ ├── manifest.json # MV3 扩展清单(popup + options_page + side_panel + background + offscreen + web_accessible_resources) ├── popup.html # 弹窗页面结构 ├── popup.css # 弹窗样式 ├── app-layout.css # 各播放器界面(popup / 侧栏 / 全页)共用的布局样式 ├── popup.js # 播放逻辑(混合加载:远端优先 + 本地打包兜底) ├── player.html # 独立全页播放器(复用 popup 播放逻辑,对应「独立插件应用」) ├── lib/hls.min.js # 本地打包的 hls.js(Apache-2.0),用于播放 .m3u8 ├── plugins/ # 最小自定义插件接口(插件式媒体源) │ ├── plugin-api.js # LocalPlayer.plugins 注册表 + collectMedia(fallback 链) │ └── sample-source.js # 示例插件模板(默认不加载,按注释启用) ├── options.html # 选项页结构 ├── options.css # 选项页样式 ├── options.js # 选项页逻辑(读写后端地址到 chrome.storage.sync) ├── background.js # MV3 service worker(拉取后端 /api/list 清单 + 信令中转 + offscreen 管理) ├── offscreen.html # 后台音频 / WebRTC 主运行时文档 ├── offscreen.js # 后台音频续播 + 网页投送(WebRTC 串流当前媒体) ├── server.py # 可选 Flask 后端(/api/list + /media/ + /ws 信令 + /remote 观看页) ├── gen_media_manifest.py # 扫描 media/ 生成本地媒体清单 media/manifest.json ├── gen_media_manifest.bat # 同上(Windows 双击运行) ├── media/ # 随扩展打包的媒体(含 README 说明与 manifest.json 清单) ├── requirements.txt # 可选 Flask 后端依赖 ├── CHANGELOG.md # 版本变更记录 ├── docs/ # 文档(分支模型 branching.md、发版说明 RELEASE-*.md 等) ├── LICENSE # MIT └── README.md ``` > `deepseek_html_20260914_584fc0.html` 为拆分前的单文件源,保留作参考。 ## 近期版本变更(v1.3.x 一览) v1.3.x 完成了「常驻界面 + 网页投送」两大能力升级(完整记录见 [CHANGELOG.md](CHANGELOG.md)): - **v1.3.0 常驻界面 + 网页投送**:新增独立全页播放器(`player.html`),修复「切标签页 popup 自行回退」;新增 WebRTC「网页投送」,可将当前播放投送到外部网页观看。 - **v1.3.1 投送健壮性**:WebRTC 信令「直连优先 + background 中转兜底」;开启投送前做后端可达性校验,不可达时按钮置灰并提示先启动 `server.py`;版本号补登为 1.3.1。 - **v1.3.2 投送可用性 + 静默降级**:接收端 `/remote` 页显示曲目信息与连接状态,发送端显示「投送中 · N 个接收端」;媒体源在后端未启动时静默回落本地源,不再刷 `console.warn`。 ## 加载方式 1. 打开 `chrome://extensions`(Edge 为 `edge://extensions`)。 2. 右上角开启「开发者模式」。 3. 点击「加载已解压的扩展程序」,选择本目录 `localplayer`。 4. 点击工具栏图标,弹出播放器。 ## 选项页(配置后端地址) 右键扩展图标 → 「选项」,或在 `chrome://extensions` 详情页点击「扩展选项」,打开设置页: - **后端地址 (Backend URL)**:填写你的 Flask 后端基址(默认 `http://127.0.0.1:5000`)。 `background.js` 每次拉清单时都会读取 `chrome.storage.sync.backendUrl`,保存后立即对新打开的 popup 生效。 - 留空或格式无效 → popup 回退到随扩展打包的本地媒体。 - 「测试连接」:直接探测当前输入框地址的 `/api/list`(与是否保存无关), 成功时显示返回的媒体数量,失败给出错误原因,便于保存前确认后端可达。 - 「恢复默认」一键重置为 `http://127.0.0.1:5000`。 ## 媒体来源(两种模式) `popup.js` 的 `loadMedia()` 决定媒体清单来源。两种模式可同时存在(见下文「混合模式」)。 ### 模式 A:随扩展打包 + `web_accessible_resources` 把媒体文件放进 `media/` 目录,并在 `manifest.json` 声明: ```json "web_accessible_resources": [{ "resources": ["media/*"], "matches": [""] }] ``` 扩展运行时**无法枚举自身包内目录**,所以本地媒体清单由 `gen_media_manifest.py`(或 `gen_media_manifest.bat`) 扫描 `media/` 生成 `media/manifest.json`,`popup.js` 读取该清单得到实际文件,路径形如 `chrome-extension://<扩展ID>/media/xxx.mp4`。**放入新文件后需重新运行生成脚本并刷新扩展**,popup 才会列出它们。 媒体随扩展分发,无需后端,完全离线可用。 ### 模式 B:走 background service worker 拉取后端清单 1. 用 `requirements.txt` 里的 Flask 起一个后端,提供 `/media/` 与 `/api/list`。 2. 新增 `background.js`(MV3 service worker)暴露 `chrome.runtime.onMessage` 监听,由它 `fetch` 后端清单后回传。 3. `popup.js` 通过 `chrome.runtime.sendMessage` 取清单,再逐条播放。 后端地址等可存于 `chrome.storage`。 ### 混合模式(A + B 已同时实现) 两者并不冲突,已默认开启: - `web_accessible_resources`(`manifest.json`)解决「扩展内打包文件如何被 popup 访问」; - background service worker(`background.js`)解决「如何异步从远端后端拿清单」。 **实现(`popup.js` 的 `loadMedia()`)**:popup 启动先 `chrome.runtime.sendMessage({action:'getMediaList'})` 向 `background.js` 取远端清单;`background.js` 用 `fetch` 调用后端 `/api/list`(地址来自 `chrome.storage.sync.backendUrl`,默认 `http://127.0.0.1:5000`,可覆盖)。若远端返回非空 → 用后端模式(B);若拉取失败 / 后端未起 → 回退到 `media/manifest.json` 列出的本地打包文件(A)。 两种来源互不干扰,最终统一进 `files` 数组。 **配套 Flask 后端**:`server.py` 提供 `GET /api/list`(返回 `{name,path,type}` 数组, `path` 为完整 URL)与 `GET /media/`。运行见文件头注释。 ## HLS(.m3u8)播放 `index.m3u8` 这类 HLS 播放列表,Chrome 原生 `