用 Three.js 撸了一个 3D 地球 + 全球实时电台,性能有点炸,求优化建议 - V2EX
爱意满满的作品展示区。
xingwangchan

用 Three.js 撸了一个 3D 地球 + 全球实时电台,性能有点炸,求优化建议

  •  1
     
  •   xingwangchan 1 day ago 2117 views

    [点我直接玩] https://www.radiosphere.live/

    这玩意是干啥的?

    一个 3D 交互式地球,上面每一个绿点都是一个真实在线的网络广播电台( Shoutcast / Icecast )。
    你旋转/缩放地球,随便点一个点,就能听到那个地区的广播可能是音乐、新闻、甚至是半夜的脱口秀。

    技术栈

    • Three.js (r128) 地球主体、标注点、光晕效果
    • Web Audio API 音频流播放、音量控制、跨域处理
    • 自建数据层 爬取了全球约 8000+ 个公开电台,包含经纬度、流地址、国家等
    • 前端框架 Vue + Vite
    • 坐标转换 地理坐标 (lat, lon) → 三维空间向量

    目前遇到的坑(也是我想在 V2EX 求助的重点)

    1. 性能
      地球上的标记点目前是 8000+ 个独立的 PointsMaterial,帧率在低端设备上会掉到 30 以下。
      试过用 BufferGeometry 合并,但动态光晕(播放中的电台要单独高亮)就不好做了。
      求教:有没有在“大量静态点 + 少数动态高亮点”场景下的最佳实践?

    2. 音频流的 CORS & 混合内容
      很多电台流是 HTTP 的,我的网站是 HTTPS ,浏览器会 block 。
      目前用了一个公共 CORS 代理(https://cors-anywhere.herokuapp.com/),但不稳定而且慢。
      有没有更轻量的方案?或者自己搭一个简单的代理,成本大概多少?

    3. 数据更新
      电台经常失效(流地址 404 或者超时),我是半手工检测 + 脚本定期跑。
      想知道有没有比较稳定的全球公开电台 API ?不想一直维护死链。

    接下来想加的功能

    • 用户自定义导入电台(粘贴流地址,自动推算经纬度)
    • “随机漫游”模式:每 30 秒自动跳到另一个随机电台
    • 录音片段分享(录 15 秒存成 WebM 并生成分享链接)

    我需要你帮忙做的事

    • 戳一下网站,看看在你设备上卡不卡(手机 / 老笔记本尤其需要反馈)
    • 如果你知道 本地或小众地区的网络电台流地址,直接评论丢给我(国家 + 流地址),我批量加进去
    • 对上面那几个技术坑有思路的直接留言,跪谢

    最后说句心里话

    这个项目不是为了赚钱,纯粹想做点炫酷的东西。
    做出来之后自己每天都会随便点几个没听过的国家,感觉很奇妙。
    如果你也觉得有意思,欢迎转发给朋友;如果发现 bug 或者卡顿,直接喷,我改。

    https://www.radiosphere.live/

    (网站目前没有广告,也没有用户系统,打开即用)


    可选的“沙发”自问自答

    :为什么不用 Cesium ?
    :Cesium 太重了,Three.js 更可控,而且我想保持打包后不到 2MB (不含纹理)。

    :电台数据会不会涉及版权问题?
    :所有流地址都是电台自己公开的 Shoutcast 入口,我只是做了一个播放器外壳,类似浏览器。


    39 replies    2026-06-05 16:57:28 +08:00
    wktline
        1
    wktline  
       1 day ago
    AI 说:没法优化了-炸!
    burp2019
        2
    burp2019  
       1 day ago
    不用优化,让用户觉得炫的同时有点卡,凸显项目的难度和你的牛逼
    0754
        3
    0754  
       1 day ago   1
    好酷炫~~
    Tanf
        4
    Tanf  
       1 day ago   1
    不错不错
    tianjiyao
        5
    tianjiyao  
       23h 51m ago
    挺好玩,,只是为啥大陆没有亮的。。。闪烁的都是欧美的区域。。
    xingwangchan
        6
    xingwangchan  
    OP
       23h 46m ago
    @wktline 哈哈,我已经用 AI 优化过一轮了。性能到瓶颈了才来找网友的
    xingwangchan
        7
    xingwangchan  
    OP
       23h 42m ago
    @tianjiyao 国内管控比较严格,只有市以上的广播电视行政部门才有资格申请设立电台
    FstarKing
        8
    FstarKing  
       23h 36m ago   1
    真不错,挺有意思
    XTTX
        9
    XTTX  
       23h 26m ago
    用中国地图容易被喷,实属无解。
    maybedk
        10
    maybedk  
       23h 20m ago
    挺好玩的哈哈,不过好像有 bug 。好像是我点某个频道无数据的话,会随机跳到别的地方。
    qcbf111
        11
    qcbf111  
       23h 12m ago
    用 unity 导出 webgl,走 unity 的渲染管线应该性能会高很多
    Parva
        12
    Parva  
       23h 8m ago   1
    好有意思,随便点一个,听起了音乐。
    lmsh7
        13
    lmsh7  
       23h 7m ago   1
    牛逼的, 很棒的 idea
    qcbf111
        14
    qcbf111  
       23h 4m ago
    @qcbf111 目测了下任务管理器, 原因应该在 pso 管线状态切换,还有渲染元素剔除排序收集这个阶段
    IsaacYoung
        15
    IsaacYoung  
       22h 40m ago
    静态的实例化渲染
    aidevs
        16
    aidevs  
       22h 35m ago   1
    不错,666
    logyxiao
        17
    logyxiao  
       22h 31m ago
    看起来挺炫的
    sn0wdr1am
        18
    sn0wdr1am  
       22h 25m ago
    嘲讽客户硬件太渣,让他们升级内存,升级 CPU 。
    cst4you
        19
    cst4you  
       22h 22m ago

    看着卡卡的, 以为渲染性能问题, 没想到是限帧率了
    lifei6671
        20
    lifei6671  
       22h 20m ago
    使用 WASM 技术应该可以吧。
    joinmouse
        21
    joinmouse  
       22h 13m ago   1
    楼主创意很好!!!

    体验设备: MacBookM4 Pro 48G 内存

    性能 Lighthouse 测试如下:
    https://v2ex.com/i/eDxpTY3n.png

    目前看还是 js 执行太耗时了(可能是动态渲染),看是否可以用一些懒加载的思路来优化
    hahahabro
        22
    hahahabro  
       20h 49m ago
    idea 很棒,想抄
    zhuang0718
        23
    zhuang0718  
       19h 49m ago
    喜欢~
    oneend
        24
    oneend  
       19h 46m ago
    感觉很厉害了, 虽然打开点几下,我 M1pro 风扇都转飞了...
    zhuang0718
        25
    zhuang0718  
       19h 43m ago
    请问做了多久?
    Paradoxos
        26
    Paradoxos  
       19h 31m ago   1
    创意是来自这个吗? https://radio.garden
    yiton
        27
    yiton  
       18h 34m ago
    还有平壤之声
    easylee
        28
    easylee  
       17h 39m ago
    为何点击一些电台比如 HK 会跳转去其他地方的电台?
    nsjs
        29
    nsjs  
       17h 28m ago via Android
    js 端 webgl 的优化重点之一是 cpu 性能,你的对象 8000 个光遍历就超出帧时了。可以用实例化渲染,threejs 也应该有吧
    Gobling
        30
    Gobling  
       10h 16m ago via Android
    节点太多,不应该实时渲染。

    不知道能否用到游戏开发中烘焙的概念,在后台队列进行烘焙成图给前端用,顺便还能检查节点质量。

    前端点击某个区域后,默认进行放大地图操作,放大到某个程度,才进行实时渲染节点,这时候才是目前的状态,小区域渲染应该就不会那么卡。
    labubu
        31
    labubu  
       8h 27m ago
    这玩意早就有了,还上了 lks 的视频,https://radio.garden/
    momocraft
        32
    momocraft  
       5h 26m ago
    看不到代码 从你描述猜 可以试试非交互状态的多个点合并成一个 object ,共享一个动态 material
    nickxudotme
        33
    nickxudotme  
       4h 46m ago
    我记得这种东西很早就有了? xQc 之前经常玩?
    xingwangchan
        34
    xingwangchan  
    OP
       52 mins ago
    @maybedk 有些音源国内被墙,还有些音源不稳定可能会失效。
    所以超时一定时间,自动寻找下一个电台,避免用户久等
    xingwangchan
        35
    xingwangchan  
    OP
       51 mins ago
    @lifei6671 我周末研究研究
    xingwangchan
        36
    xingwangchan  
    OP
       50 mins ago
    @Gobling 有道理
    xingwangchan
        37
    xingwangchan  
    OP
       49 mins ago
    @nsjs 我试试
    xingwangchan
        38
    xingwangchan  
    OP
       45 mins ago
    @zhuang0718 快半年了,去年十一月份开始的,一点一点打磨,自娱自乐,也没有做推广。
    这周偶然看了一下后台,竟然有 3000+用户了。
    为了这些用户,赶紧更新了一波
    xingwangchan
        39
    xingwangchan  
    OP
       40 mins ago
    @Paradoxos 说实话,我是做完之后才知道这个网站的。
    最初的创意来自于一个二维地图的 radio 网站,出自 GIS 的本能,我觉得可以把它做的更炫酷一些,于是就有了 https://www.radiosphere.live
    现在看达到目的了,确实比原网站更酷一些
    About     Help     Advertise     Blog     API     FAQ     Solana     5036 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 97ms UTC 09:38 PVG 17:38 LAX 02:38 JFK 05:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86