因此,我的文件夹中有数百个 .mp3 文件。几乎每个文件在听到声音之前都有一段静音期。并且静音期的大小各不相同。
文件的结尾也是一样。
是否有任何应用程序(如果可能的话,是免费的)可以帮助我一次修剪所有文件,以便每个文件在歌曲之前和结束时都有相同的静音时间(例如五秒)。
或者,也许是一个可以按照所述方式调整每首歌曲静音的 mp3 播放器。
另外,如果我必须逐个剪切所有文件,哪个应用程序最适合(即速度足够快)完成这项任务?
答案1
我知道四种方法:mp3直接剪切,Mp3splt-GTK,Mp3splt或者ffmpeg
mp3直接剪切(GUI 版本,快速获得结果的最佳选择)
提示
- 选择不同的文件夹作为输出来测试一些结果文件。验证后,重新运行并选择覆盖原件. 你应该在几秒钟内完成,因为程序不会重新编码你的 mp3 文件
- 你可能想要启用设置 » 覆盖源文件时保留日期
Mp3splt-gtk(GUI 版本,适用于所有主流操作系统平台)
mp3splt(命令行版本,适用于所有主流操作系统平台)
下载mp3splt, 打开你的PowerShell ISE,更改两个路径并运行以下代码:
$files = Get-ChildItem "C:\my\musicfolder" -Recurse -Include *.mp3,*.ogg,*.flac
$exe = "C:\path\to\mp3splt.exe"
ForEach ($file in $files) {
If ($file.BaseName -notmatch "_trimmed$" ) {
$newFile = $file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension
If (Test-Path $newFile) {Remove-Item $newFile }
& $exe -r -p "th=-48,min=2" `"$file`" | Out-Null
Remove $file.Fullname
Rename $($file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension) $file.Fullname
}
}
提示
-r -p th=-48, min=2
是删除文件开头/结尾处的静音的选项。th
定义阈值级别(以 dB 为单位)。以下所有内容均视为静音。min=2
设置最短静音(以秒为单位)。只有超过 2 秒的静音才会被截断-P
您可以通过在 mp3splt 命令末尾添加大写字母来假装测试运行。它会输出错误或表示一切顺利。如果使用,请注释掉Remove
,Rename
因为没有创建新文件来处理它们为了测试,您还可以
-d FOLDERPATH
选择单个输出文件夹并-o@f
使用原始文件名作为输出(否则_trimmed
将被附加)
FFmpeg(命令行版本,适用于所有主流操作系统平台)
FFmpeg 的音频过滤器-af silenceremove
不应该使用,因为它总是重新编码你的文件,而你不能保持与输入文件相同的音频质量.-acodec copy
此处不能使用。即使处理多个不同质量的文件,也只能选择一个固定的比特率。
但是,还有另一个 ffmpeg 选项:-af silencedetect
。 理论StackOverflow 上已经解释过了。我将它采用到 Windows 和 PowerShell。
下载ffmpeg, 打开你的PowerShell ISE,更改两个路径并运行以下代码:
$files = Get-ChildItem "C:\path\to\musicfolder" -Recurse -Include *.mp3,*.ogg,*.flac
$ffmpeg = "C:\path\to\ffmpeg.exe"
ForEach ($file in $files) {
If ($file.BaseName -notmatch "_trimmed$" ) {
# Detect silence with ffmpeg and "silencedetect". Save the complete output to variable $log
$log = & $ffmpeg -hide_banner -i `"$file`" -af "silencedetect=duration=1:noise=-50dB" -f null - 2>&1
$totalLength = [string]$log | where {$_ -match '(?<= Duration:.*)[\d:\.]+' } | % {$matches[0]}
$totalLength = ([TimeSpan]::Parse($totalLength)).TotalSeconds
# Use regex to search all numbers after string "silence_end". Save them as string array in the format XXX.XXX
# Check if any 'silence_end' was found. If yes, save the first silence ending time as mp3 start time
[string[]]$silenceEnd = $log | where {$_ -match '(?<=silence_end: )[-\d\.]+' } | % {$matches[0]}
If ($silenceEnd.count -gt 0 -And [double]$silenceEnd[0] -lt $totalLength/2) {
[double]$trackStart = $silenceEnd[0]
} else {
[double]$trackStart = 0
}
# Do the same again but for silence starting times. Save the last one as mp3 end time
[string[]]$silenceStart = $log | where {$_ -match '(?<=silence_start: )[-\d\.]+' } | % {$matches[0]}
If ($silenceStart.count -gt 0 -And $silenceStart[$silenceStart.count-1] -gt $totalLength/2) {
[double]$trackEnd = $silenceStart[$silenceStart.count-1]
} else {
[double]$trackEnd = $totalLength
}
# calculate duration since ffmpeg's -t option wants a duration and not a timestamp
$duration = $trackEnd - $trackStart
# Put together the new file name. If file already exists from previous run, delete it
$newFile = $file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension
If (Test-Path $newFile) {Remove-Item $newFile }
# Run ffmpeg with our calculated start and duration times to remove silence at start and end
write-host "$ffmpeg -i `"$file`" -ss $trackStart -t $duration -acodec copy `"$newFile`" 2>&1"
& $ffmpeg -i `"$file`" -ss $trackStart -t $duration -acodec copy `"$newFile`" 2>&1
# Delete the original mp3 file and rename the new mp3 file to the original name
Remove-Item $file.Fullname
Rename-Item $newFile $file.Fullname
}
}
答案2
如果您需要分析每条曲目中的静默部分,那么这将是一项艰巨的任务。
如果您要自动执行此操作,那么 FFMPEG 应该能够提供帮助……结果可能无法保证,因为我不确定您是否可以将 FFMPEGsilenceremove
过滤器定位到音轨的开头或结尾 - 什么定义了音轨的结尾?这是一个反问,但如果您想找到一种工具来自动化并为您提供所需的结果,这一点很重要。您可能需要逐一执行此操作……Audacity(免费)可用于直观地分析音轨,以便您可以找出需要修剪的地方