jadepeng / Musicdecryptor
酷狗、网易等音乐缓存文件转mp3
Stars: ✭ 100
Programming Languages
csharp
926 projects
Labels
Projects that are alternatives of or similar to Musicdecryptor
Reactiveui
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable state away from your user interfaces, express the idea around a feature in one readable place and improve the testability of your application.
Stars: ✭ 6,709 (+6609%)
Mutual labels: winforms
Mvvmfx
MVVM for Wisej and Windows Forms - Caliburn.Micro and Bound controls libraries
Stars: ✭ 50 (-50%)
Mutual labels: winforms
Naps2
Scan documents to PDF and other file types, as simply as possible.
Stars: ✭ 1,018 (+918%)
Mutual labels: winforms
Jsoncsharpclassgenerator
JsonCSharpClassGenerator from http://jsonclassgenerator.codeplex.com/
Stars: ✭ 70 (-30%)
Mutual labels: winforms
Try Convert
Helping .NET developers port their projects to .NET Core!
Stars: ✭ 671 (+571%)
Mutual labels: winforms
Xclwinkits
一个实用的windows小工具集合,里面包含了多个常用的小软件。其中的批量修改文件名及文件内容功能,可以自定义修改规则,支持规则的导入与导出。不需要安装Office软件,支持Excel/Word/Txt等文件的文件名或文件内容的批量修改操作。另外还包括正则表达式测试小工具、字符串转js常量工具、加密与解密和日期时间差等,您也可以很方便地扩展相关功能。
Stars: ✭ 87 (-13%)
Mutual labels: winforms
Cefsharp
.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework
Stars: ✭ 8,440 (+8340%)
Mutual labels: winforms
Aerowizard
Library for easy creation of custom and Aero Wizards. Aero Wizard strictly follows Microsoft guidelines and uses Visual Styles to get visual theming.
Stars: ✭ 73 (-27%)
Mutual labels: winforms
Csla
A home for your business logic in any .NET application.
Stars: ✭ 865 (+765%)
Mutual labels: winforms
Logbert
Logbert is an advanced log message viewer for log4net, log4j and others.
Stars: ✭ 70 (-30%)
Mutual labels: winforms
Krypton Net 5.470
A update to Component factory's krypton toolkit to support the .NET 4.7 framework.
Stars: ✭ 79 (-21%)
Mutual labels: winforms
Mpv.net
🎞 mpv.net is a modern media player for Windows that works just like mpv.
Stars: ✭ 737 (+637%)
Mutual labels: winforms
Bizhawk
BizHawk is a multi-system emulator written in C#. BizHawk provides nice features for casual gamers such as full screen, and joypad support in addition to full rerecording and debugging tools for all system cores.
Stars: ✭ 1,138 (+1038%)
Mutual labels: winforms
Reactivemvvm
Cross-platform ReactiveUI sample app built for a talk at MSK .NET conf.
Stars: ✭ 94 (-6%)
Mutual labels: winforms
Quick Screen Recorder
Lightweight desktop screen recorder for Windows.
Stars: ✭ 80 (-20%)
Mutual labels: winforms
musicDecryptor
酷狗、网易等音乐缓存文件转mp3
以前写过kgtemp文件转mp3工具,正好当前又有网易云音乐缓存文件需求,因此就在原来小工具的基础上做了一点修改,增加了对网易云音乐的支持,并简单调整了下代码结构,方便后续增加其他音乐软件的支持。 PS:写惯了java,再写c#好别扭。。
工具使用介绍
启动程序,
- 首先,设置输入目录,也就是解密后的文件存放在哪里
- 然后将酷狗或者网易的缓存文件 or 整个文件夹,拖入到程序即可
FAQ
网易云音乐的缓存目录
打开设置 -- 下载设置 - 缓存目录就是了
酷狗缓存目录
如图,在设置--下载设置里
工具代码简要说明
类图
ICacheDecrypt
我们定义一个解码接口ICacheDecrypt,实现将缓存文件字节流转换为mp3字节流。
/// <summary>
/// 解密接口
/// </summary>
public interface ICacheDecrypt
{
string AcceptableExtension
{
get;
}
bool isAcceptable(string cacheFile);
/// <summary>
/// 解密文件
/// </summary>
/// <param name="cacheFile">缓存文件</param>
/// <returns>解密后二进制数据</returns>
byte[] Decrypt(string cacheFile);
/// <summary>
/// 解密文件
/// </summary>
/// <param name="cacheFileData">缓存文件数据</param>
/// <returns></returns>
byte[] Decrypt(byte[] cacheFileData);
/// <summary>
/// 解密文件
/// </summary>
/// <param name="cacheFile">cache文件</param>
/// <param name="decodedFile">解密后文件</param>
void Decrypt(string cacheFile,string decodedFile);
}
BaseCacheDecrypt
然后,实现一个默认的抽象类BaseCacheDecrypt,实现一些公共的东西,具体的转码工作让子类去实现:
public abstract class BaseCacheDecrypt : ICacheDecrypt
{
protected string currentCacheFile;
public abstract string AcceptableExtension
{
get;
}
public abstract byte[] Decrypt(byte[] cacheFileData);
public byte[] Decrypt(string cacheFile)
{
currentCacheFile = cacheFile;
return Decrypt(File.ReadAllBytes(cacheFile));
}
public void Decrypt(string cacheFile, string decodedFile)
{
File.WriteAllBytes(decodedFile, Decrypt(cacheFile));
}
public bool isAcceptable(string cacheFile)
{
return cacheFile.EndsWith(AcceptableExtension);
}
}
NetMusicCacheDecrypt
然后,分别实现酷狗和网易云音乐的解码工作,酷狗的上次已经写了如何解码,这里只贴网易的,解码很简单,异或0xa3就可以了。网易音乐在测试时发现好多mp3没有ID3信息,经过观察发现缓存文件名里包含歌曲的id信息,因此可以根据这个id信息去抓取歌曲网页,解析出歌手和歌曲名称,然后写入到ID3里,这里ID3的读写采用了GitHub上的一个开源库
/// <summary>
/// 网易云缓存解密
/// </summary>
public class NetMusicCacheDecrypt : BaseCacheDecrypt
{
public override string AcceptableExtension
{
get
{
return ".uc";
}
}
string cut(string str,string start,string end)
{
var startIndex = str.IndexOf(start);
if (startIndex == -1)
{
return "";
}
startIndex += start.Length;
var endIndex = str.IndexOf(end, startIndex);
if (endIndex == -1)
{
return "";
}
return str.Substring(startIndex, endIndex - startIndex);
}
public override byte[] Decrypt(byte[] cacheFileData)
{
for (var i = 0; i < cacheFileData.Length; i++)
{
// 异或0xa3
cacheFileData[i] ^= 0xa3;
}
var fileName = new FileInfo(currentCacheFile).Name;
var songId = fileName.Substring(0, fileName.IndexOf("-"));
var html = HttpHelper.SendGet("http://music.163.com/song?id=" + songId);
if (html.Length > 0)
{
var title = cut(html, "<title>", "</title>").Trim();
var tempFile = currentCacheFile+ Guid.NewGuid().ToString();
File.WriteAllBytes(tempFile, cacheFileData);
Track theTrack = new Track(tempFile);
// 父亲写的散文诗(时光版) - 许飞 - 单曲 - 网易云音乐
theTrack.Artist = cut(title, "-", "-").Trim();
theTrack.Title = title.Substring(0, title.IndexOf("-")).Trim();
// Save modifications on the disc
theTrack.Save();
cacheFileData = File.ReadAllBytes(tempFile);
File.Delete(tempFile);
}
return cacheFileData;
}
}
接着介绍核心的Decryptor,实现转码的调度,这里的思路就是将所有的解码器放到一个list里,当一个文件过来的时候,遍历所有解码器,如果accetbale,就处理,否则跳过。 两个主要工作:
- 加载所有的BaseCacheDecrypt
- 进行解码工作
加载所有的BaseCacheDecrypt
两种方法,一是自己实例化,一是使用反射,这里当然用反射了:)
private Decryptor()
{
}
public static Decryptor Instance
{
get
{
return Holder.decryptor;
}
}
static class Holder
{
public static Decryptor decryptor = Load();
/// <summary>
/// 从当前Assembly加载
/// </summary>
/// <returns></returns>
private static Decryptor Load()
{
Assembly assembly = Assembly.GetExecutingAssembly();
List<Type> hostTypes = new List<Type>();
foreach (var type in assembly.GetExportedTypes())
{
//确定type为类并且继承自(实现)IMyInstance
if (type.IsClass && typeof(BaseCacheDecrypt).IsAssignableFrom(type) && !type.IsAbstract)
hostTypes.Add(type);
}
Decryptor decryptor = new Decryptor();
foreach (var type in hostTypes)
{
ICacheDecrypt instance = (ICacheDecrypt)Activator.CreateInstance(type);
decryptor.cacheDecryptors.Add(instance);
}
return decryptor;
}
}
Decryptor通过单例模式对外提供调用。
进行解码
判断拖入的是文件夹还是文件,文件夹的话遍历子文件,依次处理。解码方式就是钢说的,遍历decryptors,如果支持就解码。 解码完后,读取ID3信息,对文件进行重命名。
public int Process(string path)
{
int success = 0;
if (Directory.Exists(path))//如果是文件夹
{
DirectoryInfo dinfo = new DirectoryInfo(path);//实例化一个DirectoryInfo对象
foreach (FileInfo fs in dinfo.GetFiles()) //查找.kgtemp文件
{
ProcessFile(fs.FullName);
success++;
}
}
else
{
ProcessFile(path);
success = 1;
}
return success;
}
private string GetCleanFileName(string fileName)
{
StringBuilder rBuilder = new StringBuilder(fileName);
foreach (char rInvalidChar in Path.GetInvalidFileNameChars())
rBuilder.Replace(rInvalidChar.ToString(), string.Empty);
return rBuilder.ToString();
}
private string GetTargetFileName(string fileName)
{
var fileinfo = new FileInfo(fileName);
var rawName = fileinfo.Name.Substring(0, fileinfo.Name.IndexOf("."));
return TargetDirectory + Path.DirectorySeparatorChar + rawName + ".mp3";
}
void ProcessFile(string fileName)
{
_logger.Info("开始处理" + fileName);
try
{
foreach (var decryptor in cacheDecryptors)
{
if (decryptor.isAcceptable(fileName))
{
var targetName = TargetDirectory + Path.DirectorySeparatorChar + new FileInfo(fileName).Name + ".mp3";
decryptor.Decrypt(fileName, targetName);
// 重命名
if (AutoRename)
{
var mp3 = ID3Helper.ReadMp3(targetName);
if (mp3.Title.Length > 0)
{
string realFileName = GetTargetFileName(GetCleanFileName(mp3.Title + "-" + mp3.Artist + ".mp3"));
_logger.Info("重命名" + realFileName);
if (File.Exists(realFileName))
{
File.Delete(realFileName);
}
File.Move(targetName, realFileName);
}
}
}
}
_logger.Info(fileName + "处理完成");
}
catch(Exception ex)
{
_logger.Error(fileName + "出现异常" + ex.Message);
}
}
Note that the project description data, including the texts, logos, images, and/or trademarks,
for each open source project belongs to its rightful owner.
If you wish to add or remove any projects, please contact us at [email protected].