DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

WhatCannotBeSaid /

WhatCannotBeSaid/dsh-blackhole-radio-lab

Verified

A 3-D black-hole stage for internet radio — DSH plugin with 24k real stations, wormhole transitions and live playback.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@0dbc6c7f
黑洞电台:拖动环绕黑洞、按住左键穿过虫洞进入星团、悬停显示电台卡片

黑洞电台 · Black Hole Radio

一块给网络电台用的 3D 黑洞舞台:两万多台真实电台绕着一颗可以环绕、可以播放的黑洞运行。

English · MIT 许可 · 第三方声明 · v1.0.0


这是什么

DSH(DeepSeek Harness)的插件。装上之后左栏底部多一张电台卡片,点卡片上的黑洞图标进入全屏舞台:

  • 中央是事件视界、光子环与吸积盘,外围是三层视差星场;
  • 2.4 万台真实网络电台嵌在吸积盘里,远看是一条亮带,靠近才认得出单个电台;
  • 按住不放会穿过一段虫洞落进星团,星团里每台电台是三维体积中的一个星点;
  • 点一下星点就播放,悬停出卡片,曲目信息直接来自电台流里的 ICY 元数据。

页面没有常驻搜索栏、分类侧栏或读数面板。搜索和分类只在你主动去点的时候出现。

功能

舞台

  • 手写轨道相机:左键拖动环绕、滚轮缩放、阻尼收敛,镜头焦点锁在黑洞核心。
  • 原生 Three.js,单个 Points + 自定义着色器承载全部电台,不为每台电台建 Mesh。
  • 远中近三级 LOD:远看连续亮带与密度起伏,中距分辨盘面亮结,近距才显示单个电台与附近台名(台名画在 2D canvas 上,不进 DOM)。
  • 星团是真实三维体积:径向密度 u^1.9、三条种子纤维、垂直压扁 0.82,每台电台 5 个微 sprite 在目标处散成 2–5 px 的星结。
  • 黑洞与星团之间是虫洞转场:环形进度与阴影扩张共用同一个时钟,按下第一帧就开始动;松手时画面与环一起阻尼回抽;回弹途中再按一次从当前进度续接,不跳变。

电台

  • 2.4 万台以内置快照启动(构建时已逐条探活),缺快照时回落实时抓取。
  • 搜索覆盖台名、国家地区、语言、分类;分类面板分 13 个流派。
  • 播放 / 暂停、上一台 / 随机下一台、音量;坏流自动进黑名单,不再浪费时间重连。
  • 悬停卡片:点击播放、右键或星标收藏、显示流派与 LIVE 徽标。
  • 正在播放的曲目取自流内 icy-metaint 元数据块;点歌名可在 Spotify / 网易云音乐 / QQ 音乐 / Apple Music / YouTube 中搜索该曲(平台可右键切换)。
  • 收藏的电台与喜欢的歌曲持久保存在本机,不联网同步。
  • 中文 / English 跟随应用语言。

安装

先决条件:Node.js ≥ 20,DSH(已验证 0.2.1-rc.2)。

# 从 npm(发布版)
dsh plugin --profile <profile> add dsh-blackhole-radio-lab

# 从本地源码
git clone https://github.com/WhatCannotBeSaid/dsh-blackhole-radio-lab.git
dsh plugin --profile <profile> add "C:/path/to/dsh-blackhole-radio-lab"

装完必须重启 DSH。桌面端进程不会自己发现新 bundle,重建 chunk 之后同理——revision 是启动时算的。

卸载:

dsh plugin --profile <profile> remove dsh-blackhole-radio-lab

上手

操作 结果
左键拖动 绕黑洞旋转
滚轮 以黑洞为中心缩放
点击黑洞中心 / 回车 打开搜索
指针在中心停留 600 ms 展开分类面板(触屏长按 560 ms)
黑洞上按住左键 ≈2.3 s 穿过虫洞进入星团;松手 0.22 s 回抽
星团中按住右键 ≈1.2 s 倒放回黑洞;短按只撤销不回弹
转场途中再按同一键 从当前进度续接,不重头再来
星点上悬停 / 点击 / 右键 悬停卡片 / 播放暂停 / 收藏
Esc 关闭浮层或退回黑洞

底部卡片独占:站名、曲目行、收藏星标、喜欢心标、播放 / 上一 / 下一 / 音量。

配置

cordis.patch.yml 的条目上可挂 config:

- insert:
    - id: blackhole-radio-lab
      name: 'dsh-blackhole-radio-lab'
      config:
        antialias: true
        pixelRatioCap: 2
        reducedMotion: false
        wormhole: true
        showHints: true
        stationCount: 2400
        seed: 20261022
        featuredCount: 18
        catalogAutoRefresh: true
        catalogRefreshDays: 7
        catalogTarget: 30000
        catalogFetch: 50000
        catalogConcurrency: 48
        catalogTimeoutMs: 2800
键 默认 范围 作用
antialias true 布尔 WebGL 抗锯齿
pixelRatioCap 2 1–4 渲染倍率上限
reducedMotion false 布尔 关闭动画,只渲染单帧;转场也更快
wormhole true 布尔 虫洞转场;false 恢复瞬时切换
showHints true 布尔 显示操作提示
stationCount 2400 200–20000 模拟数据台数(sourceMode=mock 时生效)
seed 20261022 0–4294967295 数据与空间分布随机种子
featuredCount 18 4–40 内环精选台数
catalogAutoRefresh true 布尔 是否每周在后台刷新目录快照
catalogRefreshDays 7 1–90 缓存超过多少天算过期
catalogTarget 30000 1000–60000 用户侧快照保留台数
catalogFetch 50000 1000–60000 探测前抓取的候选数,须 ≥ catalogTarget
catalogConcurrency 48 1–64 探测并发
catalogTimeoutMs 2800 500–15000 单条探测超时

