Last active
August 11, 2024 13:40
-
-
Save stelf/05f612929bf2932e29bd743017878242 to your computer and use it in GitHub Desktop.
reat from acousticid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Ensure fpcalc (AcoustID fingerprinter) is installed and in PATH | |
# Ensure TagLibSharp is installed via NuGet: Install-Package TagLibSharp | |
using namespace TagLib | |
$config = @{ | |
AcoustIdApiKey = "useyoursplease" | |
AcoustIdApiUrl = "https://api.acoustid.org/v2/lookup" | |
} | |
$programFilesPath = Get-ChildItem -Path 'C:\Program Files\PackageManagement\NuGet\' -Filter TagLibSharp.dll -Recurse -ErrorAction SilentlyContinue -Depth 6 | | |
Select-Object -First 1 -ExpandProperty FullName | |
$envPath = Get-ChildItem -Path $env:NUGET_PACKAGES -Filter TagLibSharp.dll -Recurse -ErrorAction SilentlyContinue -Depth 6 | | |
Select-Object -First 1 -ExpandProperty FullName | |
$tagLibPath = $programFilesPath ? $programFilesPath : $envPath | |
Add-Type -Path $tagLibPath | |
function Get-AudioInfo { | |
param ([string]$file) | |
$output = & fpcalc -json "$file" | |
$info = $output | ConvertFrom-Json | |
return @{ | |
Fingerprint = $info.fingerprint | |
Duration = [int]$info.duration | |
} | |
} | |
function Get-TrackInfo { | |
param ([string]$fingerprint, [int]$duration) | |
$body = @{ | |
client = $config.AcoustIdApiKey | |
meta = "recordings releasegroups releases tracks compress" | |
duration = $duration | |
fingerprint = $fingerprint | |
} | |
try { | |
$response = Invoke-RestMethod -Uri $config.AcoustIdApiUrl -Method Post -Body $body | |
$response.results.Length -and ( $response | ConvertTo-Json -Depth 10 | Out-File -FilePath "last_acoustid_response.json" ) > $null | |
if ($response.results -and $response.results.Count -gt 0) { | |
return $response.results[0] | |
} | |
} | |
catch { | |
Write-Host "Error querying AcoustID API - $_" -ForegroundColor DarkGray | |
} | |
return $false | |
} | |
function Compare-and-SetTags { | |
param ([string]$file, [PSCustomObject]$trackInfo) | |
$tagFile = $null | |
try { | |
$tagFile = [TagLib.File]::Create($file) | |
$tag = $tagFile.Tag | |
$changed = $false | |
if ($trackInfo.id) { | |
Write-Host " Updating AcoustID - $($trackInfo.id)" -ForegroundColor Yellow | |
$tag.Comment = "AcoustID: $($trackInfo.id)" | |
$changed = $true | |
} | |
if ($trackInfo.recordings -and $trackInfo.recordings.Count -gt 0) { | |
$recording = $trackInfo.recordings[0] | |
$tagMapping = @{ | |
Title = $recording.title | |
Album = $recording.releasegroups[0].title | |
Year = [uint32]$recording.releasegroups[0].releases[0].date.year | |
Track = [uint32]$recording.releasegroups[0].releases[0].track_count | |
} | |
foreach ($key in $tagMapping.Keys) { | |
$newValue = $tagMapping[$key] | |
if ($null -ne $newValue -and $newValue -ne $tag.$key) { | |
Write-Host " Updating $key - $($tag.$key) -> $newValue" -ForegroundColor Yellow | |
$tag.$key = $newValue | |
$changed = $true | |
} | |
} | |
# Handle Performers and AlbumArtists | |
if ($recording.artists -and $recording.artists.Count -gt 0) { | |
$newPerformers = $recording.artists.name | |
if (($null -eq $tag.Performers) -or (@(Compare-Object $tag.Performers $newPerformers) -ne $null)) { | |
Write-Host " Updating Performers - $($tag.Performers -join ', ') -> $($newPerformers -join ', ')" -ForegroundColor Yellow | |
$tag.Performers = $newPerformers | |
$changed = $true | |
} | |
if (($null -eq $tag.AlbumArtists) -or (@(Compare-Object $tag.AlbumArtists $newPerformers) -ne $null)) { | |
Write-Host " Updating AlbumArtists - $($tag.AlbumArtists -join ', ') -> $($newPerformers -join ', ')" -ForegroundColor Yellow | |
$tag.AlbumArtists = $newPerformers | |
$changed = $true | |
} | |
} | |
# Handle MusicBrainz IDs | |
$musicBrainzTags = @{ | |
MusicBrainzTrackId = $recording.id | |
MusicBrainzReleaseGroupId = $recording.releasegroups[0].id | |
MusicBrainzArtistId = $recording.artists[0].id | |
MusicBrainzReleaseId = $recording.releasegroups[0].releases[0].id | |
} | |
foreach ($key in $musicBrainzTags.Keys) { | |
$newValue = $musicBrainzTags[$key] | |
if ($null -ne $newValue -and $newValue -ne $tag.$key) { | |
Write-Host " Updating $key - $($tag.$key) -> $newValue" -ForegroundColor Yellow | |
$tag.$key = $newValue | |
$changed = $true | |
} | |
} | |
# Handle special cases | |
if ($recording.releasegroups[0].type) { | |
$tag.Grouping = $recording.releasegroups[0].type | |
$changed = $true | |
} | |
} | |
if ($changed) { | |
$tagFile.Save() | |
Write-Host " Tags updated successfully." -ForegroundColor Green | |
} | |
else { | |
Write-Host " No tag updates needed." -ForegroundColor DarkGray | |
} | |
} | |
catch { | |
Write-Host "Error processing tags - $_" -ForegroundColor Red | |
} | |
finally { | |
if ($null -ne $tagFile) { | |
$tagFile.Dispose() | |
} | |
} | |
} | |
###################################################################### BEGIN | |
# $TagLibPath = Find-TagLibDll | |
# Add-Type -Path $TagLibPath | |
# [System.Reflection.Assembly]::LoadFile($TagLibPath) > $null | |
$wavFiles = Get-ChildItem -Filter *.wav | |
if ($wavFiles.Count -eq 0) { | |
Write-Host "No WAV files found in the current directory." -ForegroundColor DarkGray | |
exit | |
} | |
$requestCount = 0 | |
$startTime = Get-Date | |
foreach ($file in $wavFiles) { | |
Write-Host "Processing file - $($file.Name)" -ForegroundColor Cyan | |
$audioInfo = Get-AudioInfo -file $file.FullName | |
if ($audioInfo.Fingerprint -and $audioInfo.Duration) { | |
# Implement rate limiting | |
$requestCount++ | |
if ($requestCount -ge 3) { | |
$elapsed = (Get-Date) - $startTime | |
if ($elapsed.TotalSeconds -lt 1) { | |
Start-Sleep -Milliseconds (1000 - $elapsed.TotalMilliseconds) | |
} | |
$requestCount = 0 | |
$startTime = Get-Date | |
} | |
$trackInfo = Get-TrackInfo -fingerprint $audioInfo.Fingerprint -duration $audioInfo.Duration | |
if ($trackInfo) { | |
Write-Host "Match found - Score: $($trackInfo.score)" -ForegroundColor Green | |
Compare-and-SetTags -file $file.FullName -trackInfo $trackInfo | |
} | |
else { | |
Write-Host "No match found for $($file.Name)" -ForegroundColor DarkGray | |
} | |
$finalTags = [TagLib.File]::Create($file.FullName).Tag | |
$tagInfo = [PSCustomObject]@{ | |
TrackID = $finalTags.MusicBrainzTrackId | |
Album = $finalTags.Album | |
AlbumArtists = $finalTags.AlbumArtists -join ', ' | |
Comment = $finalTags.Comment | |
Performers = $finalTags.Performers -join ', ' | |
Title = $finalTags.Title | |
Track = $finalTags.Track | |
Year = $finalTags.Year | |
} | |
$tagInfo | Format-Table -AutoSize -Wrap | |
} | |
else { | |
Write-Host "Failed to get fingerprint or duration for $($file.Name)" -ForegroundColor DarkGray | |
} | |
Write-Host "---" -ForegroundColor DarkGray | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment