You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:47:13