PowerShell中实现ffmpeg进程输出停滞时自动重启的可行性咨询
PowerShell中实现ffmpeg进程输出停滞时自动重启的可行性咨询
当然可以实现!这种监控进程输出并自动重启的需求在PowerShell里完全能搞定,我给你梳理下思路和具体的实现方案,你可以直接参考调整。
首先核心思路很清晰:我们需要启动ffmpeg后实时跟踪它的输出,记录最后一次有新输出的时间,如果超过5秒没新内容,就判定为停滞,然后杀掉进程重新启动录制。
给你写了一个可直接用的PowerShell脚本框架,注释都标清楚了:
# 配置参数 $audioDevice = "Microphone (USB Microphone)" # 按时间戳生成输出文件,避免每次重启覆盖之前的录制 $outputPathTemplate = "C:\Your\Recording\Path\recording_{0:yyyyMMdd_HHmmss}.mp3" $stallThreshold = 5 # 输出停滞的判定阈值(秒) # 无限循环,直到手动停止脚本 while ($true) { $currentOutputPath = $outputPathTemplate -f (Get-Date) Write-Host "[$(Get-Date)] 开始新的录制,输出文件: $currentOutputPath" # 启动ffmpeg进程,把输出和错误流重定向到临时日志文件 # 加-loglevel info和-flush_packets 1是为了强制ffmpeg实时输出日志,避免缓冲导致误判 $ffmpegProcess = Start-Process ffmpeg -ArgumentList @( "-f", "dshow", "-i", "audio=`"$audioDevice`"", "-y", "-t", "00:10:00", "-b:a", "128k", "-loglevel", "info", "-flush_packets", "1", $currentOutputPath ) -PassThru -NoNewWindow -RedirectStandardOutput ".ffmpeg_out.tmp" -RedirectStandardError ".ffmpeg_err.tmp" # 初始化最后一次输出的时间 $lastOutputTime = Get-Date # 启动后台作业,持续读取ffmpeg的输出日志,更新最后活动时间 $monitorJob = Start-Job -ScriptBlock { param($outLogPath, $errLogPath) # 循环读取日志直到进程结束 while ($true) { # 检查标准输出日志 if ((Get-Item $outLogPath).Length -gt 0) { $reader = New-Object System.IO.StreamReader($outLogPath) # 读取所有未读过的内容 while ($line = $reader.ReadLine()) { Write-Output "ffmpeg输出: $line" # 更新最后活动时间到临时文件 (Get-Date).ToString("o") | Out-File ".last_activity.tmp" -Force } $reader.Close() } # 检查错误输出日志 if ((Get-Item $errLogPath).Length -gt 0) { $reader = New-Object System.IO.StreamReader($errLogPath) while ($line = $reader.ReadLine()) { Write-Warning "ffmpeg错误: $line" (Get-Date).ToString("o") | Out-File ".last_activity.tmp" -Force } $reader.Close() } # 每秒轮询一次,避免占用过多CPU Start-Sleep -Seconds 1 } } -ArgumentList ".ffmpeg_out.tmp", ".ffmpeg_err.tmp" # 主监控循环,检查进程状态和输出停滞情况 while (-not $ffmpegProcess.HasExited) { # 读取最后一次活动时间 if (Test-Path ".last_activity.tmp") { $lastOutputTime = [DateTime](Get-Content ".last_activity.tmp" -Raw) } # 计算距离最后一次输出的时间差 $elapsedSeconds = (Get-Date) - $lastOutputTime if ($elapsedSeconds.TotalSeconds -ge $stallThreshold) { Write-Warning "[$(Get-Date)] 警告:ffmpeg输出已停滞超过$stallThreshold秒,准备重启录制..." # 强制终止ffmpeg进程和监控作业 $ffmpegProcess | Stop-Process -Force -ErrorAction SilentlyContinue Stop-Job $monitorJob -ErrorAction SilentlyContinue Remove-Job $monitorJob -ErrorAction SilentlyContinue # 清理临时文件 Remove-Item -Path ".ffmpeg_out.tmp", ".ffmpeg_err.tmp", ".last_activity.tmp" -ErrorAction SilentlyContinue # 跳出当前监控循环,回到外层循环重启录制 break } # 如果进程正常结束,也清理资源准备下一次录制 if ($ffmpegProcess.HasExited) { Write-Host "[$(Get-Date)] ffmpeg本次录制正常结束,退出代码: $($ffmpegProcess.ExitCode)" Stop-Job $monitorJob -ErrorAction SilentlyContinue Remove-Job $monitorJob -ErrorAction SilentlyContinue Remove-Item -Path ".ffmpeg_out.tmp", ".ffmpeg_err.tmp", ".last_activity.tmp" -ErrorAction SilentlyContinue # 正常结束后短暂休眠再重启,避免频繁启动 Start-Sleep -Seconds 2 } # 主监控循环每0.5秒检查一次 Start-Sleep -Milliseconds 500 } }
这里有几个关键点需要注意:
- 我给ffmpeg加了
-loglevel info和-flush_packets 1参数,目的是强制ffmpeg实时刷新输出,避免它因为缓冲机制导致输出延迟,误判为停滞 - 每次重启都会生成带时间戳的输出文件,不会覆盖之前的录制内容,你可以根据自己的需求修改输出路径的模板
- 用后台作业来读取输出日志,主循环负责监控时间差,这样不会因为读取输出阻塞整个脚本
- 临时文件的清理逻辑也加了,避免异常退出后残留文件影响下次监控
你可以根据自己的实际环境调整参数,比如修改停滞阈值、输出目录、音频设备名称这些。如果需要更精细的错误处理,还可以加一些比如检查进程是否真的存在、处理权限问题的逻辑。
总之完全能实现你要的功能,这个脚本可以直接作为基础来用~
备注:内容来源于stack exchange,提问作者丶 Limeー来夢 丶
相关产品推荐
相关产品推荐

