家里想唱歌,最省事的办法当然是买一套成品点歌机,机器往电视旁边一放,插上线就能用,曲库和界面也都有人管。问题是这东西平时大概率在吃灰,买回来占一个位置不说,后面想加歌、换硬盘、整理曲库,很多时候还得顺着厂商的规则来,碰上会员、广告或者系统停更,心里多少有点膈应。

而熊猫作为NAS玩家,自然想法不一样了,既然家里已经有一台长期在线的服务器,电影、照片、音乐都放在里面,为什么不能顺手把KTV也塞进去?这次方案采用的是绿联DXP6800 Pro,在UGOS Pro里用Docker部署nasktv项目,音源文件放在NAS硬盘中;雷鸟电视负责大屏播放;家里的手机连上Wi-Fi后能直接点歌,整套系统只在局域网里跑,不用每个人装App,也不用把自己的曲库交给第三方平台。
主机核心
绿联DXP6800 Pro是这套方案的中枢,项目本身是需要用到一些硬件性能的,英特尔酷睿i5-1235U的处理器有10核12线程,项目需要用到的一些本地模型这点负载对它来说基本等于热身,且因为性能有亢余,当家里有人唱歌时,NAS仍然可以继续下载、备份照片、跑影音服务,几个任务堆在一起也不至于互相抢得太难看。

DXP6800 Pro给了双10GbE网口、两个M.2 NVMe插槽、双雷电4、PCIe扩展和最高8K 60Hz的HDMI输出。家庭KTV本身吃不了万兆,它真正方便的是,曲库初次入库时经常要搬几百GB甚至几TB文件,万兆局域网能明显缩短等待,加上熊猫自媒体的副业,家里还有剪辑电脑、工作站等多台终端,带宽不用全挤在一条线上。

很多人看到六盘位,第一反应是“家用有必要吗”。实话说,轻度用户确实没必要,但如果你是屯屯鼠,那还是有必要。影视和音频这类文件有个特点,单个文件看着不大,攒起来却很快,尤其是保留高码率MV、演唱会版本和不同伴奏,一首歌几百MB很正常,再叠加电影、电视剧、全家照片和电脑备份,四盘位很容易从“够用”变成“又要换盘”。

六个SATA盘位的价值不是让你第一天就插满,而是留出后悔的空间。前期可以先上两块或三块盘,按自己的数据安全需求组阵列,怎么选要看数据价值,如果数据比较重要,那么千万别为了多一点可用容量把冗余全丢了。
硬盘选择
这次也是刚好准备给它加硬盘,顺便清一下灰,之前一直是插了4张盘,但随着东西越来越多也是感觉不够用了。

这次盘位里可以搭配东芝N300 NAS机械硬盘,CMR传统磁记录,转速为7200RPM,带旋转振动传感器,作为NAS专用盘,完全是按照NAS的7×24小时环境设计,对家庭曲库这种“大文件顺序读取为主,偶尔集中写入”的场景,CMR比一些采用SMR的普通桌面盘更省心,阵列重建和持续写入时也更符合预期。

定位对路,容量选择多,持续读写也够用,这次熊猫准备了两张8T。当然了,7200转机械盘不可能完全没声音,夜深以后磁头寻道和盘体振动还是能听见,如果对噪声特别敏感,干脆把机器放到书房或弱电柜,硬盘是拿来干活的,不是靠“静音”两个字哄自己睡觉。
电视联动
电视在这套方案里不负责存歌,也不负责跑服务,充当的是大屏点歌台,NAS-KTV把前端单独做成了Web容器,默认从NAS的端口访问,因此电视与服务器不需要是同一台设备,电视只要能通过浏览器访问局域网地址,就可以打开系统页面。

熊猫这里用的是雷鸟,当然,电视不一定非要是雷鸟,不过因为雷鸟和绿联本身就是有合作的,雷鸟的TV系统自带就有绿联云的小卡片,也算是一个加分项。

