mirror of
https://github.com/real-zony/ZonyLrcToolsX.git
synced 2025-07-01 20:30:41 +00:00
feat: Enhanced song matching logic (NetEaseMusic).
This commit is contained in:
parent
c583a9c278
commit
140043db79
@ -8,6 +8,8 @@ using System.Threading.Tasks;
|
|||||||
using McMaster.Extensions.CommandLineUtils;
|
using McMaster.Extensions.CommandLineUtils;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using NAudio.Wave;
|
||||||
|
using TagLib.Mpeg;
|
||||||
using ZonyLrcTools.Cli.Config;
|
using ZonyLrcTools.Cli.Config;
|
||||||
using ZonyLrcTools.Cli.Infrastructure;
|
using ZonyLrcTools.Cli.Infrastructure;
|
||||||
using ZonyLrcTools.Cli.Infrastructure.Album;
|
using ZonyLrcTools.Cli.Infrastructure.Album;
|
||||||
@ -17,6 +19,7 @@ using ZonyLrcTools.Cli.Infrastructure.IO;
|
|||||||
using ZonyLrcTools.Cli.Infrastructure.Lyric;
|
using ZonyLrcTools.Cli.Infrastructure.Lyric;
|
||||||
using ZonyLrcTools.Cli.Infrastructure.Tag;
|
using ZonyLrcTools.Cli.Infrastructure.Tag;
|
||||||
using ZonyLrcTools.Cli.Infrastructure.Threading;
|
using ZonyLrcTools.Cli.Infrastructure.Threading;
|
||||||
|
using File = System.IO.File;
|
||||||
|
|
||||||
namespace ZonyLrcTools.Cli.Commands.SubCommand
|
namespace ZonyLrcTools.Cli.Commands.SubCommand
|
||||||
{
|
{
|
||||||
@ -131,7 +134,11 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
|
|||||||
var warpTaskList = files.Select(file => warpTask.RunAsync(() => Task.Run(async () => await _tagLoader.LoadTagAsync(file))));
|
var warpTaskList = files.Select(file => warpTask.RunAsync(() => Task.Run(async () => await _tagLoader.LoadTagAsync(file))));
|
||||||
var result = (await Task.WhenAll(warpTaskList))
|
var result = (await Task.WhenAll(warpTaskList))
|
||||||
.Where(m => m != null)
|
.Where(m => m != null)
|
||||||
.Where(m => !string.IsNullOrEmpty(m.Name) || !string.IsNullOrEmpty(m.Artist));
|
.Where(m => !string.IsNullOrEmpty(m.Name) || !string.IsNullOrEmpty(m.Artist))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Load music total time info.
|
||||||
|
result.Foreach(m => { m.TotalTime = (long?)new AudioFileReader(m.FilePath).TotalTime.TotalMilliseconds; });
|
||||||
|
|
||||||
_logger.LogInformation($"已成功加载 {files.Count} 个音乐文件的标签信息。");
|
_logger.LogInformation($"已成功加载 {files.Count} 个音乐文件的标签信息。");
|
||||||
|
|
||||||
@ -173,7 +180,7 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var lyric = await downloader.DownloadAsync(info.Name, info.Artist);
|
var lyric = await downloader.DownloadAsync(info.Name, info.Artist, info.TotalTime);
|
||||||
var lyricFilePath = Path.Combine(Path.GetDirectoryName(info.FilePath)!,
|
var lyricFilePath = Path.Combine(Path.GetDirectoryName(info.FilePath)!,
|
||||||
$"{Path.GetFileNameWithoutExtension(info.FilePath)}.lrc");
|
$"{Path.GetFileNameWithoutExtension(info.FilePath)}.lrc");
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Album.NetEase
|
|||||||
|
|
||||||
var songDetailJsonStr = await _warpHttpClient.GetAsync(
|
var songDetailJsonStr = await _warpHttpClient.GetAsync(
|
||||||
GetMusicInfoApi,
|
GetMusicInfoApi,
|
||||||
new GetSongDetailsRequest(searchResult.GetFirstMatchSongId(songName)),
|
new GetSongDetailsRequest(searchResult.GetFirstMatchSongId(songName, null)),
|
||||||
_defaultOption);
|
_defaultOption);
|
||||||
|
|
||||||
var url = JObject.Parse(songDetailJsonStr).SelectToken("$.songs[0].album.picUrl")?.Value<string>();
|
var url = JObject.Parse(songDetailJsonStr).SelectToken("$.songs[0].album.picUrl")?.Value<string>();
|
||||||
|
@ -12,8 +12,9 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="songName">歌曲的名称。</param>
|
/// <param name="songName">歌曲的名称。</param>
|
||||||
/// <param name="artist">歌曲的作者。</param>
|
/// <param name="artist">歌曲的作者。</param>
|
||||||
|
/// <param name="duration">歌曲的时长。</param>
|
||||||
/// <returns>歌曲的歌词数据对象。</returns>
|
/// <returns>歌曲的歌词数据对象。</returns>
|
||||||
ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist);
|
ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist, long? duration = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载器的名称。
|
/// 下载器的名称。
|
||||||
|
@ -16,10 +16,11 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="songName">歌曲名称。</param>
|
/// <param name="songName">歌曲名称。</param>
|
||||||
/// <param name="artist">歌曲作者/艺术家。</param>
|
/// <param name="artist">歌曲作者/艺术家。</param>
|
||||||
|
/// <param name="duration">歌曲的时长。</param>
|
||||||
/// <returns>下载完成的歌曲数据。</returns>
|
/// <returns>下载完成的歌曲数据。</returns>
|
||||||
public virtual async ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist)
|
public virtual async ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist, long? duration = null)
|
||||||
{
|
{
|
||||||
var args = new LyricDownloaderArgs(songName, artist);
|
var args = new LyricDownloaderArgs(songName, artist, duration ?? 0);
|
||||||
await ValidateAsync(args);
|
await ValidateAsync(args);
|
||||||
var downloadDataBytes = await DownloadDataAsync(args);
|
var downloadDataBytes = await DownloadDataAsync(args);
|
||||||
return await GenerateLyricAsync(downloadDataBytes, args);
|
return await GenerateLyricAsync(downloadDataBytes, args);
|
||||||
|
@ -6,10 +6,13 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
|
|||||||
|
|
||||||
public string Artist { get; set; }
|
public string Artist { get; set; }
|
||||||
|
|
||||||
public LyricDownloaderArgs(string songName, string artist)
|
public long Duration { get; set; }
|
||||||
|
|
||||||
|
public LyricDownloaderArgs(string songName, string artist, long duration)
|
||||||
{
|
{
|
||||||
SongName = songName;
|
SongName = songName;
|
||||||
Artist = artist;
|
Artist = artist;
|
||||||
|
Duration = duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase.JsonModel
|
|||||||
Type = 1;
|
Type = 1;
|
||||||
Offset = 0;
|
Offset = 0;
|
||||||
IsTotal = true;
|
IsTotal = true;
|
||||||
Limit = 5;
|
Limit = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SongSearchRequest(string musicName, string artistName) : this()
|
public SongSearchRequest(string musicName, string artistName) : this()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -10,10 +11,20 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase.JsonModel
|
|||||||
|
|
||||||
[JsonProperty("code")] public int StatusCode { get; set; }
|
[JsonProperty("code")] public int StatusCode { get; set; }
|
||||||
|
|
||||||
public int GetFirstMatchSongId(string songName)
|
public int GetFirstMatchSongId(string songName, long? duration)
|
||||||
{
|
{
|
||||||
var item = Items.SongItems.FirstOrDefault(x => x.Name == songName);
|
var perfectMatch = Items.SongItems.FirstOrDefault(x => x.Name == songName);
|
||||||
return item?.Id ?? Items.SongItems[0].Id;
|
if (perfectMatch != null)
|
||||||
|
{
|
||||||
|
return perfectMatch.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration is null or 0)
|
||||||
|
{
|
||||||
|
return Items.SongItems.First().Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Items.SongItems.OrderBy(t => Math.Abs(t.Duration - duration.Value)).First().Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +60,12 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase.JsonModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("album")]
|
[JsonProperty("album")]
|
||||||
public SongAlbumModel Album { get; set; }
|
public SongAlbumModel Album { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 歌曲的实际长度。
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("duration")]
|
||||||
|
public long Duration { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SongArtistModel
|
public class SongArtistModel
|
||||||
|
@ -48,7 +48,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase
|
|||||||
|
|
||||||
var lyricResponse = await _warpHttpClient.GetAsync(
|
var lyricResponse = await _warpHttpClient.GetAsync(
|
||||||
NetEaseGetLyricUrl,
|
NetEaseGetLyricUrl,
|
||||||
new GetLyricRequest(searchResult.GetFirstMatchSongId(args.SongName)),
|
new GetLyricRequest(searchResult.GetFirstMatchSongId(args.SongName, args.Duration)),
|
||||||
msg => msg.Headers.Referrer = new Uri(NetEaseRequestReferer));
|
msg => msg.Headers.Referrer = new Uri(NetEaseRequestReferer));
|
||||||
|
|
||||||
return Encoding.UTF8.GetBytes(lyricResponse);
|
return Encoding.UTF8.GetBytes(lyricResponse);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace ZonyLrcTools.Cli.Infrastructure
|
namespace ZonyLrcTools.Cli.Infrastructure
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -10,6 +12,11 @@ namespace ZonyLrcTools.Cli.Infrastructure
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string FilePath { get; }
|
public string FilePath { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 歌曲的实际歌曲长度。
|
||||||
|
/// </summary>
|
||||||
|
public long? TotalTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 歌曲的名称。
|
/// 歌曲的名称。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="4.0.1" />
|
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="4.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||||
|
<PackageReference Include="NAudio" Version="2.1.0" />
|
||||||
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="2.2.0" />
|
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Refit" Version="6.3.2" />
|
<PackageReference Include="Refit" Version="6.3.2" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user