视频文件往往体积庞大,尤其是高分辨率或高码率的视频。如果你经常需要压缩视频以便存储、传输或分享,那么手动输入 ffmpeg 命令会很繁琐。本文将教你如何编写一个 PowerShell 自动化脚本,智能选择压缩参数,支持以下模式:
- 默认有损压缩(自动推荐 CRF)
- 手动指定 CRF 值
- 无损压缩
- 目标大小模式(指定目标文件大小,自动计算码率)
🔧 背景知识
什么是 CRF?
- CRF (Constant Rate Factor) 是 ffmpeg 在使用
libx264或libx265编码时的一种恒定质量模式。 - 范围:0--51
- 0 → 无损压缩(文件极大)
- 18--23 → 高质量(接近无损)
- 24--28 → 中等质量(常用压缩)
- 29+ → 低质量(极限压缩)
无损压缩
- 使用
-crf 0(H.264)或-x265-params lossless=1(H.265)。 - 文件体积通常不会比原始小很多,但保证质量不丢失。
目标大小模式
- 根据视频时长和目标大小计算码率:
目标码率 (kbps) = 目标大小 (MB) x 8 x 1024 / 时长 (秒) - 使用
-b:v设置视频码率,音频固定为128k。
📜 脚本源码:auto_compress.ps1
powershell
param(
[Parameter(Mandatory=$true)]
[string]$InputFile,
[Parameter(Mandatory=$true)]
[string]$OutputFile,
[Parameter(Mandatory=$false)]
[switch]$Lossless, # 是否启用无损压缩
[Parameter(Mandatory=$false)]
[int]$CRF, # 用户可手动指定 CRF 值
[Parameter(Mandatory=$false)]
[int]$TargetSizeMB # 目标大小 (MB)
)
# 检查 ffmpeg 是否可用
if (-not (Get-Command ffmpeg -ErrorAction SilentlyContinue)) {
Write-Host "错误: 未检测到 ffmpeg,请先安装并配置到 PATH。" -ForegroundColor Red
exit 1
}
# 获取视频信息
$info = & ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,bit_rate,duration -of default=noprint_wrappers=1 "$InputFile"
$width = ($info | Select-String "width=" | ForEach-Object { $_.ToString().Split("=")[1] })
$height = ($info | Select-String "height=" | ForEach-Object { $_.ToString().Split("=")[1] })
$fpsRaw = ($info | Select-String "r_frame_rate=" | ForEach-Object { $_.ToString().Split("=")[1] })
$bitrate = ($info | Select-String "bit_rate=" | ForEach-Object { $_.ToString().Split("=")[1] })
$duration = ($info | Select-String "duration=" | ForEach-Object { $_.ToString().Split("=")[1] })
# 计算帧率
$fpsParts = $fpsRaw -split "/"
if ($fpsParts.Count -eq 2) {
$fps = [math]::Round([double]$fpsParts[0] / [double]$fpsParts[1], 2)
} else {
$fps = [double]$fpsRaw
}
Write-Host "检测到视频: ${width}x${height}, ${fps}fps, 码率=${bitrate}bps, 时长=${duration}s"
# 判断压缩模式
if ($Lossless) {
# 无损压缩
$codec = "libx264"
$preset = "slow"
$extraParams = "-crf 0"
$audioCodec = "copy"
Write-Host "选择无损压缩: $codec $preset $extraParams, 音频=$audioCodec"
} elseif ($TargetSizeMB) {
# 目标大小模式
$targetBitrate = [math]::Round(($TargetSizeMB * 8 * 1024) / [double]$duration)
Write-Host "目标大小模式: 目标=$TargetSizeMB MB, 计算码率=$targetBitrate kbps"
$codec = "libx264"
$preset = "slow"
$extraParams = "-b:v ${targetBitrate}k"
$audioCodec = "aac -b:a 128k"
Write-Host "选择目标大小压缩: $codec $preset $extraParams, 音频=$audioCodec"
} else {
# 有损压缩,自动推荐 CRF
if ($CRF) {
$chosenCRF = $CRF
Write-Host "用户指定 CRF=$chosenCRF"
} else {
if ([int]$width -ge 1920 -or [int]$bitrate -ge 4000000) {
$chosenCRF = 23
} elseif ([int]$width -ge 1280 -or [int]$bitrate -ge 2000000) {
$chosenCRF = 26
} else {
$chosenCRF = 28
}
Write-Host "自动推荐 CRF=$chosenCRF"
}
$codec = "libx264"
$preset = "slow"
$extraParams = "-crf $chosenCRF"
$audioCodec = "aac -b:a 128k"
Write-Host "选择有损压缩: $codec $preset $extraParams, 音频=$audioCodec"
}
# 执行压缩
$ffmpegCmd = "ffmpeg -i `"$InputFile`" -c:v $codec -preset $preset $extraParams -c:a $audioCodec `"$OutputFile`""
Write-Host "执行命令: $ffmpegCmd"
& cmd /c $ffmpegCmd
# 显示文件大小对比
$origSize = (Get-Item $InputFile).Length
$newSize = (Get-Item $OutputFile).Length
Write-Host "原始大小: $([math]::Round($origSize/1MB,2)) MB"
Write-Host "压缩后大小: $([math]::Round($newSize/1MB,2)) MB" -ForegroundColor Green
🚀 使用方法
-
默认有损压缩(自动推荐 CRF)
powershell./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -
指定 CRF 值(例如 CRF=24,高质量)
powershell./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -CRF 24 -
无损压缩
powershell./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -Lossless -
目标大小模式(例如目标 100MB)
powershell./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -TargetSizeMB 100
📌 总结
这个脚本让你在 Windows 下用 PowerShell 一键压缩视频,支持:
- 自动推荐 CRF 值(智能选择质量与体积平衡)
- 手动指定 CRF 值
- 无损压缩(保留原始质量)
- 目标大小模式(精确控制输出文件大小)