如果电视自带浏览器打不开全屏,或者播放某些MP4只有声音没有画面,可以换BrowseHere或其他Chromium内核电视浏览器,也可以接一个兼容性更好的盒子,实在不想折腾,拿笔记本接HDMI当播放端也行。
整个项目想要完整的体验,你就需要准备这些东西:装好UGOS Pro与Docker的绿联NAS、能正常访问局域网的电视、本地歌曲文件,以及一套独立的麦克风。
容器部署
打开绿联的的Docker应用,切到项目选项选择创建项目,把下面Compose内容贴进去:
♾️ yaml 代码:services:
backend:
image: ghcr.linkos.org/panda-995/nas-ktv-backend:${NASKTV_IMAGE_TAG:-latest}
pull_policy: always
ports:
- "3000:3000"
- "45678:45678/udp"
volumes:
- ./data/db:/app/data/db
- ./data/songs:/app/data/songs
- ./data/separation:/app/data/separation
- ./data/uploads:/app/data/uploads
environment:
NODE_ENV: production
PORT: "3000"
JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-me}
DB_PATH: /app/data/db/nasktv.db
SCAN_PATH: /app/data/songs
SEPARATOR_SERVICE_URL: http://separator:8001
SEPARATION_OUTPUT_DIR: /app/data/separation
SEPARATION_CONCURRENCY: ${SEPARATION_CONCURRENCY:-2}
SEPARATION_AUTO_ENABLE: ${SEPARATION_AUTO_ENABLE:-true}
HF_ENDPOINT: ${HF_ENDPOINT:-https://hf-mirror.com}
AI_ENABLED: ${AI_ENABLED:-false}
AI_BASE_URL: ${AI_BASE_URL:-https://api.openai.com/v1}
AI_API_KEY: ${AI_API_KEY:-}
AI_MODEL: ${AI_MODEL:-gpt-4o-mini}
AI_PARSE_CONCURRENCY: ${AI_PARSE_CONCURRENCY:-2}
AI_AUTO_PARSE_AFTER_SCAN: ${AI_AUTO_PARSE_AFTER_SCAN:-true}
depends_on:
separator:
condition: service_started
restart: unless-stopped
healthcheck:
test:
- CMD-SHELL
- >-
node -e "require('http').get(
'http://localhost:3000/api/health',
r => process.exit(r.statusCode === 200 ? 0 : 1)
).on('error', () => process.exit(1))"
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
separator:
image: ghcr.linkos.org/panda-995/nas-ktv-separator:${NASKTV_IMAGE_TAG:-latest}
user: "0:0"
pull_policy: always
volumes:
- ./data/songs:/app/data/songs:ro
- ./data/separation:/app/data/separation
- ./data/separator-cache:/app/cache
environment:
TORCH_HOME: /app/cache
DEMUCS_CACHE: /app/cache
HF_ENDPOINT: ${HF_ENDPOINT:-https://hf-mirror.com}
SEPARATION_CONCURRENCY: ${SEPARATION_CONCURRENCY:-2}
PYTORCH_INDEX_URL: ${PYTORCH_INDEX_URL:-https://download.pytorch.org/whl/cpu}
restart: unless-stopped
web:
image: ghcr.linkos.org/panda-995/nas-ktv-web:${NASKTV_IMAGE_TAG:-latest}
pull_policy: always
ports:
- "18080:80"
depends_on:
backend:
condition: service_healthy
restart: unless-stopped关于文件夹映射,其中data/songs为歌曲存放目录,你可以部署之后再放文件,也可以提前放,同时熊猫在镜像中已经添加了加速源,所以不需要再担心速度问题。

歌曲命名依然建议做干净,例如“歌手 - 歌名”,项目虽然预留了AI解析能力,但默认毕竟要外接API,不开AI不能指望系统替你猜完所有乱七八糟的文件名,即便以后开启AI,整齐的源文件也更方便迁移和备份。
这份配置最少要改一项JWT_SECRET,这里需要填写一个32位的长随机字符串,可以直接让豆包之类的帮你生成,AI曲名解析默认关闭,需要时再把AI_ENABLED设为true,补上AI_BASE_URL、AI_API_KEY与AI_MODEL就行。

保存并启动项目,Docker会拉取Backend、Separator和Web三个镜像,三个容器显示正常启动后,再用http://绿联NASIP:18080打开正式页面,也可以直接从绿联的Docker界面点击直接快捷访问,默认账号是admin,密码为admin123。

仪表盘会显示当前的曲库数量、歌手数、播放次数以及活跃房间,下面还有完整的AI解析和人声分离队列以及歌曲解析,相当于KTV的中控后台界面。

歌曲管理、去重和歌手管理这些就不用看了,很正常播放器的管理没有区别。
歌曲上传或者放到曲库之后首先看AI解析,配置好AI之后AI会根据提示词根据歌曲的内容进行解析歌曲名和歌手,还会进行流派分类等操作,最终这个解析并不会写入曲库中,而是作为json存在项目本地。

除了解析,人生分离就是最重要的了。一般来说个人找到的音源是默认没有人声伴奏分离的,所以这时候就要借助大模型来将人生和伴奏进行分离,首先在GPU管理这里我们能看到硬件信息和PyTorch状态,如果你有外接显卡,那么这里就能检测到你的外接显卡并用GPU版本模型来加速人声分离,如果没有那么就会采用CPU版本。

点击人声分离,这时候项目会调用你绿联NAS的本地CPU能力进行模型处理,再将分离的人声伴奏进行转码,熊猫的绿联DXP 6800Pro一首歌按照标准模型处理大概用时50秒左右。

分离之后可以点击后面的试听,这时候就能看到歌曲分成了原唱音频、伴奏音频、人声音频,且分离效果非常不错,如果想要更精细,可以选择更好的模型进行分离,不过耗时会更久一点。

分离配置在系统设置界面可以找到,同时需要注意右下角这个H5手机点歌,需要改成你的NASIP地址和端口然后加上/h5/的后缀,后面会用到。

在电视上安装NASKTV应用,下载地址在github搜索项目Panda-995/NAS-KTV,按页面提供二维码扫码,这里手机一定要是同一局域网,这时候手机就会弹出项目的后端配置界面,输入我们的后端地址,也就是http://绿联NASIP:18080,就能进入点歌界面。

这里熊猫的歌曲文件没有内嵌歌词,如果你有lrc歌词文件,也可以在后端的歌曲管理中去上传,这样桌面就能显示歌词了。

手机扫码之后的点歌界面长这样,除了支持点歌,也能作为遥控器使用,支持单独调节伴奏、人声音量,同时还提供了各种环绕声效果,也支持升调降调操作,基本是满足K歌的需求了。

这套方案落地后,最省心的是曲库确实在自己手里,当然,它没有商业KTV那种现成的海量在线曲库,第一次整理会花时间,人声分离更不是点一下马上完成,说白了,这是一套“愿意前期折腾,换后期自由”的方案。
写在最后
这套方案不一定适合所有人,它需要整理曲库,也需要花一点时间处理Docker路径、应用兼容,但折腾完之后,家里的照片、电影、音乐、KTV都能围着同一台NAS运转,这种“东西是自己的,规则也由自己定”的感觉,确实挺舒服。
以上便是本次分享的全部内容了。如果你觉得还算有趣或对你有所帮助,不妨点赞收藏,最后也希望能得到你的关注,咱们下期见!

panda