作用/意义
由于meting-api是调用网易云的接口,所以需要vip的歌曲需要一个有vip的账号cookie才能完整解析,本着能白嫖绝不花钱的原则,我制作了一个python脚本将已经离线的歌曲文件伪造成meting-api用nginx返回
这样不仅可以避免每个月多一笔开销,还能避免自己喜欢的歌曲失效
效果演示
物品/软件准备
- 服务器一台
- nginx(默认已经配置好域名,证书等)
- 音乐资源(带独立/嵌入的歌曲封面/歌词)
- python (可选docker内运行)
- ffmpeg二进制文件
配置过程
分析meting-api返回结果
在访问meting-api的url如http://127.0.0.1/?server=netease&type=playlist&id=9379831714返回的结果(仅展示部分)
json
[
{
"name": "经过",
"artist": "张杰/HOYO-MiX",
"url": "http://127.0.0.1/?server=netease&type=url&id=2631333977",
"pic": "http://127.0.0.1/?server=netease&type=pic&id=109951170000135696",
"lrc": "http://127.0.0.1/?server=netease&type=lrc&id=2631333977"
},
{
"name": "Myself & I",
"artist": "TheFatRat/RIELL",
"url": "http://127.0.0.1/?server=netease&type=url&id=2140097072",
"pic": "http://127.0.0.1/?server=netease&type=pic&id=109951169448554402",
"lrc": "http://127.0.0.1/?server=netease&type=lrc&id=2140097072"
}
]
其中的链接是跳转到音乐平台的资源的,这里可以直接换成自己的
所以我们只需要拿到 歌手 歌名 歌曲资源链接 歌曲封面资源链接 歌词资源链接这几个东西再写进一个json即可,这些东西都是静态的,所以可以用nginx搞定
配置nginx文件服务器
- 新建一个nginx可以访问的
/res/music文件夹以存放音乐相关资源文件
nginx
└─ res
└─ music
├─ flac.json
├─ mp3.json
└─ input
├─ 歌手 - 歌名1.flac
├─ 歌手 - 歌名1.lrc
├─ 歌手 - 歌名2.lrc
└─ 歌手 - 歌名2.mp3
- 新建一个res.conf文件并在nginx.conf引入
nginx
server {
listen [::]:443 ssl;
listen 443 ssl;
listen [::]:80;
listen 80;
ssl_certificate /cert/A/fullchain.cer;
ssl_certificate_key /cert/A/key.key;
server_name res.your-domain.com;
root /res;
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
autoindex_exact_size off;
autoindex_localtime on;
default_type application/octet-stream;# 将当前目录中所有文件的默认MIME类型设置为application/octet-stream
if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx)$){# 当文件格式为上述格式时,将头字段属性Content-Disposition的值设置为"attachment"
add_header Content-Disposition: 'attachment;';
}
sendfile on;
sendfile_max_chunk 1m;
tcp_nopush on;
directio 5m;
directio_alignment 4096;
output_buffers 4 32k;
max_ranges 4096;
send_timeout 20s;
postpone_output 2048;
chunked_transfer_encoding on;
}
}
- 检查nginx配置文件语法是否正确,如果正确则热重启以让上面的配置生效
bash
nginx -t
nginx -s reload
配置python脚本
下载ffmpeg的二进制文件,放在/ffmpegh以供调用
在其他地方新建一个main.py并用python运行
python
import os
import json
import subprocess
input_dir = '/res/music/input'
pic_dir = '/res/music/pic'
mp3_dir = '/res/music/output/mp3'
flac_dir = '/res/music/output/flac'
lrc_dir = '/res/music/lrc'
mp3_json = '/res/music/mp3.json'
mp3_json_file = '/res/music/mp3'
flac_json = '/res/music/flac.json'
flac_json_file = '/res/music/flac'
res_url= "https://res.your-domain.com/music/"
pass_recompression=True
pass_recopy=True
pass_repic=True
os.makedirs(pic_dir, exist_ok=True)
os.makedirs(mp3_dir, exist_ok=True)
os.makedirs(flac_dir, exist_ok=True)
os.makedirs(lrc_dir, exist_ok=True)
m4a_data = []
mp3_data = []
flac_data = []
print("开始处理flac文件")
i=1
files=int(len(os.listdir(input_dir))/2-1)
for filename in os.listdir(input_dir):
if filename.endswith('.flac'):
file_path = os.path.join(input_dir, filename)
base_name = os.path.splitext(filename)[0]
print(f"正在读取:{base_name}.flac 总进度:{i}/{files}")
title = base_name.split(' - ',1)[1]
author= base_name.split(' - ',1)[0]
pic_path = os.path.join(pic_dir, f'{base_name}.jpg')
if os.path.exists(pic_path) and pass_repic:
print("图片已存在,跳过提取")
else:
try:
result = subprocess.run(['/ffmpeg/ffmpeg', '-i', file_path, '-an', '-vcodec', 'copy', '-y', pic_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except Exception as e:
print(f"{base_name}.flac : 图片提取失败")
print(e)
else:
print(f"{base_name}.flac : 图片提取成功")
flac_path = os.path.join(input_dir, f'{base_name}.flac')
if os.path.exists(flac_path) and pass_recopy:
print("文件已存在,跳过复制")
else:
try:
os.system(f'cp -f "{flac_path}" "{flac_dir}"')
except Exception as e:
print(f"{base_name}.flac : 音乐复制失败")
print(e)
else:
print(f"{base_name}.flac : 音乐复制成功")
lrc_path = os.path.join(input_dir, f'{base_name}.lrc')
if os.path.exists(lrc_path) and pass_recopy:
print("文件已存在,跳过复制")
else:
try:
os.system(f'cp -f "{lrc_path}" "{lrc_dir}"')
except Exception as e:
print(f"{base_name}.lrc : 歌词复制失败")
print(e)
else:
print(f"{base_name}.flac : 歌词复制成功")
mp3_path = os.path.join(mp3_dir, f'{base_name}.mp3')
if os.path.exists(mp3_path) and pass_recompression:
print("文件已存在,跳过压缩")
else:
print("开始压缩音质,请耐心等待")
try:
result = subprocess.run(['/ffmpeg/ffmpeg', '-i', file_path, '-q:a', '0',"-y", mp3_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except Exception as e:
print(f"{base_name}.flac : 音质压缩失败")
print(e)
else:
print(f"{base_name}.flac : 音质压缩成功")
path_to_pic = res_url+f"pic/{base_name}.jpg"
path_to_mp3 = res_url+f"output/mp3/{base_name}.mp3"
path_to_flac = res_url+f"output/flac/{base_name}.flac"
path_to_lrc = res_url+f"lrc/{base_name}.lrc"
mp3_data.append({
'title': title,
'author': author,
'pic': path_to_pic,
'url': path_to_mp3,
'lrc': path_to_lrc
})
flac_data.append({
'title': title,
'author': author,
'pic': path_to_pic,
'url': path_to_flac,
'lrc': path_to_lrc
})
print("写入json数据ing")
print("-"*30)
i+=1
print("\nflac sucess\n")
print("开始处理mp3文件")
for filename in os.listdir(input_dir):
if filename.endswith('.mp3'):
file_path = os.path.join(input_dir, filename)
base_name = os.path.splitext(filename)[0]
print(f"正在读取:{base_name}.mp3 总进度:{i}/{files}")
title = base_name.split(' - ',1)[1]
author= base_name.split(' - ',1)[0]
pic_path = os.path.join(pic_dir, f'{base_name}.jpg')
if os.path.exists(pic_path) and pass_repic:
print("图片已存在,跳过提取")
else:
try:
result = subprocess.run(['/ffmpeg/ffmpeg', '-i', file_path, '-an', '-vcodec', 'copy', '-y', pic_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except Exception as e:
print(f"{base_name}.mp3 : 图片提取失败")
print(e)
else:
print(f"{base_name}.mp3 : 图片提取成功")
mp3_path = os.path.join(input_dir, f'{base_name}.mp3')
if os.path.exists(mp3_path) and pass_recopy:
print("文件已存在,跳过压缩")
else:
try:
os.system(f'cp -f "{mp3_path}" "{mp3_dir}"')
except Exception as e:
print(f"{base_name}.mp3 : 音乐复制失败")
print(e)
else:
print(f"{base_name}.mp3 : 音乐复制成功")
lrc_path = os.path.join(input_dir, f'{base_name}.lrc')
if os.path.exists(lrc_path) and pass_recopy:
print("文件已存在,跳过压缩")
else:
try:
os.system(f'cp -f "{lrc_path}" "{lrc_dir}"')
except Exception as e:
print(f"{base_name}.lrc : 歌词复制失败")
print(e)
else:
print(f"{base_name}.lrc : 歌词复制成功")
path_to_pic = res_url+f"pic/{base_name}.jpg"
path_to_mp3 = res_url+f"output/mp3/{base_name}.mp3"
path_to_lrc = res_url+f"lrc/{base_name}.lrc"
mp3_data.append({
'title': title,
'author': author,
'pic': path_to_pic,
'url': path_to_mp3,
'lrc': path_to_lrc
})
print("写入json数据ing")
print("-"*30)
i+=1
print("\nmp3 sucess\n")
print("写入JSON文件")
with open(mp3_json_file, 'w') as f:
json.dump(mp3_data, f, indent=4)
with open(mp3_json, 'w') as f:
json.dump(mp3_data, f, indent=4)
with open(flac_json_file, 'w') as f:
json.dump(flac_data, f, indent=4)
with open(flac_json, 'w') as f:
json.dump(flac_data, f, indent=4)
print("write sucess")
Docker化
根据自己情况修改
dockerfile:
dockerfile
yaml
在博客中使用此接口
flac音质: https://res.your-domain.com/music/flac
mp3音质: https://res.your-domain.com/music/mp3