【PowerShell】ffmpegでmp4をgifに変換する

Code

はじまり

リサちゃん
リサちゃん

GIFにしたいよなあ。

135ml
135ml

軽くしたいよなあ。

mp4をgifに変換したい。

動画として何かしらを残しておきたい時、音声フォーマットは要らないんだよなあ。という時があります。

つまり、MP4じゃなくていい、GIFでいい。

というわけで今回は、PowerShellからmp4ファイルをgifファイルに変換していきたいと思います。

ffmpegで変換していく。

今回、mp4からgifにファイルを変換するために、「ffmpeg」のライブラリを使っていきます。情報は沢山出てきました。定番みたいですね。

FFmpeg

ffmpegは様々なパッケージ管理ライブラリからインストールできます。今回は、Scoopからインストールしていきます。

scoop update
scoop install ffmpeg

そして、ffmpegでファイルを変換していきます。実行するバッチファイルはこんな感じです。

@echo off
setlocal enabledelayedexpansion

echo "%1"

:: Check if space is contained.
set "filePath=%~1"
echo "Check if the source file name contains SPACE characters. That causes a bug."
set /p tmp="The process is starting. Input any key."

Start /WAIT Powershell -Windowstyle Normal -NoProfile -ExecutionPolicy Unrestricted -File ".\Z5-5_convert_mp4_to_gif.ps1" %1 10 1080

:FINISH
set /p tmp="The process is terminated. Input any key."

endlocal

PowerShellファイルの中身はこんな感じです。

ffmpegの-vfオプションを「"split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse"」と指定すると、高画質に出力されます。しかし、サイズがかなり大きくなります。逆に、「"scale=1920:-1"」という感じで指定すると、アスペクト比を維持しながら出力して、画質は悪くなりますがサイズがかなり減らせます。

function Convert-Mp4ToGif([string]$srcMovieAbsName, [Int32]$loop, [Int32]$fps, [Int32]$imgWidth) {
  <#
    .Synopsis
      Converts an input video into an animated GIF
    .Description
      Converts an input video into a high-quality animated GIF.
      Supported extensions are mp4, mkv.
    .INPUTS
      System.String # Path to the source MP4 file.
      System.Int32 # 0: output GIF with loops forever. -1: output GIF with no loops.
      System.Int32 # FPS of the output GIF.
      System.Int32 # Width of the output GIF. 0: Outputs with higher quality with default width.
    .Example
      Convert-Mp4ToGif -srcMovieAbsName "C:\path\to\video.mp4" -fps 30
      Get-ChildItem -Path "C:\path\to\videos" -Filter "*.mp4" | ForEach-Object { Convert-Mp4ToGif -srcMovieAbsName $_.FullName -loop 0 -fps 15 -imgWidth 0 }
      Get-ChildItem -Path "C:\path\to\videos" -Filter "*.mkv" | ForEach-Object { Convert-Mp4ToGif -srcMovieAbsName $_.FullName -loop 0 -fps 15 -imgWidth 0 }
    .Link
      Nothing.
    .Notes
      Enjoy.
  #>
  Write-Host ("{0}: converting mp4 to gif.`n" -f $MyInvocation.MyCommand.Name);
  Write-Output "Input: $srcMovieAbsName";
  $srcFile = Get-Item -Path $srcMovieAbsName;
  Write-Output "{0}" -f $srcFile.BaseName;

  $dstExt = ".gif";
  $srcFileDirectory = Split-Path $srcFile.FullName
  $dstMovieAbsName = "{0}\{1}{2}" -f $srcFile.Directory, $srcFile.BaseName, $dstExt;
  Write-Host ("{0}: destination decided.`n" -f $MyInvocation.MyCommand.Name);
  Write-Output "directory: $srcFileDirectory"
  Write-Output "destination to output: $dstMovieAbsName"

  $vfStr = "split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse";
  if ($imgWidth -ne 0){
    $vfStr = "scale={0}:-1" -f $imgWidth;
  }
  ffmpeg -i "$srcMovieAbsName" -vf $vfStr -r $fps -loop $loop $dstMovieAbsName;
  Write-Host ("{0}: finished converting mp4 to gif.`n" -f $MyInvocation.MyCommand.Name);

  return $dstMovieAbsName;
}


$targetFolder = (Get-Location).Path;
$srcMovieAbsName = $Args[0];
$dstFps = $Args[1];
$dstImgWidth = $Args[2];
Write-Host ("{0}: destination decided.`n" -f $MyInvocation.MyCommand.Name);
Write-Output "srcMovieAbsName: $srcMovieAbsName"
if ($srcMovieAbsName.Contains(" ")) {
  $tmp = Read-Host "Source file name contains space characters. Input 'y' to cancel this process.";
  return;
}
if (-not $srcMovieAbsName.Contains(".")) {
  $tmp = Read-Host "Source file name does not contain a dot as extension. Input 'y' to cancel this process.";
  return;
}

Convert-Mp4ToGif $srcMovieAbsName 0 $dstFps $dstImgWidth;

$tmp = Read-Host "Input 'y' to move source files and terminate this process......";
If ($tmp -eq "y") {
  $folderName = ".\5_original_files";
  If (!(Test-path $targetFolder\$folderName)) {
    New-Item -Name $folderName -ItemType Directory;
  }
  # Move-Item -Path .\*.mp4 -Destination $folderName -Exclude *$suffix*;
}

変換されたGIFはこんな風に動きました。FPS10です。

まとめ

今回の記事では、ffmpegライブラリを使って、mp4をgifに変換する流れを紹介しました。

これで動画を手頃なサイズで共有できるようになりましたね。

PowerShell関連記事

その他のPowerShell関連の記事を貼っておきます。

おしまい

リサちゃん
リサちゃん

軽くなったなあ。

135ml
135ml

GIFになったなあ。

以上になります!

コメント

タイトルとURLをコピーしました