diff --git a/src/ZonyLrcTools.Cli/Commands/SubCommand/DownloadCommand.cs b/src/ZonyLrcTools.Cli/Commands/SubCommand/DownloadCommand.cs index 28271b1..2984dfb 100644 --- a/src/ZonyLrcTools.Cli/Commands/SubCommand/DownloadCommand.cs +++ b/src/ZonyLrcTools.Cli/Commands/SubCommand/DownloadCommand.cs @@ -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"); diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Album/NetEase/NetEaseAlbumDownloader.cs b/src/ZonyLrcTools.Cli/Infrastructure/Album/NetEase/NetEaseAlbumDownloader.cs index f1e6583..0202118 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Album/NetEase/NetEaseAlbumDownloader.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Album/NetEase/NetEaseAlbumDownloader.cs @@ -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(); diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/ILyricDownloader.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/ILyricDownloader.cs index a17a634..78d5abe 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/ILyricDownloader.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/ILyricDownloader.cs @@ -12,8 +12,9 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric /// /// 歌曲的名称。 /// 歌曲的作者。 + /// 歌曲的时长。 /// 歌曲的歌词数据对象。 - ValueTask DownloadAsync(string songName, string artist); + ValueTask DownloadAsync(string songName, string artist, long? duration = null); /// /// 下载器的名称。 diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloader.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloader.cs index e701dba..32bf3fc 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloader.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloader.cs @@ -16,10 +16,11 @@ namespace ZonyLrcTools.Cli.Infrastructure.Lyric /// /// 歌曲名称。 /// 歌曲作者/艺术家。 + /// 歌曲的时长。 /// 下载完成的歌曲数据。 - public virtual async ValueTask DownloadAsync(string songName, string artist) + public virtual async ValueTask 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); diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloaderArgs.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloaderArgs.cs index 26adb7a..e2f0124 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloaderArgs.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/LyricDownloaderArgs.cs @@ -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; } } } \ No newline at end of file diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchRequest.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchRequest.cs index 0056812..3c694bd 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchRequest.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchRequest.cs @@ -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() diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchResponse.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchResponse.cs index db3495d..cafffc5 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchResponse.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/JsonModel/SongSearchResponse.cs @@ -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 /// [JsonProperty("album")] public SongAlbumModel Album { get; set; } + + /// + /// 歌曲的实际长度。 + /// + [JsonProperty("duration")] + public long Duration { get; set; } } public class SongArtistModel diff --git a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/NetEaseLyricDownloader.cs b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/NetEaseLyricDownloader.cs index 29862f7..4461351 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/NetEaseLyricDownloader.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/Lyric/NetEase/NetEaseLyricDownloader.cs @@ -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); diff --git a/src/ZonyLrcTools.Cli/Infrastructure/MusicInfo.cs b/src/ZonyLrcTools.Cli/Infrastructure/MusicInfo.cs index 6308bc7..a0cb5b9 100644 --- a/src/ZonyLrcTools.Cli/Infrastructure/MusicInfo.cs +++ b/src/ZonyLrcTools.Cli/Infrastructure/MusicInfo.cs @@ -1,3 +1,5 @@ +using System; + namespace ZonyLrcTools.Cli.Infrastructure { /// @@ -10,6 +12,11 @@ namespace ZonyLrcTools.Cli.Infrastructure /// public string FilePath { get; } + /// + /// 歌曲的实际歌曲长度。 + /// + public long? TotalTime { get; set; } + /// /// 歌曲的名称。 /// diff --git a/src/ZonyLrcTools.Cli/ZonyLrcTools.Cli.csproj b/src/ZonyLrcTools.Cli/ZonyLrcTools.Cli.csproj index 60b265d..5e377a0 100644 --- a/src/ZonyLrcTools.Cli/ZonyLrcTools.Cli.csproj +++ b/src/ZonyLrcTools.Cli/ZonyLrcTools.Cli.csproj @@ -10,6 +10,7 @@ +