PowerShell, bulk music conversion script


Music Tasks

Di recente ho avuto la necessità di convertire tutta la libreria musicale da un formato lossless (FLAC in questo caso) a un formato lossy (in questo caso MP3) senza perdere la struttura delle cartelle, le copertine dei cd e i testi. Per farlo ci sono diversi software free e non, ma purtroppo non soddisfavano le aspettative così ho preferito scrive uno script per farlo e ve lo riporto qui di seguito:

Clear-Host
$Host.UI.RawUI.WindowTitle = "PoSH Music Menu"
$version = "1.0"
function loadMainMenu()
{
[bool]$loopMainMenu = $true
while ($loopMainMenu)
{
Clear-Host # Clear the screen.
Write-Host -BackgroundColor Black -ForegroundColor White “`n`tMusic Tasks – Version $version`t`n”
Write-Host -BackgroundColor Black -ForegroundColor White “`t`tMain Menu`t`t`n”
$runasAlias = [Environment]::UserName
Write-Host -BackgroundColor Black -ForegroundColor White "Running as: $runasAlias`n"
Write-Host “`t`t`t0 - Lossless To FLAC”
Write-Host “`t`t`t1 - Lossless To MP3 (320 Kbps)”
Write-Host “`t`t`t2 - Lossless To MP3 (192 Kbps)”
Write-Host “`t`t`t3 - MP3 To MP3 (192 Kbps) ”
Write-Host “`t`t`t4 - Car Sync (sorted)”
Write-Host “`t`t`tE - Esci`n”
$mainMenu = Read-Host “`t`tOpzione Numero” # Get user's entry.
switch ($mainMenu)
{
0{lossless_to_flac} #Chiama la funzione lossless_to_flac()
1{lossless_to_mp3_hi} #Chiama la funzione lossless_to_mp3_hi()
2{lossless_to_mp3_lo} #Chiama la funzione lossless_to_mp3_lo()
3{mp3_hi_to_mp3_lo} #Chiama la funzione mp3_hi_to_mp3_lo()
4{car_sync} #Chiama la funzione car_sync()
"e" {
$loopMainMenu = $false
$Host.UI.RawUI.WindowTitle = "Windows PowerShell"
Clear-Host
Exit
}
default {
Write-Host -BackgroundColor Red -ForegroundColor White "Scelta non valida!"
sleep -Seconds 1
}
}
}
return
}
function lossless_to_flac()
{
#$sourceDir = 'c:\src\'
#$targetDir = 'c:\dst\'
Write-Host ""
Write-Host "Nota: I path devono terminare con backslash '\'"
Write-Host ""
$sourceDir = Read-Host 'Path sorgente'
$targetDir = Read-Host 'Path di destinazione'
# Decl.
$tree = gci -Directory -Name -Recurse $sourceDir
#Funct.
function Check-Command($cmdname)
{
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
# Check for ffmpeg.exe
if (!(Check-Command -cmdname 'ffmpeg.exe')){
"Non riesco a trovare ffmpeg.exe!, Assicurati che sia presente in `$PATH` nelle variabili di sistema!"
exit 1
}
# Check if $sourceDir exist
if(!(Test-Path -Path $sourceDir )){
"Il path sorgente non è valido!" ; pause
exit 1
}
# Check (and create) $targetDir
if(!(Test-Path -Path $targetDir )){
mkdir $targetDir -Force
}
# Rebuild folder tree
foreach ( $folders in $tree ) { mkdir $targetDir\$folders -Force }
# Copy all files with extension .jpg, .png (album covers) and .txt, .lrc (lyrics)
Get-ChildItem $sourceDir -include "*.jpg","*.png","*.lrc","*.txt" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
# Converts all files from, AIFF, WAV, APE, M4A and ALAC to MP3 (320Kbps) from $ SourceDir to $ TargetDir preserving the tree structure.
Get-ChildItem $sourceDir -include "*.flac","*.wav","*.ape","*.m4a" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length)
$targetFile = $targetFile -replace ".aiff|.wav|.wma|.ape|.alac|.m4a",".flac" ;
ffmpeg -n -i $_.FullName -ab 320k $targetFile
}
Write-Host "Conversione completata!" ; pause
loadMainMenu
}

function lossless_to_mp3_hi()
{
#$sourceDir = 'c:\src\'
#$targetDir = 'c:\dst\'
Write-Host ""
Write-Host "Nota: I path devono terminare con backslash '\'"
Write-Host ""
$sourceDir = Read-Host 'Path sorgente'
$targetDir = Read-Host 'Path di destinazione'
# Decl.
$tree = gci -Directory -Name -Recurse $sourceDir
#Funct.
function Check-Command($cmdname)
{
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
# Check for ffmpeg.exe
if (!(Check-Command -cmdname 'ffmpeg.exe')){
"Non riesco a trovare ffmpeg.exe!, Assicurati che sia presente in `$PATH` nelle variabili di sistema!"
exit 1
}
# Check if $sourceDir exist
if(!(Test-Path -Path $sourceDir )){
"Il path sorgente non è valido!" ; pause
exit 1
}
# Check (and create) $targetDir
if(!(Test-Path -Path $targetDir )){
mkdir $targetDir -Force
}
# Rebuild folder tree
foreach ( $folders in $tree ) { mkdir $targetDir\$folders -Force }
# Copy all files with extension .jpg, .png (album covers) and .txt, .lrc (lyrics)
Get-ChildItem $sourceDir -include "*.jpg","*.png","*.lrc","*.txt" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
# Converts all files from, FLAC, WAV, APE and M4A to MP3 (320Kbps) from $ SourceDir to $ TargetDir preserving the tree structure.
Get-ChildItem $sourceDir -include "*.flac","*.wav","*.ape","*.m4a" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length)
$targetFile = $targetFile -replace ".flac|.wav|.ape|.m4a",".mp3" ;
ffmpeg -n -i $_.FullName -ab 320k $targetFile
}
Write-Host "Conversione completata!" ; pause
loadMainMenu
}
#
function lossless_to_mp3_lo()
{
#$sourceDir = 'c:\src\'
#$targetDir = 'c:\dst\'
Write-Host ""
Write-Host "Nota: I path devono terminare con backslash '\'"
Write-Host ""
$sourceDir = Read-Host 'Path sorgente'
$targetDir = Read-Host 'Path di destinazione'
# Decl.
$tree = gci -Directory -Name -Recurse $sourceDir
#Funct.
function Check-Command($cmdname)
{
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
# Check for ffmpeg.exe
if (!(Check-Command -cmdname 'ffmpeg.exe')){
"Non riesco a trovare ffmpeg.exe!, Assicurati che sia presente in `$PATH` nelle variabili di sistema!"
exit 1
}
# Check if $sourceDir exist
if(!(Test-Path -Path $sourceDir )){
"Il path sorgente non è valido!" ; pause
exit 1
}
# Check (and create) $targetDir
if(!(Test-Path -Path $targetDir )){
mkdir $targetDir -Force
}
# Rebuild folder tree
foreach ( $folders in $tree ) { mkdir $targetDir\$folders -Force }
# Copy all files with extension .jpg, .png (album covers) and .txt, .lrc (lyrics)
Get-ChildItem $sourceDir -include "*.jpg","*.png","*.lrc","*.txt" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
# Converts all files from, FLAC, WAV, APE and M4A to MP3 (192Kbps) from $ SourceDir to $ TargetDir preserving the tree structure.
Get-ChildItem $sourceDir -include "*.flac","*.wav","*.ape","*.m4a" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length)
$targetFile = $targetFile -replace ".flac|.wav|.ape|.m4a",".mp3" ;
ffmpeg -n -i $_.FullName -ab 192k $targetFile
}
Write-Host "Conversione completata!" ; pause
loadMainMenu
}
function mp3_hi_to_mp3_lo()
{
#$sourceDir = 'c:\src\'
#$targetDir = 'c:\dst\'
Write-Host ""
Write-Host "Nota: I path devono terminare con backslash '\'"
Write-Host ""
$sourceDir = Read-Host 'Path sorgente'
$targetDir = Read-Host 'Path di destinazione'
# Decl.
$tree = gci -Directory -Name -Recurse $sourceDir
#Funct.
function Check-Command($cmdname)
{
return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}
# Check for ffmpeg.exe
if (!(Check-Command -cmdname 'ffmpeg.exe')){
"Non riesco a trovare ffmpeg.exe!, Assicurati che sia presente in `$PATH` nelle variabili di sistema!"
exit 1
}
# Check if $sourceDir exist
if(!(Test-Path -Path $sourceDir )){
"Il path sorgente non è valido!" ; pause
exit 1
}
# Check (and create) $targetDir
if(!(Test-Path -Path $targetDir )){
mkdir $targetDir -Force
}
# Rebuild folder tree
foreach ( $folders in $tree ) { mkdir $targetDir\$folders -Force }
# Copy all files with extension .jpg, .png (album covers) and .txt, .lrc (lyrics)
Get-ChildItem $sourceDir -include "*.jpg","*.png","*.lrc","*.txt" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
# Converts all MP3 to MP3 (192Kbps) from $ SourceDir to $ TargetDir preserving the tree structure.
Get-ChildItem $sourceDir -include "*.mp3" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length)
ffmpeg -n -i $_.FullName -ab 192k $targetFile
}
Write-Host "Conversione completata!" ; pause
loadMainMenu
}
#
function car_sync()
{
#$sourceDir = 'c:\src\'
#$targetDir = 'c:\dst\'
Write-Host ""
Write-Host "Nota: I path devono terminare con backslash '\'"
Write-Host ""
$sourceDir = Read-Host 'Path sorgente'
$targetDir = Read-Host 'Path di destinazione'
# Decl.
$tree = gci -Directory -Name -Recurse $sourceDir
# Check if $sourceDir exist
if(!(Test-Path -Path $sourceDir )){
"Il path sorgente non è valido!" ; pause
exit 1
}
# Check (and create) $targetDir
if(!(Test-Path -Path $targetDir )){
mkdir $targetDir -Force
}
# Rebuild folder tree
foreach ( $folders in $tree ) { mkdir $targetDir\$folders -Force }
# Copy all files with extension .mp3
Get-ChildItem $sourceDir -include "*.mp3" -recurse |
foreach{
$targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
New-Item -ItemType File -Path $targetFile -Force;
Copy-Item $_.FullName -destination $targetFile
}
Write-Host "Copia completata!" ; pause
loadMainMenu
}

#---------------------------------------------------
# Start the Menu once loaded:
loadMainMenu
# Extras:
if ($clearHost) {Clear-Host}
if ($exitSession) {Exit-PSSession};

Prerequisiti:

* PowerShell (3.0 o superiore) installato (già incluso da Windows 8 in poi!) 
 * L’eseguibile di FFmpeg copiato in “C:\Windows\” (o in alternativa aggiungendone il percorso nella variable $PATH di Windows.)

Originally published on Anfossi.tk