NAS(OpenResty/nginx)上挂载本地音乐目录,并通过浏览器或博客播放。
1. 教程概览
本文将带你完成以下步骤:
- 环境准备
- 挂载音乐目录到服务器
- 配置目录权限
- 安装并配置 OpenResty/nginx
- 编写 nginx 配置(alias、autoindex、CORS、UTF-8)
- 重载并测试访问
- 在博客中嵌入播放器
- 常见问题与排查
2. 环境准备
- 操作系统:Linux(Debian/Ubuntu/CentOS 均可)
- Web 服务器:OpenResty / nginx
- 音乐存放目录:
/mnt/big/share/jellyfin/media/music/
- 域名:
music.yys.zone
已解析到 NAS 公网/内网 IP - SSL 证书:已准备好
fullchain.cer
与xxx.key
提示:如果还未安装 OpenResty/nginx,可参考官方文档快速安装。
3. 挂载音乐目录到 NAS
假设你的音乐都存在于外接硬盘或另一分区上,已通过 /etc/fstab
或手动挂载到,不是的话可以忽略:
sudo mkdir -p /mnt/big/share/jellyfin/media/music
sudo mount /dev/sdX1 /mnt/big/share/jellyfin/media/music
请根据实际设备路径调整
/dev/sdX1
。
4. 配置目录权限
nginx(openresty)默认以 nobody
或 www-data
用户运行,需要对音乐目录和文件授予“其他用户”可读、可进权限:
# 递归授予所有文件可读
sudo chmod -R o+r /mnt/big/share/jellyfin/media/music
# 授予所有目录可进入权限
sudo find /mnt/big/share/jellyfin/media/music -type d -exec chmod o+x {} \;
执行完成后,nginx 即可访问所有子目录与文件。
5. OpenResty/nginx 配置
将以下内容追加到 /usr/local/openresty/nginx/conf/nginx.conf
(或你自己的 include 文件):
######################################
# music.yys.zone 静态音乐目录配置
######################################
# HTTP 服务
server {
listen 80;
listen [::]:80;
server_name music.yys.zone;
# 访问根路径时,直接映射到本地音乐目录
location / {
alias /mnt/big/share/jellyfin/media/music/;
autoindex on; # 开启目录浏览
charset utf-8; # 确保中文正常显示
add_header Access-Control-Allow-Origin *; # 允许跨域播放
}
}
# HTTPS 服务
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name music.yys.zone;
ssl_certificate /home/music.yys.zone_ecc/fullchain.cer;
ssl_certificate_key /home/music.yys.zone_ecc/music.yys.zone.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
alias /mnt/big/share/jellyfin/media/music/;
autoindex on;
charset utf-8;
add_header Access-Control-Allow-Origin *;
}
}
配置要点
- alias
直接将 URL 路径/xxx.mp3
映射到磁盘路径/mnt/.../music/xxx.mp3
。 - autoindex on
生成简易文件列表,访客可直接点击播放或下载。 - charset utf-8
保证自动索引页面使用 UTF-8 编码,中文目录/文件名不乱码。 - Access-Control-Allow-Origin *
允许跨域资源共享(CORS),以便博客页面上<audio>
正常播放。
6. 重载并测试
- 语法检查
sudo openresty -t # 或 nginx -t
- 重载配置
sudo systemctl reload openresty # 或 sudo systemctl reload nginx
- 浏览器访问
打开:http://music.yys.zone/
- 能看到完整的目录列表
- 点任意
.mp3
文件即可在线播放或下载 - 中文文件夹/文件名亦正常显示
7. 在博客中嵌入播放器
以最简单的 HTML5 <audio>
为例,复制到你的博客文章中:
<h3>试听:My Favorite Track</h3>
<audio controls preload="none">
<source src="https://music.yys.zone/album1/song.mp3" type="audio/mpeg">
您的浏览器不支持 audio 元素。
</audio>
如果想要更好看的播放器,可用 APlayer:
<link rel="stylesheet" href="https://unpkg.com/aplayer/dist/APlayer.min.css">
<script src="https://unpkg.com/aplayer/dist/APlayer.min.js"></script>
<div id="aplayer"></div>
<script>
const ap = new APlayer({
container: document.getElementById('aplayer'),
audio: [
{
name: 'Song Name',
artist: 'Artist Name',
url: 'https://music.yys.zone/album1/song.mp3',
cover: 'https://link-to-cover.jpg'
},
// 可添加多首曲目
]
});
</script>
8. 常见问题与排查
问题现象 | 可能原因 | 排查/解决 |
---|---|---|
部分目录打不开 | 目录或上级目录缺少“其他用户可执行”权限 | chmod o+x 目录 |
文件列表中文乱码 | 未设置 charset utf-8 |
在 location 块加上 charset utf-8; |
浏览器无法播放音频 | 跨域被拦(CORS) | 添加 add_header Access-Control-Allow-Origin *; |
nginx 启动报 alias 错误 |
写成 root 或路径格式不对 |
确保使用 alias /绝对路径/; |
9. 小结
通过以上步骤,你已成功:
- 在 NAS 上以静态方式挂载本地音乐目录
- 配置 nginx 自动列表与 UTF-8 编码
- 添加 CORS 头,确保博客页面可播放
- 无需后台服务,浏览器直连静态文件,性能开销极小
10.代码
<link rel="stylesheet" href="https://unpkg.com/aplayer/dist/APlayer.min.css">
<script src="https://unpkg.com/aplayer/dist/APlayer.min.js"></script>
/* 一体化浮动播放器容器 */
#floating-player {
position: fixed;
top: 90px; right: 10px;
width: 50px; height: 50px;
border-radius: 50%;
overflow: hidden;
z-index: 9999;
background: #fff;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
cursor: pointer;
transition: width 0.3s, height 0.3s, border-radius 0.3s;
display: flex; align-items: center; justify-content: center;
}
/* 展开状态 */
#floating-player.expanded {
width: 320px; height: auto;
border-radius: 8px;
padding: 10px;
}
/* 使 APlayer 主体在容器内铺满 */
#floating-player.expanded #aplayer-container .aplayer {
width: 100% !important;
max-width: none;
}
/* 封面图 */
#fp-icon img {
width: 50px; height: 50px;
border-radius: 50%;
object-fit: cover;
}
/* 隐藏播放器内容 */
#fp-content {
display: none;
width: 100%;
}
/* 展开后显示 */
#floating-player.expanded #fp-content {
display: block;
}
/* 加载动画 */
#fp-spinner {
margin: 10px auto;
width: 24px; height: 24px;
border: 3px solid rgba(0,0,0,0.1);
border-top-color: #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin-cover {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
#fp-icon.rotating img {
animation: spin-cover 5s linear infinite;
}
<!-- 一体化浮动播放器 -->
<div id="floating-player">
<div id="fp-icon">
<img src="https://music.yys.zone:4000/徐良/犯贱.jpg" alt="Cover" />
</div>
<div id="fp-content">
<div id="fp-spinner"></div>
<div id="aplayer-container"></div>
</div>
</div>
document.addEventListener('DOMContentLoaded', function(){
const fp = document.getElementById('floating-player');
const iconImg = document.querySelector('#fp-icon img');
const spinner = document.getElementById('fp-spinner');
const content = document.getElementById('fp-content');
// const tracks = [
// ['https://xxxx/徐良/犯贱.mp3', '犯贱', '徐良', 'https://xxxx/徐良/犯贱.jpg'],
// // …可继续添加更多曲目
// ];
let metadataTimeout;
// 检测可用音源
Promise.all(tracks.map(item =>
fetch(item[0], { method: 'HEAD' })
.then(res => res.ok ? item : null)
.catch(() => null)
)).then(results => {
const available = results.filter(Boolean);
if (!available.length) {
fp.style.display = 'none';
return;
}
// 初始封面
iconImg.src = available[0][3];
const audioList = available.map(item => ({
url: item[0],
name: item[1],
artist: item[2],
cover: item[3],
lrc: item[0].replace(/\.\w+$/, '.lrc')
}));
// 初始化 APlayer,关键加 lrcType:3
const ap = new APlayer({
container: document.getElementById('aplayer-container'),
fixed: false,
autoplay: false,
loop: 'all',
volume: 0.7,
audio: audioList,
lrcType: 3 // 加载外部歌词
});
// 隐藏加载动画
ap.on('canplay', () => {
clearTimeout(metadataTimeout);
spinner.style.display = 'none';
});
metadataTimeout = setTimeout(() => spinner.style.display = 'none', 5000);
// 播放时:更新封面、标题、开始旋转
ap.on('play', () => {
const idx = ap.list.index;
const song = ap.list.audios[idx];
iconImg.src = song.cover;
// 标题
let titleEl = document.getElementById('fp-title');
if (!titleEl) {
titleEl = document.createElement('div');
titleEl.id = 'fp-title';
titleEl.style.marginTop = '8px';
titleEl.style.color = '#333';
titleEl.style.textAlign = 'center';
content.insertBefore(titleEl, document.getElementById('aplayer-container'));
}
titleEl.innerText = `${song.name} — ${song.artist}`;
// 旋转
fp.querySelector('#fp-icon').classList.add('rotating');
});
// 暂停/结束:停止旋转
const stopRotate = () => fp.querySelector('#fp-icon').classList.remove('rotating');
ap.on('pause', stopRotate);
ap.on('ended', stopRotate);
// 强制歌词滚动与音频同步
ap.on('timeupdate', () => {
ap.lrc && ap.lrc.reset();
});
// 点击切换展开/收起
fp.addEventListener('click', e => {
if (fp.classList.contains('expanded') && content.contains(e.target)) return;
fp.classList.toggle('expanded');
});
});
});
显示效果
本文作者: 永生
本文链接: https://yys.zone/detail/?id=415
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
评论列表 (0 条评论)