Skip to content

Instantly share code, notes, and snippets.

@stelf
Last active August 11, 2024 13:40
Show Gist options
  • Save stelf/05f612929bf2932e29bd743017878242 to your computer and use it in GitHub Desktop.
Save stelf/05f612929bf2932e29bd743017878242 to your computer and use it in GitHub Desktop.
reat from acousticid
# 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