unreal无损音乐百度云_将网易云音乐专用的无损音乐格式转换成全平台通用的无损格式...
前几天发现网易云音乐的ncm格式很坑爹,由于网易云的部分音乐采取了这种流媒体平台模式,这种格式的歌曲下载到设备本地以后只有在网易云音乐的app上面才能播放,而且还要在会员生效期间才能播
今天网易云弄出一个ncm,明天百度音乐来一个cnm,后天酷狗推出nmb,大后天qq音乐又来了个rnm。目前国内的音乐版权可谓是乱到了一个极端,阿叉想听一个歌手的歌还得在酷狗和网易云之间来回跑,最终用户就成了受害者
花钱买的歌我们理所当然有权利支配,而不是短期的租借,所以在这里提供一个在尽量不影响音质的情况下将ncm格式转换成flac格式的方法
↓↓↓↓↓↓↓↓↓
(链接挂了的话就尽情骚扰阿叉的微信吧)
使用方法就是把要转换的ncm音乐文件直接拖到 格式转换.exe上
然后flac格式的音乐文件就会自己变出来啦
↑↑↑↑↑↑↑↑↑
以这首Sailing为例,经过转换以后得到了flac文件:
把成品导入AU之后可以发现高频部分还是很完整的,完全符合无损音质的表现
和来自某狗的原版flac对比:
可以明显看出,转码后高频部分没有被切掉,比特率都是968kbps,音质几乎没有区别,所以我们可以完美地完成无损到无损的转换
附上源代码和注释:
import binascii
import struct
import base64
import json
import os
from Crypto.Cipher import AES
def dump(file_path):
core_key = binascii.a2b_hex("687A4852416D736F356B496E62617857")
meta_key = binascii.a2b_hex("2331346C6A6B5F215C5D2630553C2728")
#core_key和meta_key,把这个字符串按照十六进制反解析为二进制字节序列(bytes类型)
unpad = lambda s : s[0:-(s[-1] if type(s[-1]) == int else ord(s[-1]))]
f = open(file_path,'rb')
header = f.read(8)
assert binascii.b2a_hex(header) == b'4354454e4644414d'
#打开ncm文件并读取8个字节,确认这8个字节是否是字节序列b'4354454e4644414d',0x43=C,所以这些字节是'CTENFDAM',说明这些就是ncm独有的文件标记
f.seek(2, 1)
key_length = f.read(4)
key_length = struct.unpack('
key_data = f.read(key_length)
key_data_array = bytearray(key_data)
for i in range (0,len(key_data_array)): key_data_array[i] ^= 0x64
#获取4字节的key,并且按照小端(
key_data = bytes(key_data_array)
cryptor = AES.new(core_key, AES.MODE_ECB)
key_data = unpad(cryptor.decrypt(key_data))[17:]
#然后用之前的core_key创建了AES_ECB解密器,将整个明文分成若干段相同的小段,然后对每一小段进行加密,如果不足则会进行补足。
cryptor.decrypt(key_data)解析出来的是:
b'neteasecloudmusic10073261712832E7fT49x7dof9OKCgg9cdvhEuezy3iZCL1nFvBFd1T4uSktAJKmwZXsijPbijliionVUXXg9plTbXEclAE9Lb\r\r\r\r\r\r\r\r\r\r\r\r\r'
key_length = len(key_data)
key_data = bytearray(key_data)
key_box = bytearray(range(256))
c = 0
last_byte = 0
key_offset = 0
for i in range(256):
swap = key_box[i]
c = (swap + last_byte + key_data[key_offset]) & 0xff
key_offset += 1
if key_offset >= key_length: key_offset = 0
key_box[i] = key_box[c]
key_box[c] = swap
last_byte = c
#标准RC4-KSA算法去计算S-box
meta_length = f.read(4)
meta_length = struct.unpack('
meta_data = f.read(meta_length)
meta_data_array = bytearray(meta_data)
for i in range(0,len(meta_data_array)): meta_data_array[i] ^= 0x63
meta_data = bytes(meta_data_array)
meta_data = base64.b64decode(meta_data[22:])
cryptor = AES.new(meta_key, AES.MODE_ECB)
meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
meta_data = json.loads(meta_data)
#meta_data的值是这样的:
b"163key(Don't modify):L64FU3W4YxX3ZFTmbZ+8/fOGFX4ZDFzRxiE6WTSCw8Wbw8yYSVQFmAmCHw9A96ZnO0UOuMsVWYFWvoqD0/YcH3r7VAGU8B3l+FBJm4JL6is23S2yXChnSbfLIksnEUcTC7JtrA1JAoR0GVnz+OT3hGTJRsjGIVQXg2yide/YKBACffE+oYBApqZ5Isq0n7h/MlBnjn6ihuSlIl5V2rXEjSISQr031eSBdEVJ/JcwttzLafIPBh2FQfaVd/U0inWY5jxCXZCw/jxcIdGmGH/0Oft3UlNPt2kDBrsivoVuD03tMWL6A5Flg/jCbofSOblHFC79oU3WF9doUjD24BXuu6K7wyoWkgyG7SJu8tk72hkGw3rLK1nbTHsSEIPjocC6Ba9mzF48SB087MFTSn+9PXPZIboMXFXGI3TpMj4rR6cD+6CEWS7EoZrUC1cipi/A0jT/rFtAirM4hmkbrvslJumMHDJz1q9o6t3XRWydyoIaC3ktXuesyV8sbuoQ+Y/EMWNZRN3KhGR/jnnQPBtseQ=="
前面有22位的“163 key(Don't modify):”,去掉之后用base64解码,并同样地通过AES_ECB和meta_key进行解密:
b'music:{"musicId":441491828,"musicName":"\xe6\xb0\xb4\xe6\x98\x9f\xe8\xae\xb0","artist":[["\xe9\x83\xad\xe9\xa1\xb6",2843]],"albumId":35005583,"album":"\xe9\xa3\x9e\xe8\xa1\x8c\xe5\x99\xa8\xe7\x9a\x84\xe6\x89\xa7\xe8\xa1\x8c\xe5\x91\xa8\xe6\x9c\x9f","albumPicDocId":2946691248081599,"albumPic":"https://p4.music.126.net/wSMfGvFzOAYRU_yVIfquAA==/2946691248081599.jpg","bitrate":320000,"mp3DocId":"668809cf9ba99c3b7cc51ae17a66027f","duration":325266,"mvId":5404031,"alias":[],"transNames":[],"format":"mp3"}\r\r\r\r\r\r\r\r\r\r\r\r\r'
去掉前面的 music: ,然后转为json字典,可以得到一些歌曲原本的信息,比如歌手,歌名之类的
crc32 = f.read(4)
crc32 = struct.unpack('
f.seek(5, 1)
image_size = f.read(4)
image_size = struct.unpack('
image_data = f.read(image_size)
file_name = meta_data['musicName'] + '.' + meta_data['format']
m = open(os.path.join(os.path.split(file_path)[0],file_name),'wb')
chunk = bytearray()
while True:
chunk = bytearray(f.read(0x8000))
chunk_length = len(chunk)
if not chunk:
break
for i in range(1,chunk_length+1):
j = i & 0xff;
chunk[i-1] ^= key_box[(key_box[j] + key_box[(key_box[j] + j) & 0xff]) & 0xff]
m.write(chunk)
m.close()
f.close()
#用修改后的RC4-PRGA算法进行还原并输出新的歌曲文件,得到flac的原本数据
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
for file_path in sys.argv[1:]:
try:
dump(file_path)
except:
pass
else:
print("Usage: python ncm_transformation.py \"File Name\"")
另:这个是git上一个大神弄的,看得懂的可以看一下,好像比这个要复杂点
https://github.com/nondanee/ncmdump
unreal无损音乐百度云_将网易云音乐专用的无损音乐格式转换成全平台通用的无损格式...相关推荐
- unreal无损音乐百度云_嵐-IN THE SUMMER[FLAC]
嵐-IN THE SUMMER[FLAC] 2020-07-27Mb IN THE SUMMER - 嵐 (あらし) 词:Rami Yacoub/Gregory Hein/Funk Uchino 曲: ...
- unreal无损音乐百度云_嵐-IN THE SUMMER
嵐-IN THE SUMMER FLAC 07/29 IN THE SUMMER - 嵐 (あらし) 词:Rami Yacoub/Gregory Hein/Funk Uchino 曲:Rami Yac ...
- java 音乐api接口_关于网易云音乐爬虫的api接口?
java 版本的网易 api 加密方式: 加密工具类 https://github.com/junbaor/netease/blob/master/src/main/java/com/junbaor/ ...
- php案例分析百度云_案例 | QQ 音乐还是网易云音乐?看完分析,你会选哪一个?...
欢迎阅读小禾野君~ 上期分析了微信和 QQ,可以点击这里哦- 小禾呈:微信和 QQ,两大社交巨头为何能够共存?zhuanlan.zhihu.com 被问到在用的音乐 App 时,办公室的小伙伴们只给 ...
- 除了提升听感,鲸云音效对网易云音乐还意味着什么?
最近,网易云音乐听歌界面的右上角出现了一个类似"鲸鱼尾"的标志,点开来发现,是网易云音乐上线不久的"鲸云音效"功能.截至目前,使用推荐音效"3D环绕& ...
- 网易云api如何调用_分析网易云音乐API的经历
在做qq机器人的时候想加入点歌功能,虽然自带一个点歌插件,但是只能分享QQ音乐,所以我想着自己写一个网易云音乐的. 首先打开网易云音乐的搜索界面,F12打开开发者工具并切换到Network. 随便搜索 ...
- 网易云音乐android api_网易云音乐怎么发布个人Mlog?网易云音乐发布个人Mlog的教程介绍...
现在很多人都喜欢发Mlog,网易云音乐中也可以发布mlog啦,下面小编就为大家带来网易云音乐发布个人Mlog的具体操作方法,想知道的话就来看看吧. 网易云音乐怎么发布个人Mlog?网易云音乐发布个人M ...
- 腾讯音乐回港上市,抖音取代网易云,成为腾讯音乐终极对手?
回归港股二次上市,腾讯音乐摸着"抖音"过河? 在线音乐下半场,竞争格局已变:传统老对手网易云音乐之外,腾讯音乐也面临短视频的新挑战.异军突起的在线演唱会,巨头间亦竞争激烈:9月2日 ...
- 电脑网易云音乐,拿下华研,网易云音乐终于解决1%的大难题,可阿里音乐以后咋办?...
3月1日,网易云音乐和华研国际宣布达成战略合作,将在华语音乐的宣传推广和原创音乐人的扶持培养方面,展开多样化的合作.其中,在音乐版权合作方面,网易云音乐已获得华研国际旗下目前全量音乐曲库的授权. 这件 ...
最新文章
- c语言fsetpos是什么,fsetpos - [ C语言中文开发手册 ] - 在线原生手册 - php中文网
- 权威报告】WanaCrypt0r勒索蠕虫完全分析报告
- Linux文件目录及其作用
- 在c语言中如何屏蔽一段程序,如何在用C语言关闭TCP程序中的Nagle算法
- POJ 3041 Asteroids (对偶性,二分图匹配)
- Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法
- CentOS7 服务器连接超时自动断开问题解决
- Kepware AB驱动 · 秒懂百科
- win10 UWP RSS阅读器
- 显卡驱动设备状态代码31
- Win10运行红色警戒2尤里的复仇联机技巧+防守地图
- python获取outlook邮件内容_Python3读取Outlook邮件并写入MySQL
- laravel:如何快速实现数据填充,创建模拟数据(使用seeder)
- Android 系统的分区和文件系统(一)--Android分区的大概框架
- 怎样在计算机上登录qq音乐,如何使用手机控制电脑qq音乐播放
- QT控件被其他控件遮盖
- Android开发技巧——定制仿微信图片裁剪控件
- sbt编程语言scala的构建工具配置及项目构建(附带网盘下载)
- 视角设置(第一人称、第三人称)
- while循环、方法(伟大的作品,不是靠力量而是靠坚持才完成的。)
热门文章
- redis mysql原理_MYSQL MONGODB REDIS 同步原理以及高可用性对比
- ARM(IMX6U)裸机主频和时钟
- python装饰器参数讲解_python装饰器的详细解析
- 青岛西海岸惠普大数据_青岛西海岸新区用好卫星大数据 为城市治理全面赋能...
- mysql中使用安全等于 <=>
- Spring的IOC原理(通俗解释)
- 盘点Spring Boot最核心的27个注解
- 只有3%的猿能完全看懂的高端漫画
- 分别使用 XHR、jQuery 和 Fetch 实现 AJAX
- java 布尔表达式_java - 布尔值,条件运算符和自动装箱