Skip to content

Commit 00b55f4

Browse files
committed
refactor(metadata): replace IdSharpMetaTag with NativeId3MetaTag and remove IdSharp dependency
- Migrated from `IdSharpMetaTag` to `NativeId3MetaTag` for improved .mp3 metadata handling. - Removed `IdSharp` dependencies (`IdSharp.Common` and `IdSharp.Tagging`) across the project. - Updated `DirectoryProcessorToStagingService` to use `NativeId3MetaTag`. - Adjusted tests to reflect the metadata plugin migration. - Cleaned up unused `AuralizeBlazor` dependency in the Blazor project.
1 parent c29bc3f commit 00b55f4

19 files changed

Lines changed: 342 additions & 362 deletions

File tree

.github/docker/Dockerfile.container-scan

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
FROM mcr.microsoft.com/dotnet/aspnet:10.0.4
1+
ARG DOTNET_ASPNET_IMAGE=mcr.microsoft.com/dotnet/aspnet:10.0
2+
FROM ${DOTNET_ASPNET_IMAGE}
23

34
WORKDIR /app
45

.github/workflows/sca-container-scan.yml

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ jobs:
4545
permissions:
4646
contents: read
4747
security-events: write
48+
env:
49+
SCAN_BASE_IMAGE: mcr.microsoft.com/dotnet/aspnet:10.0
4850

4951
steps:
5052
- name: Checkout repository
@@ -58,18 +60,47 @@ jobs:
5860
- name: Publish application for scanning
5961
run: dotnet publish src/Melodee.Blazor/Melodee.Blazor.csproj -c Release -o scan/publish --self-contained false -p:PublishTrimmed=false
6062

61-
- name: Set up Docker Buildx
62-
uses: docker/setup-buildx-action@v3
63+
- name: Pull Docker base image for scanning
64+
run: |
65+
set -euo pipefail
66+
67+
for attempt in 1 2 3 4 5; do
68+
if docker pull "$SCAN_BASE_IMAGE"; then
69+
exit 0
70+
fi
71+
72+
delay=$((attempt * 20))
73+
echo "Base image pull failed on attempt ${attempt}; retrying in ${delay}s..."
74+
sleep "$delay"
75+
done
76+
77+
docker pull "$SCAN_BASE_IMAGE"
6378
6479
- name: Build Docker image for scanning
65-
uses: docker/build-push-action@v5
66-
with:
67-
context: .
68-
file: .github/docker/Dockerfile.container-scan
69-
load: true
70-
tags: melodee:latest
71-
cache-from: type=gha
72-
cache-to: type=gha,mode=max
80+
run: |
81+
set -euo pipefail
82+
83+
for attempt in 1 2 3; do
84+
if docker build \
85+
--pull=false \
86+
--build-arg DOTNET_ASPNET_IMAGE="$SCAN_BASE_IMAGE" \
87+
-f .github/docker/Dockerfile.container-scan \
88+
-t melodee:latest \
89+
.; then
90+
exit 0
91+
fi
92+
93+
delay=$((attempt * 20))
94+
echo "Docker image build failed on attempt ${attempt}; retrying in ${delay}s..."
95+
sleep "$delay"
96+
done
97+
98+
docker build \
99+
--pull=false \
100+
--build-arg DOTNET_ASPNET_IMAGE="$SCAN_BASE_IMAGE" \
101+
-f .github/docker/Dockerfile.container-scan \
102+
-t melodee:latest \
103+
.
73104
74105
- name: Run Trivy Vulnerability Scanner
75106
uses: aquasecurity/trivy-action@master

Directory.Build.props

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<Project>
22
<PropertyGroup>
33
<AllowMissingPrunePackageData>true</AllowMissingPrunePackageData>
4-
<!-- Suppress NU1902 for SixLabors.ImageSharp (v3.1.10) which is a transitive dependency of IdSharp.Tagging.
5-
Melodee no longer directly references or uses ImageSharp; all image processing is done via SkiaSharp.
6-
This warning cannot be resolved without upgrading or replacing IdSharp.Tagging. -->
7-
<NoWarn>$(NoWarn);NU1902</NoWarn>
84
</PropertyGroup>
95
</Project>