未给的键回落到 index.js 里的 DEFAULTS。调试时也可以给页面加 ?bhrlStations=5000 临时覆盖台数,加 ?bhrlWormhole=0 关掉虫洞做 A/B。

数据来源与隐私

  • 电台目录来自 Radio Browser 的公开 API。发布包里的快照由 tools/build-catalog.mjs 抓取、逐条探活、按国家与流派保底筛洗而成,构建时间与台数写在 THIRD-PARTY-NOTICES.md。
  • 用户侧每周在 DSH 运行期间后台重建一次快照,写入 $DSH_HOME/cache/blackhole-radio-lab/;DSH 没开就不跑,失败只记日志、六小时后再试。
  • 播放时浏览器直接连电台的流地址,曲目信息来自该流的 ICY 元数据块(Host 只取一个块即断开)。这些连接会把你的 IP 暴露给对应电台,作者服务器不参与、也看不到。
  • 收藏、喜欢的歌曲、坏流黑名单只写本机 $DSH_HOME/blackhole-radio-lab/library.json,不上传任何地方。
  • 插件不加载远端脚本,不引 CDN,Three.js 是包内私有依赖。

架构

插件分两半:Host 半(index.js + src/host/)只做配置、静态路由、目录刷新与曲目探测,零运行时依赖;浏览器半被打成两个按需下载的 chunk。

路径 作用
index.js Host 入口:配置校验(标准 schema)、路由、卸载清理
src/host/library.js 收藏与黑名单的本机记录(原子写)
src/host/catalog-builder.js 目录构建:抓取、探活、保底筛洗(CLI 与 Host 共用)
src/host/catalog-refresh.js 每周后台刷新调度与回落规则
src/host/now-playing.js ICY 元数据探测(只读一个元数据块)
client.js 浏览器入口:React 组件、样式、槽位注册、懒加载、卸载清理
src/stage.js 渲染入口:renderer / 场景 / 相机、rAF、指针状态机、虫洞转场
src/scene/ 黑体、光子环、吸积盘、星场、轨道相机、共用 GLSL
src/nodes/ 电台微结构层、星团层、2D canvas 标签层
src/cluster/ 星团布局与离线投影测量
client.stage.js / client.radio.js 构建产物,不要手改
cordis.patch.yml bundle 补丁层,一行 loader 条目

两个 chunk 只在需要时才下载:

window.__ModuleLoader__.load({
  id: 'dsh-blackhole-radio-lab',
  chunk: 'client.stage.js',
  factory(require) { /* three 已内联,没有裸模块请求 */ },
});

chunk 的 URL 取自入口包的 revision,所以构建脚本会在产物真的变化时顶一下 client.js 的 mtime——不顶这一下,浏览器会拿 immutable 缓存里的旧 chunk。

本地开发

npm install      # three + esbuild
npm run build    # 重建 client.stage.js 与 client.radio.js
npm test         # 转场与产物的契约测试
  • 只改 src/,然后 npm run build。 两个 client.*.js 是产物。
  • 不要在 client.js 里 import 'three':浏览器侧没有 three 的基座模块,解析会直接失败。
  • client.js 本身不是构建产物,直接改;但改完必须求值一次真实的模块加载路径(npm test 会做:在 vm 里提供 window.__ModuleLoader__.load,断言 factory 返回 apply / inject)。
  • 重建目录快照:npm run build:catalog(CATALOG_TARGET、CATALOG_FETCH、CATALOG_CHECK_CONCURRENCY 等环境变量控制,探测两万台第三方流要几分钟到几十分钟,所以不放进 npm run build)。

测试覆盖到哪

npm test 是纯 Node 的契约测试,不需要浏览器:39 个转场用例(含按下即动、松手回抽、回弹复按不跳变、一次长按只跨越一次)、89 组真实源码取色与投影映射、真实 SVG 环的时序、以及两个产物 chunk 的 loader 注册冒烟。

它不覆盖 GPU 与浏览器观感:着色器编译、实际帧率、HDR 色调映射的观感只能靠人眼在真机上看。

已知限制

  • 无账号、无云同步、无歌单:收藏与喜欢只在本机。
  • 部分电台会 404、断流或只在特定地区可用;坏流进黑名单后不再重试。
  • 实时抓取路径每次最多取 5,000 台(分页 + 时间预算),内置快照远大于此;快照过期 30 天或台数骤减时会回落实时抓取。
  • reducedMotion 下转场时间更短,不是完全无动画。
  • 缩放到最近处时,密集区域的台名仍会互相让位,极端密度下会有标签不显示。

贡献

Issue 与 PR 都欢迎。提交前请跑 npm run build && npm test,并且不要手改 client.*.js 或 data/catalog*.json.gz。

许可

代码以 MIT 发布。第三方组件与数据的来源、许可与义务见 THIRD-PARTY-NOTICES.md。

—/ 5

No ratings yet

Verified DSH bundle

Commit 0dbc6c7fa7dd

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout