# Powershell script
# Uses ffmpeg to auto calculate image size from duration *
# Uses ffmpeg to generate loudness plot using lavfi ebur128 filter
# * ~5 px per 1s - filter auto generates images that have wasted space.
Function MakePlot ($file){
# define output plot image file
$outplot = $($env:TEMP + "\r128Plot" + $(Get-Date -format 'yyyyMMdd_HHmmss') + ".png")
$filepath = $file
# capture ffmpeg read file output by dumping a stream copy to null
$ffmpegOutput = & ffmpeg.exe -hide_banner -i $filepath 2>&1 -codec copy -f null -
# format graph title from metadata else use filepath
# replace escape chars for drawtext filter
$artist = $($($ffmpegOutput.Exception.Message | ?{$_ -match ' ARTIST' })[0]).Substring(22)
$album = $($($ffmpegOutput.Exception.Message | ?{$_ -match ' ALBUM' })[0]).Substring(22)
$track = $($($ffmpegOutput.Exception.Message | ?{$_ -match ' TITLE' })[0]).Substring(22)
if($track){
$title = $track
}
if($album){
$title = $($album + " - " + $track)
}
if($artist){
$title = $($artist + " : " + $album + " / " + $track)
} else {
$title = $filepath
}
$title = $title -replace('\\','\\\\') -replace([regex]::Escape(':'),'\\\:') -replace([regex]::escape("'"),"'\\\''") -replace(' ','\ ')
Write-host $title
# find file duration in nearest 0.1s, use as output image width, which later is halved.
# blame the adrawgraph filter for the odd behaviour or right side dead space.
$durationStr = $($ffmpegOutput -split',' | ?{$_ -match "Duration:"}) -split' ' | ?{$_ -match "\d\d:\d\d:\d\d.\d\d"}
Write-host $durationStr
$width = $($([TimeSpan]::Parse($durationStr)).TotalMilliseconds) -replace'.{2}$'
$height=600;$rExt=50
& ffmpeg.exe -hide_banner -i $filepath -filter_complex `
"ebur128=dualmono=true:metadata=1:framelog=verbose,asplit[r128data0][r128data1];`
[r128data0]adrawgraph=slide=picture:min=-60:max=0:s=$($width)x$($height):`
m1=lavfi.r128.M:fg1=0x900000ff:`
m2=lavfi.r128.S:fg2=0xff51b400:`
m3=lavfi.r128.I:fg3=0xffff9000[r128plot0];`
[r128data1]adrawgraph=slide=picture:min=-5:max=25:s=$($width)x$($height):`
m1=lavfi.r128.LRA:fg1=0xff00d000:bg=0xff000000[r128plot1];`
color=c=#[email protected]:s=$($width)x$($height),format=argb,split=3[bg0][bg1][bg2];`
[bg0]drawgrid=width=50:height=ih/60:color=#[email protected]:replace=1,`
drawgrid=width=50*6:height=ih/12:color=#[email protected]:replace=1[grid];`
[bg1]drawtext=text='$($title.toString())':x=(w/4)-(text_w/2):y=(h/2)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=30:fontcolor=black,`
drawtext=text='Time (mm\\\:ss)':x=(w/4)-(text_w/2):y=(h-10)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=12:fontcolor=black,`
drawtext=text='01\:00':x=(300*1)-(text_w/2):y=(h-25)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='02\:00':x=(300*2)-(text_w/2):y=(h-25)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='03\:00':x=(300*3)-(text_w/2):y=(h-25)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='04\:00':x=(300*4)-(text_w/2):y=(h-25)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-5':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*1)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-10':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*2)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-15':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*3)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-20':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*4)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-25':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*5)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-30':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*6)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-35':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*7)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-40':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*8)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-45':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*9)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-50':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*10)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='-55':x=(w/2-35+$rExt)-(text_w/2):y=(h/12*11)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='20':x=(w/2-40)-(text_w/2):y=(h/12*2)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='15':x=(w/2-40)-(text_w/2):y=(h/12*4)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='10':x=(w/2-40)-(text_w/2):y=(h/12*6)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='5':x=(w/2-40)-(text_w/2):y=(h/12*8)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black,`
drawtext=text='0':x=(w/2-40)-(text_w/2):y=(h/12*10)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=15:fontcolor=black[text0];`
[bg2]drawtext=text='Loudness Range LRA (LU)':x=(w/2)-(text_w/2):y=(h/2-10)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=12:fontcolor=black,`
drawtext=text='Loudness Units Full Scale (LUFS)':x=(w/2)-(text_w/2):y=(h/2+40)-(text_h/2):fontfile=C\\:/Windows/Fonts/arial.ttf:fontsize=12:fontcolor=black[text1];`
[r128plot0][r128plot1]overlay=format=auto[r128plot];`
[r128plot][grid]overlay=main_w-overlay_w-1:main_h-overlay_h-1:format=auto[gfx];`
[text1]rotate=-90*PI/180:fillcolor=none[textrot];`
[text0][textrot]overlay=format=auto[text];`
[gfx][text]overlay=format=auto,`
crop=$($width/2+$rExt):$($height):0:0"`
-update 1 -frames:v 1 -y $outplot
return $outplot
}
ForEach ($i in $args){
if(!(Test-Path $i)){continue}
Write-host $i
$outplot = MakePlot -file $i
& $outplot
}