Directory.Packages.props

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<PackageVersion Include="Asp.Versioning.Http" Version="10.0.0" />
88
<PackageVersion Include="Asp.Versioning.Mvc" Version="10.0.0" />
99
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="10.0.0" />
10-
<PackageVersion Include="AuralizeBlazor" Version="3.0.4" />
1110
<PackageVersion Include="BCrypt.Net-Next" Version="4.2.0" />
1211
<PackageVersion Include="Blazored.SessionStorage" Version="2.4.0" />
1312
<PackageVersion Include="bunit" Version="2.7.2" />
@@ -31,14 +30,13 @@
3130
<PackageVersion Include="HtmlAgilityPack" Version="1.12.4" />
3231
<PackageVersion Include="HtmlSanitizer" Version="9.1.923-beta" />
3332
<PackageVersion Include="IdGen" Version="3.0.7" />
34-
<PackageVersion Include="IdSharp.Common" Version="2.0.3" />
35-
<PackageVersion Include="IdSharp.Tagging" Version="2.0.3" />
3633
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.4" />
3734
<PackageVersion Include="Jint" Version="4.10.0" />
3835
<PackageVersion Include="K4os.Hash.xxHash" Version="1.0.8" />
3936
<PackageVersion Include="LiteDB" Version="5.0.21" />
4037
<PackageVersion Include="Mapster" Version="10.0.8" />
4138
<PackageVersion Include="Markdig" Version="1.3.0" />
39+
<PackageVersion Include="MessagePack" Version="3.1.7" />
4240
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.9" />
4341
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.9" />
4442
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.3.11" />
@@ -121,4 +119,4 @@
121119
<PackageVersion Include="z440.atl.core" Version="7.15.3" />
122120
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
123121
</ItemGroup>
124-
</Project>
122+
</Project>

benchmarks/Melodee.Benchmarks/Melodee.Benchmarks.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
<PackageReference Include="BenchmarkDotNet" />
1818
<PackageReference Include="DecentDB.AdoNet" />
1919
<PackageReference Include="NBomber" />
20+
<PackageReference Include="MessagePack">
21+
<PrivateAssets>all</PrivateAssets>
22+
</PackageReference>
2023
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
2124
<PackageReference Include="FluentAssertions" />
2225
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />

docs/_posts/2026-05-24-melodee-2-1-0-released.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Melodee 2.1.0 is here! This release focuses on performance, developer experience
1313
## What's New in 2.1.0
1414

1515
### SkiaSharp Image Processing
16-
All image processing has migrated from `SixLabors.ImageSharp` to `SkiaSharp`, replacing the legacy library with a more performant and actively maintained alternative.
16+
All image processing has migrated to `SkiaSharp`, replacing the legacy library with a more performant and actively maintained alternative.
1717

1818
- New `IImageProcessor` abstraction for decode, encode, resize, format detection, and hash generation
1919
- Clean dependency injection throughout services, Blazor components, CLI commands, and tests

docs/pages/changelog.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4040
- MusicBrainz query probes now keep the broad ordered first-row existence
4141
measurement opt-in via `--include-row-existence` so default validation stays
4242
focused on request-safe indexed lookups.
43+
- Replaced the legacy IdSharp metadata fallback with Melodee's native ID3 tag
44+
reader, removing the obsolete transitive image-processing dependency path.
45+
- Added explicit private `MessagePack` references for NBomber consumers so the
46+
test and benchmark graphs resolve the non-vulnerable package version.
4347

4448
### Fixed
4549

@@ -139,7 +143,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
139143

140144
### Changed
141145

142-
- **Replaced `SixLabors.ImageSharp` with `SkiaSharp`** for all image processing operations.
146+
- **Replaced the legacy image processing library with `SkiaSharp`** for all image processing operations.
143147
A new `IImageProcessor` abstraction centralizes decode, encode, resize, format
144148
identification, and average-hash computation. `ImageHasher`, `ImageConvertor`, and
145149
`ImageValidator` now receive `IImageProcessor` via dependency injection rather than
Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@page "/share/{ShareUniqueId}"
2-
@using AuralizeBlazor
32
@using Melodee.Common.Data.Models.Extensions
43
@using Melodee.Common.Enums
54

@@ -13,23 +12,41 @@
1312

1413
<div class="shared-container">
1514

16-
<Auralizer
17-
InitialPreset="AuralizerPreset.ClassicLedBars"
18-
TrackList="@_songInfos"
19-
Height="400px"
20-
Width="100%">
21-
<div style="text-align: center;">
22-
<audio class="audio-main" preload="metadata" loading="lazy" controls src="@_songInfos[0].Url"></audio>
15+
@if (_selectedTrack is not null)
16+
{
17+
<div class="shared-player">
18+
<img src="@_selectedTrack.CoverArtUrl" alt="" class="shared-cover-art" loading="lazy" />
19+
<div class="shared-player-details">
20+
<h1>@_selectedTrack.Title</h1>
21+
<audio class="audio-main" preload="metadata" controls src="@_selectedTrack.Url"></audio>
22+
</div>
2323
</div>
24-
</Auralizer>
24+
}
25+
26+
@if (_tracks.Length > 1)
27+
{
28+
<ol class="shared-track-list">
29+
@foreach (var track in _tracks)
30+
{
31+
<li>
32+
<button type="button"
33+
class="shared-track-button"
34+
@onclick="() => SelectTrack(track)">
35+
@track.Title
36+
</button>
37+
</li>
38+
}
39+
</ol>
40+
}
2541

2642
</div>
2743

2844
@code {
2945
[Parameter] public required string ShareUniqueId { get; set; }
3046
[CascadingParameter] private HttpContext? HttpContext { get; set; }
3147

32-
private IAuralizerTrack[] _songInfos = [new AuralizerTrack(string.Empty, string.Empty, string.Empty)];
48+
private SharedTrack[] _tracks = [];
49+
private SharedTrack? _selectedTrack;
3350

3451
protected override async Task OnParametersSetAsync()
3552
{
@@ -44,36 +61,36 @@
4461
var songResult = await SongService.GetAsync(share.ShareId);
4562
if (songResult is { IsSuccess: true, Data: not null })
4663
{
47-
_songInfos =
64+
SetTracks(
4865
[
49-
new AuralizerTrack(songResult.Data.ToApiStreamUrl(configuration, HttpContext),
66+
new SharedTrack(songResult.Data.ToApiStreamUrl(configuration, HttpContext),
5067
$"{songResult.Data.Album.Name} - {songResult.Data.Title}",
5168
$"/images/{songResult.Data.ToCoverArtId()}/{ ImageSize.Large }")
52-
];
69+
]);
5370
}
5471

5572
break;
5673
case ShareType.Album:
5774
var albumResult = await AlbumService.GetAsync(share.ShareId);
5875
if (albumResult is { IsSuccess: true, Data: not null })
5976
{
60-
_songInfos = albumResult.Data.Songs.Select(x =>
61-
new AuralizerTrack(x.ToApiStreamUrl(configuration, HttpContext),
77+
SetTracks(albumResult.Data.Songs.Select(x =>
78+
new SharedTrack(x.ToApiStreamUrl(configuration, HttpContext),
6279
$"{albumResult.Data.Name} - {x.Title}",
6380
$"/images/{albumResult.Data.ToCoverArtId()}/{ ImageSize.Large }")
64-
).ToArray();
81+
).ToArray());
6582
}
6683

6784
break;
6885
case ShareType.Playlist:
6986
var playlistResult = await PlaylistService.GetAsync(share.ShareId);
7087
if (playlistResult is { IsSuccess: true, Data: not null })
7188
{
72-
_songInfos = playlistResult.Data.Songs.Select(x =>
73-
new AuralizerTrack(x.Song.ToApiStreamUrl(configuration, HttpContext),
89+
SetTracks(playlistResult.Data.Songs.Select(x =>
90+
new SharedTrack(x.Song.ToApiStreamUrl(configuration, HttpContext),
7491
$"{x.Song.Album.Name} - {x.Song.Title}",
7592
$"/images/{x.Song.ToCoverArtId()}/{ ImageSize.Large }")
76-
).ToArray();
93+
).ToArray());
7794
}
7895

7996
break;
@@ -83,8 +100,18 @@
83100
}
84101
}
85102

103+
private void SetTracks(SharedTrack[] tracks)
104+
{
105+
_tracks = tracks;
106+
_selectedTrack = _tracks.FirstOrDefault();
107+
}
86108

87-
}
109+
private void SelectTrack(SharedTrack track)
110+
{
111+
_selectedTrack = track;
112+
}
88113

114+
private sealed record SharedTrack(string Url, string Title, string CoverArtUrl);
115+
}
89116

90117

src/Melodee.Blazor/Melodee.Blazor.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
<ItemGroup>
5858
<PackageReference Include="Asp.Versioning.Mvc" />
5959
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" />
60-
<PackageReference Include="AuralizeBlazor" />
6160
<PackageReference Include="HtmlSanitizer" />
6261
<PackageReference Include="MailKit" />
6362
<PackageReference Include="Markdig" />

src/Melodee.Common/Jobs/LibraryInsertJob.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Concurrent;
22
using System.Diagnostics;
3-
using IdSharp.Common.Utils;
43
using Melodee.Common.Configuration;
54
using Melodee.Common.Constants;
65
using Melodee.Common.Data;
@@ -556,7 +555,7 @@ await bus.SendLocal(new MelodeeAlbumReprocessEvent(melodeeAlbum.Directory.FullNa
556555
break;
557556
}
558557

559-
var mediaFileHash = CRC32.Calculate(mediaFile);
558+
var mediaFileHash = Crc32.Calculate(mediaFile);
560559
var songTitle = song.Title()?.CleanStringAsIs() ??
561560
throw new Exception("Song title is required.");
562561
var s = new dbModels.Song

0 commit comments

Comments
 (0)