Skip to content

Instantly share code, notes, and snippets.

@SpL1Ne
Last active January 14, 2022 15:54
Show Gist options
  • Save SpL1Ne/54d8c8d036f58b8afb89eaa34ce77fd0 to your computer and use it in GitHub Desktop.
Save SpL1Ne/54d8c8d036f58b8afb89eaa34ce77fd0 to your computer and use it in GitHub Desktop.
Split album song file into separate tracks with powershell and ffmpeg
# ReadMe
# How to use
# 1. Put script and ffmpeg.exe into one folder.
# 2. Create file with timestamps.
# 3. Open powershell terminal.
# 4. Execute script: *path\to\script\SplitSong.ps1* *path\to\track* *path\to\file\with\timestamps*
#
# Example timestamps file:
# 00:00 DEVILISH TRIO - As Light Fades (Skeler Remix)
# 04:02 Juice WRLD - Conversations (Skeler Remix)
#
# Example using when album song and chapters in current working directory:
# D:\Script\SplitSong.ps1 '.\Downloaded song.mp3' .\chapters.txt
#
#
# Use quotes for paths if it contais spaces.
# Script will create folder in current working directory with same name as album track and put there separate tracks.
#
# Supported format only: [hh:]mm:ss Title
# If title contains '-', script will try to split title and add "artist - title" to metadata.
#
# Tested with Powershell 7.1.
# If you want run script on Windows Powershell 5.
# Replace
# Join-Path $pwd $folderName $trackName
# to
# Join-Path (Join-Path $pwd $folderName) $trackName
#
# Also, probably you will have to change execution policy for powershell 5
# Set-ExecutionPolicy RemoteSigned -Scope Process
# This command allow to execute scripts for this powershell session.
#
param( [Parameter(Mandatory = $true)] [string]$songPath, [Parameter(Mandatory = $true)] [string]$chaptersFile )
$chapters = @(Get-Content $chaptersFile)
$songfile = Get-ChildItem $songPath
$folderName = $songfile.BaseName.Trim().Split([IO.Path]::GetInvalidFileNameChars()) -join '_'
if ( -not (Test-Path (Join-Path $pwd $folderName)) ) { New-Item (Join-Path $pwd $folderName) -ItemType Directory > $null }
for ($i = 0; $i -lt $chapters.Count; $i++) {
$startTime, $trackName = $chapters[$i] -split ' ', 2
$endTime = $trackArtist = ''
$trackTitle = $trackName = ($trackName.Trim().Split([IO.Path]::GetInvalidFileNameChars()) -join '_') -replace '\$', '`$'
if ($trackName.Contains('-')) { $trackArtist, $trackTitle = $trackName -split '-', 2 }
$trackPath = Join-Path $pwd $folderName $trackName
if (Test-Path ($trackPath + $songfile.Extension)) {
$trackName += "`_$i"
$trackPath = Join-Path $pwd $folderName $trackName
}
$trackPath += $songfile.Extension
if ($i -lt $chapters.Count - 1) {
$endTime = "-to $(($chapters[$i + 1] -split ' ', 2)[0])"
}
$command = "ffmpeg -loglevel error -stats -i `"$($songfile.FullName)`" -c:a copy -ss $startTime $endTime -metadata track=`"$($i + 1)`" -metadata title=`"$($trackTitle.Trim())`" -metadata artist=`"$($trackArtist.Trim())`" `"$trackPath`""
Write-Host "Extracting: $trackName"
Invoke-Expression $command
Write-Host ''
Start-Sleep -Milliseconds 500
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment