🗂

【ffmpeg】 HEICを変換するコマンド

に公開

iPhoneとかで画像を撮ったら出力されるのが.HEIC

このファイルには

  • 低解像度のプレビュー用画像
  • 効率的に表示するためにいくつものタイルに分割された本体画像

が存在するので、正しくコマンドを打たないとプレビュー用画像の方が出力されてしまいます。

今回はそんなめんどくさいHEICファイルを一発で変換するスクリプトを作りました。

main.ps1

# --- 設定項目 ---
$inputFile = "IMG_5440.HEIC"
$outputFile = "converted\output.png"


# 1. 最終的な画像サイズを取得
Write-Host "Step 1: 最終的な画像サイズを取得中..."
$ffmpegInfo = ffmpeg -i $inputFile 2>&1
$match = $ffmpegInfo | Select-String -Pattern 'Tile Grid:.*?(\d{3,})x(\d{3,})'
if (-not $match) { throw "タイルの解像度が見つかりませんでした。" }
$finalWidth = $match.Matches[0].Groups[1].Value
$finalHeight = $match.Matches[0].Groups[2].Value
Write-Host "  -> 発見した解像度: ${finalWidth}x${finalHeight}"


# 2. タイルの情報(数とサイズ)を取得
Write-Host "Step 2: タイルの情報を取得中..."
$probeJson = ffprobe -v quiet -print_format json -show_streams $inputFile | ConvertFrom-Json
$firstTile = ($probeJson.streams | Where-Object { $_.codec_type -eq 'video' })[0]
$mainTiles = $probeJson.streams | Where-Object { $_.codec_type -eq 'video' -and $_.width -eq $firstTile.width -and $_.height -eq $firstTile.height }
$tileCount = $mainTiles.Count
$tileWidth = $firstTile.width
$tileHeight = $firstTile.height
Write-Host "  -> メインタイルの数: $tileCount, タイルサイズ: ${tileWidth}x${tileHeight}"


# 3. グリッドのレイアウトを計算する
Write-Host "Step 3: グリッドレイアウトを計算中..."
$gridCols = [Math]::Ceiling($finalWidth / $tileWidth)
$gridRows = [Math]::Ceiling($finalHeight / $tileHeight)
$grid = "${gridCols}x${gridRows}"
Write-Host "  -> 計算したグリッド: $grid"


# 4. filter_complex用の文字列を生成
Write-Host "Step 4: FFmpegフィルタグラフを生成中..."
$filterGraph = (-join (0..($tileCount-1) | ForEach-Object { "[0:v:$_]" }))


# 5. 最終的なffmpegコマンドを組み立てて実行
Write-Host "Step 5: 最終コマンドを組み立てて実行します..."
# xstackに :grid=$grid を追加
$ffmpegCommand = "ffmpeg -i `"$inputFile`" -filter_complex `"${filterGraph}xstack=inputs=${tileCount}:grid=${grid},crop=${finalWidth}:${finalHeight}:0:0[out]`" -map `"[out]`" -frames:v 1 `"$outputFile`""

Write-Host "実行コマンド:"
Write-Host $ffmpegCommand -ForegroundColor Cyan
Invoke-Expression $ffmpegCommand

Write-Host "処理が完了しました。"

一行のコマンドにしたい場合は多分;で区切ればいけます。

ちなみに

ちなみにimagemagickっていうツール使えば

magick image.heic output.png

だけでいけます^^

Discussion