使用 PowerShell + ffmpeg 自动压缩视频(支持 CRF、无损、目标大小模式)

视频文件往往体积庞大,尤其是高分辨率或高码率的视频。如果你经常需要压缩视频以便存储、传输或分享,那么手动输入 ffmpeg 命令会很繁琐。本文将教你如何编写一个 PowerShell 自动化脚本,智能选择压缩参数,支持以下模式:

前提:需要安装Windows 安装 FFmpeg 新手教程(附环境变量配置)

  • 默认有损压缩(自动推荐 CRF)
  • 手动指定 CRF 值
  • 无损压缩
  • 目标大小模式(指定目标文件大小,自动计算码率)

🔧 背景知识

什么是 CRF?

  • CRF (Constant Rate Factor) 是 ffmpeg 在使用 libx264libx265 编码时的一种恒定质量模式。
  • 范围: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 值
  • 无损压缩(保留原始质量)
  • 目标大小模式(精确控制输出文件大小)
相关推荐
香蕉ai大玩家2 小时前
ffmpeg.dll丢失怎么办?ffmpeg.dll找不到是什么情况
ffmpeg
The_cute_cat2 小时前
FFmpeg的初步学习
学习·ffmpeg
赖small强16 小时前
【音视频开发】Linux UVC (USB Video Class) 驱动框架深度解析
linux·音视频·v4l2·uvc
赖small强16 小时前
【音视频开发】ISP流水线核心模块深度解析
音视频·isp·白平衡·亮度·luminance·gamma 校正·降噪处理
赖small强17 小时前
【音视频开发】Linux V4L2 (Video for Linux 2) 驱动框架深度解析白皮书
linux·音视频·v4l2·设备节点管理·视频缓冲队列·videobuf2
mortimer17 小时前
视频自动翻译里的“时空折叠”:简单实用的音画同步实践
python·ffmpeg·aigc
未央几许17 小时前
使用ffmpeg.wasm解码视频(avi,mpg等格式)问题
前端·ffmpeg
ACP广源盛1392462567320 小时前
GSV2712@ACP#2 进 1 出 HDMI 2.0/Type-C DisplayPort 1.4 混合切换器 + 嵌入式 MCU
单片机·嵌入式硬件·计算机外设·音视频
AI周红伟21 小时前
通义万相开源14B数字人Wan2.2-S2V!影视级音频驱动视频生成,助力专业内容创作
音视频