feat: Enhanced song matching logic (NetEaseMusic).

This commit is contained in:
real-zony 2022-09-22 17:49:54 +08:00
parent c583a9c278
commit 140043db79
10 changed files with 49 additions and 12 deletions

View File

@ -8,6 +8,8 @@ using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NAudio.Wave;
using TagLib.Mpeg;
using ZonyLrcTools.Cli.Config;
using ZonyLrcTools.Cli.Infrastructure;
using ZonyLrcTools.Cli.Infrastructure.Album;
@ -17,6 +19,7 @@ using ZonyLrcTools.Cli.Infrastructure.IO;
using ZonyLrcTools.Cli.Infrastructure.Lyric;
using ZonyLrcTools.Cli.Infrastructure.Tag;
using ZonyLrcTools.Cli.Infrastructure.Threading;
using File = System.IO.File;
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 result = (await Task.WhenAll(warpTaskList))
.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} 个音乐文件的标签信息。");
@ -173,7 +180,7 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
{
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)!,
$"{Path.GetFileNameWithoutExtension(info.FilePath)}.lrc");

View File

@ -51,7 +51,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Album.NetEase
var songDetailJsonStr = await _warpHttpClient.GetAsync(
GetMusicInfoApi,
new GetSongDetailsRequest(searchResult.GetFirstMatchSongId(songName)),
new GetSongDetailsRequest(searchResult.GetFirstMatchSongId(songName, null)),
_defaultOption);
var url = JObject.Parse(songDetailJsonStr).SelectToken("$.songs[0].album.picUrl")?.Value<string>();

View File

@ -12,8 +12,9 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
/// </summary>
/// <param name="songName">歌曲的名称。</param>
/// <param name="artist">歌曲的作者。</param>
/// <param name="duration">歌曲的时长。</param>
/// <returns>歌曲的歌词数据对象。</returns>
ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist);
ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist, long? duration = null);
/// <summary>
/// 下载器的名称。

View File

@ -16,10 +16,11 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
/// </summary>
/// <param name="songName">歌曲名称。</param>
/// <param name="artist">歌曲作者/艺术家。</param>
/// <param name="duration">歌曲的时长。</param>
/// <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);
var downloadDataBytes = await DownloadDataAsync(args);
return await GenerateLyricAsync(downloadDataBytes, args);

View File

@ -6,10 +6,13 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric
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;
Artist = artist;
Duration = duration;
}
}
}

View File

@ -49,7 +49,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase.JsonModel
Type = 1;
Offset = 0;
IsTotal = true;
Limit = 5;
Limit = 10;
}
public SongSearchRequest(string musicName, string artistName) : this()

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
@ -10,10 +11,20 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase.JsonModel
[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);
return item?.Id ?? Items.SongItems[0].Id;
var perfectMatch = Items.SongItems.FirstOrDefault(x => x.Name == songName);
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>
[JsonProperty("album")]
public SongAlbumModel Album { get; set; }
/// <summary>
/// 歌曲的实际长度。
/// </summary>
[JsonProperty("duration")]
public long Duration { get; set; }
}
public class SongArtistModel

View File

@ -48,7 +48,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric.NetEase
var lyricResponse = await _warpHttpClient.GetAsync(
NetEaseGetLyricUrl,
new GetLyricRequest(searchResult.GetFirstMatchSongId(args.SongName)),
new GetLyricRequest(searchResult.GetFirstMatchSongId(args.SongName, args.Duration)),
msg => msg.Headers.Referrer = new Uri(NetEaseRequestReferer));
return Encoding.UTF8.GetBytes(lyricResponse);

View File

@ -1,3 +1,5 @@
using System;
namespace ZonyLrcTools.Cli.Infrastructure
{
/// <summary>
@ -10,6 +12,11 @@ namespace ZonyLrcTools.Cli.Infrastructure
/// </summary>
public string FilePath { get; }
/// <summary>
/// 歌曲的实际歌曲长度。
/// </summary>
public long? TotalTime { get; set; }
/// <summary>
/// 歌曲的名称。
/// </summary>

View File

@ -10,6 +10,7 @@
<PackageReference Include="McMaster.Extensions.Hosting.CommandLine" Version="4.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<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="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Refit" Version="6.3.2" />