Skip to content

Instantly share code, notes, and snippets.

@MattJeanes
Last active March 30, 2020 16:25
Show Gist options
  • Save MattJeanes/9633bf6f4eaacb02a28ef6852fdf7cc8 to your computer and use it in GitHub Desktop.
Save MattJeanes/9633bf6f4eaacb02a28ef6852fdf7cc8 to your computer and use it in GitHub Desktop.
Convert a collection of files and text captions to training format
Set-Location $PSScriptRoot
if (-not (Get-Module -ListAvailable -Name "Newtonsoft.Json")) {
Install-Module "Newtonsoft.Json" -Force
}
Import-Module "Newtonsoft.Json"
. $PSScriptRoot/normalize.ps1
$ErrorActionPreference = 'Stop'
try {
$audioFiles = Get-ChildItem -Recurse -Filter "*.flac"
$sounds = @()
# Get audio files and link to text files
$audioFiles | ForEach-Object {
$audioFile = $_
$found = $audioFile.Name -match "^\d\d_\d\d_\d\d_(.+?)_+?"
if (-not $found) { Write-Host "No string match for $txtFileName"; return; } # ignore if cannot match character in file name
$character = $matches[1]
if ($character -ne "Twilight") { return; } # ignore if character is not Twilight
$txtFileName = ($audioFile.Name -replace "\.\.flac", ".txt") -replace "\.flac", ".txt"
if (-not (Test-Path (Join-Path $audioFile.DirectoryName $txtFileName))) { Write-Host "No match for $txtFileName"; return } # ignore if we cannot locate the matching text file
$sounds += @{ Folder = ($audioFile.DirectoryName.Replace($PSScriptRoot + "\", "")); Audio = $audioFile.Name; Text = $txtFileName; Character = $character }
}
Write-Host "Found $($sounds.Count) sounds"
Write-Host "Creating folders"
$tempFolder = (Join-Path $PSScriptRoot "temp")
$convertedFolder = (Join-Path $PSScriptRoot "wavs")
Remove-Item $tempFolder -Recurse -Force -ErrorAction SilentlyContinue
$null = New-Item -ItemType Directory -Path $tempFolder -Force
$null = New-Item -ItemType Directory -Path $convertedFolder -Force
$convertedFilesPath = Join-Path $PSScriptRoot "converted.json"
if (Test-Path $convertedFilesPath) {
Write-Host "Loading existing converted files from $convertedFilesPath"
$convertedFiles = (Get-Content -Raw $convertedFilesPath) | ConvertFrom-JsonNewtonsoft
}
else {
Write-Host "Using new converted files"
$convertedFiles = @{ }
}
$lastNumber = $null
Write-Host "Converting sounds"
$sounds | ForEach-Object {
$folder = $_.Folder
$audioFile = $_.Audio
$audioFilePath = Join-Path $folder $audioFile
if ($convertedFiles[$audioFilePath] -ne $null) { return; }
$textFile = $_.Text
$textFilePath = Join-Path $folder $textFile
if ($lastNumber -eq $null) {
$currentNumbers = @($convertedFiles.Values | ForEach-Object { [int]$_.Number })
$number = $null
for ($i = 1; $i -le $sounds.Count; $i++) {
if (-not $currentNumbers.Contains($i)) {
$number = $i
break;
}
}
if ($number -eq $null) {
Write-Error "Unable to find free number from 0 to $($sounds.Count)"
}
} else {
$number = $lastNumber + 1
}
$newAudioFile = "$number.wav"
$character = $_.Character
$tempAudioPath = Join-Path $tempFolder $newAudioFile
$convertedAudioPath = Join-Path $convertedFolder $newAudioFile
try {
$text = Get-Content -Raw $textFilePath
& "ffmpeg" @(
"-i", "`"$audioFilePath`"",
"-c:a", "pcm_s16le",
"-ar", "22050"
"`"$tempAudioPath`"",
"-hide_banner", "-loglevel", "warning"
)
if ($LASTEXITCODE -ne 0) {
Write-Error "ffmpeg exited with code $LASTEXITCODE"
}
Move-Item $tempAudioPath $convertedAudioPath
$convertedFiles[$audioFilePath] = @{ Audio = $newAudioFile; Text = $text.ToString(); Number = $number }
$lastNumber = $number
Set-Content $convertedFilesPath ($convertedFiles | ConvertTo-JsonNewtonsoft)
Write-Host "Number: $number/$($sounds.Count), Character: $character, Audio file: $audioFile, text: $text"
}
catch {
Write-Warning "Failed to process $audioFile"
Write-Warning $_.Exception.Message
Write-Warning $_.ScriptStackTrace
}
finally {
while (Test-Path $tempAudioPath) {
Start-Sleep 5
try {
Remove-Item $tempAudioPath -Force
break;
}
catch {
Write-Warning "$($_.Exception.Message), retrying in 5 seconds"
}
}
}
}
Write-Host "Generating metadata csv"
$csvLines = @()
$convertedFiles.Keys | ForEach-Object {
$convertedFile = $convertedFiles[$_]
$audio = $convertedFile.Audio -replace ".wav", ""
$text = $convertedFile.Text
$normalizedText = Invoke-EnglishCleaners $text
$csvLines += "$audio|$text|$normalizedText"
}
$outputCsv = Join-Path $PSScriptRoot "metadata.csv"
Set-Content $outputCsv ($csvLines -join "`n")
}
catch {
Write-Host "CRITICAL ERROR"
Write-Error $_.Exception.Message -ErrorAction "Continue"
Write-Error $_.ScriptStackTrace -ErrorAction "Continue"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment