FFmpeg自优化脚本问题:按静音分割MP3时如何启停搜索功能
按静音分割MP3:实现ffmpeg进程的停止与重启
问题背景
需要按静音在180-480秒的时长范围内分割MP3文件,编写了PowerShell脚本,但无法在检测到片段超时时停止当前ffmpeg搜索进程、调整参数后重启搜索。
原脚本
$minDuraton = 180 $maxDuraton = 480 $paramDB = -42 $w_paramDB = $paramDB $silparam = [string]$w_paramDB+"dB:d=0.2" C:\ffmpeg\bin\ffmpeg.exe -v warning -i "C:\mp3\test.mp3" -af silencedetect=$silparam,ametadata=mode=print:file=-:key=lavfi.silence_start -vn -sn -f s16le -y D:\Mailbox\09_Tools\PS_Scripte\mp3\Tmp_silents_part.txt| %{ if ($_ -match "start"){ $i++ $text,$time = $_ -split "=" $p_Duration = $time - $StartPart if($p_Duration -gt ($maxDuraton +10)){ # Stop ffmepg and restart with new parameter ##### -please help- ##### # editing Parameter $w_paramDB = [INT]($w_paramDB * 1,10) } elseif($p_Duration -ge $minDuraton ){ $null = $PartArr.Add($time) $StartPart = $time } } } $PartArr $i $segments = ($PartArr) -join "," #PartArr | Join-String -Separator ',' $segmentsC: C:\ffmpeg\bin\ffmpeg.exe -i "C:\mp3\test.mp3" -f segment -segment_times $segments "C:\mp3\output_silc_%03d.mp3"
解决方案
要实现进程的停止与重启,核心是捕获ffmpeg进程对象、用循环控制重启逻辑,以下是修改后的完整脚本:
# 初始化参数 $minDuration = 180 $maxDuration = 480 $paramDB = -42 $w_paramDB = $paramDB $PartArr = @() $StartPart = 0.0 $shouldRestart = $false # 循环执行ffmpeg检测,直到无需重启 do { $shouldRestart = $false # 构造静音检测参数 $silparam = "$w_paramDB dB:d=0.2" # 启动ffmpeg并捕获进程对象 $ffmpegProcess = Start-Process -FilePath "C:\ffmpeg\bin\ffmpeg.exe" -ArgumentList @( "-v", "warning", "-i", "C:\mp3\test.mp3", "-af", "silencedetect=$silparam,ametadata=mode=print:file=-:key=lavfi.silence_start", "-vn", "-sn", "-f", "s16le", "-y", "D:\Mailbox\09_Tools\PS_Scripte\mp3\Tmp_silents_part.txt" ) -NoNewWindow -PassThru -RedirectStandardOutput "ffmpeg_temp_output.txt" # 实时读取ffmpeg输出 $outputReader = New-Object System.IO.StreamReader("ffmpeg_temp_output.txt") while (!$outputReader.EndOfStream -and !$shouldRestart) { $line = $outputReader.ReadLine() if ($line -match "start") { $text, $time = $line -split "=" $p_Duration = [double]$time - [double]$StartPart # 检测到片段过长,停止进程并标记重启 if ($p_Duration -gt ($maxDuration + 10)) { $ffmpegProcess.Kill() $ffmpegProcess.WaitForExit() $outputReader.Close() # 调整静音检测阈值(改用1.1避免地区格式问题) $w_paramDB = [int]($w_paramDB * 1.1) $shouldRestart = $true break } # 符合时长要求,记录分割点 elseif ($p_Duration -ge $minDuration) { $null = $PartArr.Add($time) $StartPart = $time } } } # 清理临时文件 $outputReader.Close() Remove-Item "ffmpeg_temp_output.txt" -ErrorAction SilentlyContinue } while ($shouldRestart) # 执行MP3分割 $segments = $PartArr -join "," C:\ffmpeg\bin\ffmpeg.exe -i "C:\mp3\test.mp3" -f segment -segment_times $segments "C:\mp3\output_silc_%03d.mp3"
关键修改点
- 捕获进程对象:用
Start-Process -PassThru获取ffmpeg进程实例,方便调用Kill()终止进程 - 循环控制重启:通过
do-while循环和$shouldRestart标记,实现参数调整后的自动重启 - 实时输出读取:用
StreamReader实时读取ffmpeg输出,避免管道阻塞问题 - 参数修正:将原脚本的
1,10改为1.1,避免因系统地区格式导致的数值计算错误 - 变量初始化:补充
$PartArr和$StartPart的初始化,避免运行报错
内容的提问来源于stack exchange,提问作者TheRob87
相关产品推荐
相关产品推荐

