自动批处理 - Trim,更改比特率,然后通过 Windows 上的 sox 规范化 wav 文件

Auto Batch Process - Trim, change bit rate and then normalize wav files via sox on Windows

我想批量处理文件夹中的wav文件:

  1. 首先将文件修剪为 5 秒,并将修剪后的文件放在名为“Trim5s”的文件夹中,然后
  2. 更改修剪文件的比特率(即在文件夹“Trim5s”中)并将在上述步骤 1 中从修剪文件导出的新比特率文件保存到名为“16bit”的文件夹中" 然后
  3. 将新的修剪+新比特率文件标准化为-1,它位于上面步骤 2 中导出的“16bit”文件夹中,并将标准化+修剪的文件+新比特率文件保存到文件夹“Norm-1”。

这是我的文件夹结构:

MainFolder
   |____file1.wav
   |____file2.wav
   |____Trim5s
           |____file1_trim5s.wav
           |____file2_trim5s.wav
           |____16bit
                  |____file1_trim5s_16bit.wav
                  |____file2_trim5s_16bit.wav
                  |____Norm-1
                         |____file1_trim5s_16bit_Norm-1.wav
                         |____file2_trim5s_16bit_Norm-1.wav
        

目前我每次都手动执行每个步骤。以下是 Windows cmd 命令:

第 1 步:Trim 个文件到秒:

for %i in (*.wav) do sox -S "%i" "Trim5s\%~ni_trim5.wav" trim 0 5

然后我手动更改目录到“Trim5s”和运行第二步:

第 2 步:在“Trim5s”文件夹中将位深度更改为 16 位:

for %i in (*.wav) do sox -S "%i" -b 16 "16bit\%~ni_16bit.wav"

然后我再次手动更改目录到文件夹“16bit”和运行第三步:

第 3 步:规范化 16 位文件夹中的文件:

for %i in (*.wav) do sox -S --norm=-1 "%i" "Norm-1\%~ni_norm-1.wav"

有没有办法自动执行此过程,我可以自动执行所有 3 个过程?也就是将上面给出的三个手动步骤转换为嵌套循环?嵌套循环可以完成还是有更好的方法从 MainFolder 自动执行上述 3 个任务?

这是我到目前为止尝试过的:

for %i in (*.wav) do sox -S "%i" "Trim5s\%~ni_trim-5.wav" trim 0 0.5 & cd Trim5s & for %j in (*.wav) do sox -S "%j" -b 16 "..bit\%~nj_16bit.wav" & cd 16bit & for %k in (*wav) do sox -S --norm=-1 "%k" "..\norm-1\%~nk_norm-1.wav"

任何帮助将不胜感激!

几条评论:

  • 使用绝对路径而不是“相对路径并更改 current/working 目录”是一个好主意,因为当出现问题时,人们会迷失在那些工作目录中;绝对路径还允许直接链接脚本。
  • 避免链接子文件夹也是一个好主意,因为您正在创建一个依赖链,这在更改脚本或添加新脚本时很难follow/test;这减少了维护 overhead/cost。不过,如果您想这样做,请随意更改脚本中的目标目录。
  • 在脚本中定义函数是个好主意,这样可以提高可读性和可测试性,并允许重用。

在这个脚本中,我定义了前几个函数来解决小问题,最后才是真正的批处理:

function ToColor($color) { process { Write-Host $_ -ForegroundColor $color } }
function Trim($source, $target) { "sox -S $source $target trim 0 5" | ToColor "green" }
function To16bits($source, $target) { "sox -S $source -b 16 $target" | ToColor "green" }
function Norm($source, $target) { "sox -S --norm=-1 $source $target" | ToColor "green" }
function AddTag($ori, $tag) { return $ori.name -replace '(\w+)(\.wav)', ('_' + $tag + '') }
function AddDir($ori, $name) { New-Item -Path $ori -Name $name -ItemType "directory" -Erroraction SilentlyContinue }

function Batch($func, $oriSubDir, $newDir, $tag) {
    AddDir $dir $newDir
    $oriDir = "$dir$oriSubDir"
    $targetDir = "$dir$newDir"
    $files = Get-ChildItem *.wav -Path $oriDir
    "applying <<$tag>> to $(($files | Measure-Object).Count) files from <$oriDir> to <$targetDir>" | ToColor "yellow"
    foreach($file in $files) {
        $target = AddTag $file $tag
        Invoke-Command $func -ArgumentList "$oriDir/$file", "$targetDir/$target"
        New-Item -Path "$targetDir" -ItemType "file" -Name $target # mocks creation of processed file
    }
}

function ProcessFiles() {
    foreach ($dir in $targetList) {
        "using original files from $dir" | ToColor "yellow"
        Batch ${function:Trim}     ""       "trim5s" "trim"
        Batch ${function:To16bits} "trim5s" "16bits" "16bits"
        Batch ${function:Norm}     "16bits" "Norm-1" "norm"
    }
}

$targetList = $args | Where-Object {Test-Path $_  -PathType Container}
$count = ($targetList | Measure-Object).Count
if($count -eq 0) {
    "usage: Start-BatchSox.ps1 dir1 [dir2 ...]" | ToColor "yellow"
    return
}
"Got $count directories to process" | ToColor "yellow"
ProcessFiles

为了获得实际的行为,您需要注释 New-Item 行并将处理命令(作为文本)更改为实际命令,例如,

"sox -S $source $target trim 0 5" | ToColor "green"

至:

sox -S $source $target trim 0 5

脚本可以放在Start-BatchSox.ps1中,可以放在你路径的某个地方;然后你可以从任何地方调用它(见“用法”消息)。