使用PowerShell和ffmpeg编写一个自动压缩视频脚本

作者:

文章目录
  • 视频文件往往体积庞大,尤其是高分辨率或高码率的视频。如果你经常需要压缩视频以便存储、传输或分享,那么手动输入 ffmpeg 命令会很繁琐。本文将教你如何编写一个 PowerShell 自动化脚本,智能选择压缩参数,支持以下模式: 默认有损压缩(自动推荐 CRF) 手动指定 CRF 值 无损压缩 目标大小模式(指定目标文件大小,自动计算码率)
  • 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) ./auto_compress.ps1 -InputFile “input.mp4” -OutputFile “output.mp4” 指定 CRF 值(例如 CRF=24,高质量) ./auto_compress.ps1 -InputFile “input.mp4” -OutputFile “output.mp4” -CRF 24 无损压缩 ./auto_compress.ps1 -InputFile “input.mp4” -OutputFile “output.mp4” -Lossless 目标大小模式(例如目标 100MB) ./auto_compress.ps1 -InputFile “input.mp4” -OutputFile “output.mp4” -TargetSizeMB 100
  • 这个脚本让你在 Windows 下用 PowerShell 一键压缩视频,支持: 自动推荐 CRF 值(智能选择质量与体积平衡) 手动指定 CRF 值 无损压缩(保留原始质量) 目标大小模式(精确控制输出文件大小) 到此这篇关于使用PowerShell和ffmpeg编写一个自动压缩视频脚本的文章就介绍到这了,更多相关PowerShell ffmpeg自动压缩视频内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: PowerShell和FFmpeg查找Windows中所有损坏音频文件 使用PowerShell实现视频抽帧的完全指南 使用PowerShell实现定时播放视频和音频文件
  • 目录
    • 引言
    • 背景知识
      • 什么是 CRF?
      • 无损压缩
      • 目标大小模式
    • 脚本源码:auto_compress.ps1
      • 使用方法
        • 总结

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

          • 默认有损压缩(自动推荐 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

          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)

          ./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4"
          

          指定 CRF 值(例如 CRF=24,高质量)

          ./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -CRF 24
          

          无损压缩

          ./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -Lossless
          

          目标大小模式(例如目标 100MB)

          ./auto_compress.ps1 -InputFile "input.mp4" -OutputFile "output.mp4" -TargetSizeMB 100
          

          这个脚本让你在 Windows 下用 PowerShell 一键压缩视频,支持:

          • 自动推荐 CRF 值(智能选择质量与体积平衡)
          • 手动指定 CRF 值
          • 无损压缩(保留原始质量)
          • 目标大小模式(精确控制输出文件大小)

          到此这篇关于使用PowerShell和ffmpeg编写一个自动压缩视频脚本的文章就介绍到这了,更多相关PowerShell ffmpeg自动压缩视频内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • PowerShell和FFmpeg查找Windows中所有损坏音频文件
          • 使用PowerShell实现视频抽帧的完全指南
          • 使用PowerShell实现定时播放视频和音频文件

          站内搜索