替换 SourceAppUserModelId 为 PlayerId 并新增 SongId

将 SongInfo 中的 SourceAppUserModelId 属性替换为 PlayerId,新增可选属性 SongId 以支持更精确的歌曲标识。
更新了相关服务和方法的参数签名,增加对 SongId 的支持,包括 SearchSmartlyAsync 和 SearchSingleAsync 方法。
调整了 MediaSessionsService 的逻辑,支持不同播放器的 SongId 处理。
优化了代码的灵活性和可扩展性,便于处理多播放器和歌曲标识。
This commit is contained in:
Zhe Fang
2025-10-10 11:29:50 -04:00
parent ea038c9c56
commit e467ab9c73
7 changed files with 63 additions and 50 deletions

View File

@@ -21,11 +21,14 @@ namespace BetterLyrics.WinUI3.Models
public partial double? DurationMs { get; set; }
[ObservableProperty]
public partial string? SourceAppUserModelId { get; set; } = null;
public partial string? PlayerId { get; set; } = null;
[ObservableProperty]
public partial string Title { get; set; }
[ObservableProperty]
public partial string? SongId { get; set; } = null;
public SongInfo() { }
}
}

View File

@@ -11,7 +11,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
public interface ILyricsSearchService
{
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token);
Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
}

View File

@@ -91,7 +91,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
}
}
public async Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
public async Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
{
var lyricsSearchResult = new LyricsSearchResult();
@@ -123,7 +123,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var targetProvider = found.LyricsSearchProvider;
if (targetProvider != null)
{
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, token);
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, songId, token);
}
}
@@ -134,7 +134,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
continue;
}
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, token);
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, null, token);
if (lyricsSearchResult.IsFound)
{
@@ -151,13 +151,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var results = new List<LyricsSearchResult>();
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
{
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, token);
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, null, token);
results.Add(searchResult);
}
return results;
}
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, CancellationToken token)
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
{
var lyricsSearchResult = new LyricsSearchResult
{
@@ -200,13 +200,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
break;
case LyricsSearchProvider.QQ:
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.QQMusic);
break;
case LyricsSearchProvider.Kugou:
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Kugou);
break;
case LyricsSearchProvider.Netease:
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Netease);
break;
case LyricsSearchProvider.AmllTtmlDb:
lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist);
@@ -436,7 +436,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
return lyricsSearchResult;
}
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, string? songId, Searchers searchers)
{
var lyricsSearchResult = new LyricsSearchResult();
@@ -457,15 +457,23 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
break;
}
var result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
{
DurationMs = durationMs,
Album = album,
Artists = [artist],
Title = title,
}
);
ISearchResult? result;
if (searchers == Searchers.Netease && songId != null)
{
result = new NeteaseSearchResult(title, [artist], album, null, durationMs, songId);
}
else
{
result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
{
DurationMs = durationMs,
Album = album,
Artists = [artist],
Title = title,
}
);
}
if (result is QQMusicSearchResult qqResult)
{

View File

@@ -34,7 +34,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
}
byte[]? bytes = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
SongInfo?.SourceAppUserModelId ?? "",
SongInfo?.PlayerId ?? "",
_cachedSongInfo.Title,
_cachedSongInfo.Artist,
_cachedSongInfo?.Album ?? string.Empty,

View File

@@ -156,11 +156,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
SongInfo.SourceAppUserModelId ?? "",
SongInfo.PlayerId ?? "",
SongInfo.Title,
SongInfo.Artist,
SongInfo.Album ?? "",
SongInfo.DurationMs ?? 0,
SongInfo.SongId,
token
), token);
if (token.IsCancellationRequested) return;

View File

@@ -284,21 +284,21 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (!_mediaManager.IsStarted) return;
if (mediaSession == null) return;
string id = mediaSession.Id;
string sessionId = mediaSession.Id;
var desiredSession = GetCurrentSession();
//RecordMediaSourceProviderInfo(mediaSession);
if (mediaSession != desiredSession) return;
if (!IsMediaSourceEnabled(id))
if (!IsMediaSourceEnabled(sessionId))
{
_cachedSongInfo = null;
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
if (id == Constants.PlayerID.LXMusic)
if (sessionId == Constants.PlayerID.LXMusic)
{
StopSSE();
}
@@ -313,38 +313,39 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
currentMediaSourceProviderInfo?.PositionOffset = 0;
}
if (id == Constants.PlayerID.AppleMusic || id == Constants.PlayerID.AppleMusicAlternative)
{
string fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
string fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
string fixedArtist = mediaProperties.Artist;
string fixedAlbum = mediaProperties.AlbumTitle;
string? songId = null;
_cachedSongInfo = new SongInfo
{
Title = mediaProperties.Title,
Artist = fixedArtist,
Album = fixedAlbum,
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
SourceAppUserModelId = id,
};
}
else
if (sessionId == Constants.PlayerID.AppleMusic || sessionId == Constants.PlayerID.AppleMusicAlternative)
{
_cachedSongInfo = new SongInfo
fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
}
else if (sessionId == Constants.PlayerID.NetEaseCloudMusic)
{
songId = mediaProperties.Genres.FirstOrDefault()?.Replace("NCM-", "");
if (songId != null && songId.Length != 10)
{
Title = mediaProperties.Title,
Artist = mediaProperties.Artist,
Album = mediaProperties.AlbumTitle,
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
SourceAppUserModelId = id,
};
songId = null;
}
}
_cachedSongInfo = new SongInfo
{
Title = mediaProperties.Title,
Artist = fixedArtist,
Album = fixedAlbum,
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
PlayerId = sessionId,
SongId = songId
};
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
if (id == Constants.PlayerID.LXMusic)
if (sessionId == Constants.PlayerID.LXMusic)
{
StartSSE();
}
@@ -353,7 +354,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
StopSSE();
}
if (id == Constants.PlayerID.LXMusic && _lxMusicAlbumArtBytes != null)
if (sessionId == Constants.PlayerID.LXMusic && _lxMusicAlbumArtBytes != null)
{
_SMTCAlbumArtBytes = _lxMusicAlbumArtBytes;
}
@@ -507,7 +508,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
{
if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
if (_cachedSongInfo?.PlayerId == Constants.PlayerID.LXMusic)
{
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
if (data.ValueKind == JsonValueKind.Number)

View File

@@ -111,7 +111,7 @@ namespace BetterLyrics.WinUI3.ViewModels
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
{
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.SourceAppUserModelId)?.FirstOrDefault();
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.PlayerId)?.FirstOrDefault();
if (_mediaSessionsService.Position.TotalSeconds <= 1 && current?.ResetPositionOffsetOnSongChanged == true)
{
current.PositionOffset = 0;