PowerShellで画像を扱う
投稿:2023-04-01
PowerShellでテキストからボイス作って一枚絵に加えて動画を作る処理を書きました。 ところが、一枚絵のファイル形式やサイズにより上手く処理できないケースが出てきました。 そこでできる限りオールマイティに処理できるよう、色々と工夫してみます。
- JPEGかPNGを選択可
- PNGをJPEGに変換
- VoicePeakをコマンドラインで使用
- JPEG変換でピクセルフォーマットをyuvj420p
- 画像処理にライブラリ(?)のSystem.Drawing
- 画像の解像度がフルHDより大きい場合は縦横比を変えずに収まるよう縮小
- 解像度の縦または横が奇数ピクセル数の場合は強制的に1減らして偶数に(動画エンコードの都合)
- モノラル音声を読み込む際の警告を抑止
# 【注意】powershellはBOM必要
# 静止画にボイスをつけてmp4を生成
add-type -AssemblyName System.Drawing
if (1 -ne $args.Length) {
Write-Output "画像ファイルを1個だけ選択してください。"
Pause
Exit
}
$extension = (Get-Item -Path $args[0]).Extension
if (".jpg" -ne $extension -and ".png" -ne $extension) {
Write-Output "JPEGかPNGを選択してください。"
Pause
Exit
}
$graph_path = $args[0]
Write-Output "画像ファイル $graph_path"
$wav_path = [System.IO.Path]::ChangeExtension($graph_path, ".wav")
Write-Output "WAVEファイル $wav_path"
$mp4_path = [System.IO.Path]::ChangeExtension($graph_path, ".mp4")
Write-Output "MP4ファイル $mp4_path"
if (".jpg" -eq $extension) {
$jpg_path = $graph_path
} elseif (".png" -eq $extension) {
$jpg_path = [System.IO.Path]::ChangeExtension($graph_path, ".jpg")
Write-Output "PNGからJPEGファイルに変換"
Write-Output "JPEGファイル $jpg_path"
$ArgList =
"-loglevel", "warning",
"-y",
"-i", $graph_path,
"-update", 1,
"-pix_fmt", "yuvj420p",
$jpg_path
Start-Process -Wait -NoNewWindow -FilePath "ffmpeg" -ArgumentList $ArgList
}
if (!(Test-Path -Path $jpg_path)) {
Write-Output "JPEGファイルがありません。"
Pause
Exit
}
$text = Read-Host "ボイスを入力してください"
if (0 -lt $text.Length) {
Write-Output "音声を生成"
&"voicepeak" --say "$text" --out $wav_path --narrator "Japanese Male 3" --emotion happy=100,fun=100,angry=0,sad=0 | Out-Null
}
if (Test-Path -Path $wav_path) {
Write-Output "動画を生成"
$image = [System.Drawing.Image]::FromFile($jpg_path)
$width = $image.Width
$height = $image.Height
Write-Output "縮小前サイズ $width x $height"
if (1920 -lt $width) {
$height *= (1920 / $width)
$width = 1920
}
if (1080 -lt $height) {
$width *= (1080 / $height)
$height = 1080
}
$width = [Math]::Floor($width)
if (1 -eq $width % 2) {
$width--
}
$height = [Math]::Floor($height)
if (1 -eq $height % 2) {
$height--
}
Write-Output "縮小後サイズ $width x $height"
$ArgList =
"-loglevel", "warning",
"-y",
"-i", $jpg_path,
"-guess_layout_max", "0",
"-i", $wav_path,
"-filter_complex", "[0:v]scale=width=${width}:height=${height}[video];[1:a]channelmap=0|0[audio]",
"-map", "[video]",
"-map", "[audio]",
$mp4_path
Start-Process -Wait -NoNewWindow -FilePath "ffmpeg" -ArgumentList $ArgList
Write-Output "音声を削除"
Remove-Item -Path $wav_path
}
if (Test-Path -Path $mp4_path) {
Write-Output "動画を再生"
Start-Process -FilePath $mp4_path
}
Pause