Skip to content

Instantly share code, notes, and snippets.

@milnak
Last active March 13, 2024 05:18
Show Gist options
  • Save milnak/006133638d3b82c2bc670c48d562282f to your computer and use it in GitHub Desktop.
Save milnak/006133638d3b82c2bc670c48d562282f to your computer and use it in GitHub Desktop.
Create MP3, FLAC files HTML (or pipeline) Report. Requires ffprobe.exe from ffmpeg package.
Param(
[string]$Path,
[switch]$HtmlOutput
)
function Format-Size {
param(
[Parameter(Mandatory)][double]$Bytes
)
switch ([math]::Max($Bytes, 0)) {
{ $_ -ge 1GB } { "{0:N1} GB" -f ($Bytes / 1GB); break }
{ $_ -ge 1MB } { "{0:N1} MB" -f ($Bytes / 1MB); break }
{ $_ -ge 1KB } { "{0:N1} KB" -f ($Bytes / 1KB); break }
default { "$Bytes B" }
}
}
$files = Get-ChildItem $Path -File -Recurse -Include '*.mp3','*.flac' | ForEach-Object {
# TODO: Add -select_streams a:0 ?
$metadata = ffprobe.exe -loglevel quiet -show_entries stream=bit_rate -show_format -print_format json $_.FullName | ConvertFrom-Json
[PSCustomObject]@{
Name = $_.Name
DirectoryName = $_.DirectoryName
Artist = $metadata.format.tags.artist
Album = $metadata.format.tags.album
Title = $metadata.format.tags.title
Year = $metadata.format.tags.date
Genre = $metadata.format.tags.genre
Track = [int]$metadata.format.tags.track
Size = $metadata.format.size
Duration = [TimeSpan]::FromSeconds([Math]::Round($metadata.format.duration))
# Convert to kb/s
BitRate = @($metadata.streams.bit_rate)[0] / 1000
}
}
if (!$HtmlOutput) {
$files | Sort-Object Track | Group-Object DirectoryName
return
}
# HTML
'<html>'
# Head
'<head>'
'<title>Music files report</title>'
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
'</head>'
# Body
'<body bgcolor="#5E7CB0" text="#000000"><table width="100%" border="0" align="center" cellpadding="2" cellspacing="2" bgcolor="#A2B6D7">'
# Header
'<tr bgcolor="#CCCCCC"><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">File name</font></b></td><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Artist</font></b></td><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Album</font></b></td><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Title</font></b></td><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Year</font></b></td><td><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Genre</font></b></td><td><div align="right"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">#</font></b></div></td><td><div align="right"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Bitrate</font></b></div></td><td><div align="right"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Duration</font></b></div></td><td><div align="right"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">File size</font></b></div></td></tr>'
$TotalCount = 0
$TotalDurationSeconds = 0
$TotalSize = 0
$files | Sort-Object Track | Group-Object DirectoryName | ForEach-Object {
# Directory Name
'<tr bgcolor="#E9E3C7"><td colspan="10"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{0}</font></td></tr>' -f `
$_.Name
# Contained files
foreach ($item in $_.Group) {
'<tr bgcolor="#C4CEDF"><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{0}</font></td><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{1}</font></td><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{2}</font></td><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{3}</font></td><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{4}</font></td><td><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{5}</font></td><td><div align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{6}</font></div></td><td><div align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{7}</font></div></td><td><div align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{8}</font></div></td><td><div align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">{9}</font></div></td></tr>' -f `
$item.Name, `
$item.Artist, `
$item.Album, `
$item.Title, `
$item.Year, `
$item.Genre, `
$item.Track, `
$item.BitRate, `
$item.Duration.ToString('mm\:ss'), `
(Format-Size -Bytes $item.Size)
$TotalCount++
$TotalDurationSeconds += $item.Duration.TotalSeconds
$TotalSize += $item.Size
}
}
# Totals
$TotalTimeSpan = [TimeSpan]::FromSeconds($TotalDurationSeconds)
'<tr bgcolor="#E9E3C7"><td colspan="10"><div align="center"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Total files count: {0}.&nbsp;&nbsp; Total duration: {1}.&nbsp;&nbsp;Total files size: {2}.</font></b></div></td></tr>' -f `
$TotalCount, `
('{0}:{1:d2}:{2:d2}' -f ($TotalTimeSpan.Days * 24 + $TotalTimeSpan.Hours), $TotalTimeSpan.Minutes, $TotalTimeSpan.Seconds), `
(Format-Size -Bytes $TotalSize)
# end table
'</table>'
# credits
'<p align="center"><a href="https://learn.microsoft.com/en-us/powershell/" target="_blank"><font face="Verdana, Arial, Helvetica, sans-serif" size="1">Report generated with PowerShell</font></a></p>'
# end body
'</body>'
# end html
'</html>'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment