部署YesPlayMusic+UnblockNeteaseMusic

1
2
vim docker-compose.yml
docker-compose up -d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
services:
unblock:
#新版本会导致播放格式错误,故选择v0.27.1版本
image: krmeng/unblock-netease-music-enhanced:v0.27.1
container_name: music
command: "-o pyncmd migu -p 80:443"
networks:
music_network:
ipv4_address: 172.24.0.2
environment:
- FOLLOW_SOURCE_ORDER=true
YesPlayMusic:
image: krmeng/yesplaymusic:v0.4.8
container_name: YesPlayMusic
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- 8080:80
networks:
music_network:
ipv4_address: 172.24.0.3
extra_hosts:
- "music.163.com:172.24.0.2"
- "interface.music.163.com:172.24.0.2"
- "interface3.music.163.com:172.24.0.2"
environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0
restart: always
networks:
music_network:
ipam:
config:
- subnet: 172.24.0.0/24

nginx反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#请填写绑定证书的域名
server_name music.xxx;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/ssl/.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/ssl/.key;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

kuwo音源https会出现不安全,可能会出现“不支持音频格式的错误”

pyncmd音源更新

Release下载0.27.1版本的源码

修改src/provider/pyncmd.js如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const select = require('./select');
const request = require('../request');
const { getManagedCacheStorage } = require('../cache');

const track = (info) => {
// Credit: This API is provided by GD studio (music.gdstudio.xyz).
const url =
'https://music-api.gdstudio.xyz/api.php?types=url&source=netease&id=' +
info.id +
'&br=' +
['999', '320'].slice(
select.ENABLE_FLAC ? 0 : 1,
select.ENABLE_FLAC ? 1 : 2
);
return request('GET', url)
.then((response) => response.json())
.then((jsonBody) => {
if (
jsonBody &&
typeof jsonBody === 'object' &&
(!'url') in jsonBody
)
return Promise.reject();

return jsonBody.br > 0 ? jsonBody.url : Promise.reject();
});
};

const cs = getManagedCacheStorage('provider/pyncmd');
const check = (info) => cs.cache(info, () => track(info));

module.exports = { check };

编译

修改.swcrc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"env": {
"targets": {
"node": "12"
},
"mode": "usage",
"coreJs": "3.32",
"shippedProposals": true
},
"jsc": {
"parser": {
"syntax": "ecmascript"
}
},
"module": {
"type": "commonjs"
}
}

env,jsc不能同时设置,删除其中一个

1
2
npm install --save-dev webpack webpack-cli babel-loader @babel/core @babel/preset-env
npm run build
1
2
docker cp precompiled/app.js music:/app
docker cp precompiled/bridge.js music:/app

或者重新制作docker镜像

其他音源更新类似

YesPlayMusic未登录状态播放vip音乐

修改src/utils/Player.js

注释掉 import { isAccountLoggedIn } from ‘@/utils/auth’;

修改getAudioSourceFromNetease如下:

1
2
3
4
5
6
7
8
9
10
11
12
_getAudioSourceFromNetease(track) {
return getMP3(track.id).then(result => {
if (!result.data[0]) return null;
if (!result.data[0].url) return null;
if (result.data[0].freeTrialInfo !== null) return null; // 跳过只能试听的歌曲
const source = result.data[0].url.replace(/^http:/, 'https:');
if (store.state.settings.automaticallyCacheSongs) {
cacheTrackSource(track, source, result.data[0].br);
}
return source;
});
}

http(可选,不安全)

酷我音源https不安全,有概率出现“不支持音源格式”

编辑src/utils/Player.js

1
const source = result.data[0].url.replace(/^http:/, 'https:'); //删掉.replace(/^http:/, 'https:')

添加navidrome音源

新建src/provider/navidrome.js,粘贴以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const {
cacheStorage,
CacheStorageGroup,
getManagedCacheStorage,
} = require('../cache');
const insure = require('./insure');
const select = require('./select');
const request = require('../request');

const format = (song) => {
return {
id: song.id,
name: song.title,
duration: song.duration * 1000,
album: { id: song.album, name: song.album }, // 使用 song.album
artists: { id: song.artistId, name: song.artist }, // 使用 song.artistId
};
};
const search = (info) => {
const keyword = encodeURIComponent(
info.keyword
.replace(/ - .*/, '') // 去掉 - 及其后面的内容
.replace(/\s+\(live\)$/i, '(live)') // 去掉 (live) 前面的空格,处理小写
.replace(/\s+\(Live\)$/i, '(Live)') // 去掉 (Live) 前面的空格,处理大写
);
const url =
'https://xxx/rest/search2?' +
'songCount=5&songOffset=0&u=xxx&t=xxx&s=1c9a40&f=json&v=1.8.0&c=NavidromeUI&query=' +
keyword;
return request('GET', url)
.then((response) => response.json())
.then((jsonBody) => {
const list = jsonBody['subsonic-response'].searchResult2.song.map(format);
// 检查 list 是否为空
if (list.length === 0) {
return Promise.reject(new Error("navidrome: No matching song found"));
} else {
const matched = select(list, info);
return matched ? matched.id : Promise.reject(new Error("navidrome: No matching song found"));
}
});
};

const track = (id) => {
const url =
'https://xxx/rest/stream?' +
'u=xxx&t=xxx&s=xxx&f=json&v=1.8.0&c=NavidromeUI&id=' +
id;
return url;
};

const cs = getManagedCacheStorage('provider/navidrome');
const check = (info) => cs.cache(info, () => search(info)).then(track);

module.exports = { check, track };

自行替换链接中xxx部分

navidrome search2目前不支持“歌曲名 - 歌手”的搜索方式,上述代码只搜索歌曲名