はじまり
これ、音声は要らんのよなあ
gifかwebpにしたら減らせるのだろうか
動画のサイズを小さくしたい。
mp4ファイルって重いですよね・・・。
ということで、動画のサイズをなんとか小さく出来ないものかと色々試行錯誤した結果をまとめてみました。今回は音声をサポートしていない拡張子(.gifおよび.webp)によるアニメーションに変換することで、ファイルサイズを小さくしていこうと思います。
今回使う変換方法
今回、動画を別の拡張子に変換するために使った方法は、「ffmpeg」と「gif2webp」のパッケージです。
WindowsであればどちらのパッケージもScoopからインストールすることが可能です。
cd C:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
$username = (Get-ChildItem Env:USERNAME).Value; Set-Location "C:\Users\$username\Downloads\picture_backup";
scoop update
scoop install libwebp
scoop install ffmpeg
ffmpeg
「ffmpeg」は、メディアファイルを別のメディアファイルに変換するパッケージです。かなり昔から使われているみたいです。
gif2webp
「gif2webp」は、Google公式の「libwebp」の機能群の一部のパッケージです。GIFアニメーションからWebpアニメーションを生成することが出来ます。
今回使う動画素材
そしてちなみに、今回変換に使ったmp4の動画は、以前にアズールレーン公式がX(旧Twitter)から表現内容を修正するように依頼されたプロモーション動画をスクリーン録画したものです。動画だとちょっと重いので冒頭のスクショだけ。
変換結果のまとめ
今回色々試した結果が以下の表になります。
No | 変換用コマンド | 元ファイル | 変換後の拡張子 | 変換後のサイズ(MB) | 画質 | フレーム |
---|---|---|---|---|---|---|
1 | – | mp4動画 (1920×1080, 60fps) | mp4 | 89 | そのまま | |
2 | ffmpeg -i "$srcMovieAbsName" -vf split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 1,413 | 劣化なし。 | 再生速度が遅い。 |
3 | ffmpeg -i "$srcMovieAbsName" -vf split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse -r 30 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 767 | 劣化なし。 | 変わらない。 |
4 | ffmpeg -i "$srcMovieAbsName" -vf scale=1920:-1 -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 341 | 少し劣化する。 | 再生速度が遅い。 |
5 | ffmpeg -i "$srcMovieAbsName" -vf scale=1920:-1 -r 30 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 276 | 少し劣化する。 | 変わらない。 |
6 | ffmpeg -i "$srcMovieAbsName" -vf scale=1080:-1 -r 30 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 93 | 劣化する。 | 変わらない。 |
7 | ffmpeg -i "$srcMovieAbsName" -vf split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | webp | 223 | 少し劣化する。 | 抜けるフレームが散見された。 |
8 | ffmpeg -i "$srcMovieAbsName" -vf scale=1920:-1 -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | webp | 72 | かなり劣化する。アーティファクトが残ってしまう。 | 変わらない。 |
9 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName | 3のGIF | webp | 576 | 劣化なし。 | 抜けるフレームがあった。 |
10 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmin 9 -kmax 17 | 3のGIF | webp | 576 | 劣化なし。 | 抜けるフレームがあった。 |
11 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmin 6 -kmax 13 | 3のGIF | webp | 575 | 劣化なし。 | 抜けるフレームがあった。 |
12 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmin 3 -kmax 5 | 3のGIF | webp | 566 | 劣化なし。 | 抜けるフレームがあった。 |
13 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName | 2のGIF | webp | 1,101 | 劣化なし。 | 再生速度が遅い。 |
14 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmin 3 -kmax 5 | 2のGIF | webp | 1083 | ほぼ劣化なし。 | 再生速度が遅い。 |
15 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName | 4のGIF | webp | 285 | 劣化する。 | 再生速度が遅い。 |
16 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName | 5のGIF | webp | 220 | 少し劣化する。 | 抜けるフレームがあった。 |
17 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmax 0 | 2のGIF | webp | 1,111 | 劣化なし。 | 再生速度が遅い。 |
18 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmax 1 | 2のGIF | webp | 1,015 | 劣化なし。 | 再生速度が遅い。 |
19 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmax 0 | 3のGIF | webp | 582 | 劣化なし。 | 抜けるフレームが散見された。 |
20 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmax 1 | 3のGIF | webp | 508 | 劣化なし。 | 抜けるフレームが散見された。 |
21 | ffmpeg -i "$srcMovieAbsName" -lavfi "scale=1920:-1,setpts=PTS/2" -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 277 | 少し劣化する。 | 変わらない。 |
22 | ffmpeg -i "$srcMovieAbsName" -lavfi "split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse,setpts=PTS/2" -r 60 -loop 0 $dstMovieAbsName; | mp4動画 (1920×1080, 60fps) | gif | 768 | 劣化なし。 | 少し遅い? コンマ秒レベル。 |
23 | gif2webp "$srcMovieAbsName" -o $dstMovieAbsName -kmax 1 | 22のGIF | webp | 508 | 劣化なし。 | 少し遅い? コンマ秒レベル。 |
24 | ffmpeg -i "$srcMovieAbsName" -vf split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse -r 60 -loop 0 $dstMovieAbsName; | 22のGIF | webp | エラーになる | エラーになる | エラーになる |
25 | ffmpeg -i "$srcMovieAbsName" -lavfi split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse -r 60 -loop 0 $dstMovieAbsName; | 22のGIF | webp | エラーになる | エラーになる | エラーになる |
26 | $itsScale = "[float](1 / 2)"; ffmpeg -i "$srcMovieAbsName" -vf scale=1920:-1 -r 60 -loop 0 $dstMovieAbsName -itsscale $itsScale | mp4動画 (1920×1080, 60fps) | gif | 341 | 劣化なし。 | 再生速度が遅い。(なぜだ。) |
27 | $itsScale = "[float](1 / 2)"; ffmpeg -i "$srcMovieAbsName" -vf scale=1920:-1 -r 60 -loop 0 $dstMovieAbsName -itsscale $itsScale | mp4動画 (1920×1080, 60fps) | webp | 72 | かなり劣化する。アーティファクトが残ってしまう。 | 抜けるフレームがあった。再生速度は変わらない。(なぜだ。) |
上記の表を踏まえて、以下の所感を得ました。
- 同じアスペクト比で幅が半分以下になる画質かつノイズが入るのを許容できないのであれば、MP4からGIFへの変換はオススメじゃない。
- GIFアニメーションからWebpアニメーションに変換すると、画質を落とさずにファイルサイズを減らせる。
ffmpeg
ffmpegでは、mp4ファイルをgifもしくはwebpに変換することが可能です。そして、フィールドに対する設定値の詳細は以下の通りです。
- 基本的に、
-vf
フィールドにsplit[s0][s1];[s0]palettegen[p];[s1][p]paletteuse
を指定すると変換時間が長くなりサイズが大きくなる。その代わり、画質の劣化が発生しない。(この指定の仕方は「グローバルパレット」と呼ぶらしい。) -vf
フィールドにscale=1920:-1
を指定すると、アスペクト比を変えずに幅の値を変えることが出来る。そして、変換時間が短くなりサイズを減らせるが、画質の劣化が発生する。-lavfi
フィールドにsetpts=PTS/2
という風に指定すると、出力されるGIFを2倍速に出来る。- ちなみに、
-itsscale
フィールドで倍速指定しても、なぜか倍速にならなかった。「$itsScale = “[float](1 / 2)”; ffmpeg -i "$srcMovieAbsName" -vf $vfStr -r $fps -loop $loop $dstMovieAbsName -itsscale $itsScale
」という風に指定したのだが。(26の記録)
同じアスペクト比で動画の幅を半分にすれば、元の動画よりも少ないサイズに出来そうです。しかし、そうなると変換後の方がサイズに対する画質のコスパが悪いですね・・・。
gif2webp
gif2webpでは、gifファイルをwebpに変換することが可能です。ffmpegで少ない欠損で変換したgifを変換しました。そして、フィールドに対する設定値の詳細は以下の通りです。
-kmin
フィールドおよび-kmax
フィールドの詳細を公式リファレンスから抜粋して、llama-3.1-nemotron-70b-instructに和訳してもらいました。
kmin = 9、kmax = 17
で変換すると無損失圧縮になり、kmin = 3、kmax = 5
で変換すると有損圧縮になるみたいですね。しかし、個人的にはあまり画質に変わりはなかったので、どちらかというとkmin = 3、kmax = 5
の方が良いでしょうか。また、-kmax 1
の方が-kmax 0
より少しだけサイズを減らせます。その二者間の画質の違いにもあまり差はありません。
まとめ
今回は、ffmpegとgif2webpを使って、.mp4ファイルから.gifもしくは.webpの拡張子に変換して、サイズを減らす試みでした。
ffmpegのリファレンスはここにあります。さらに詳細に設定できるかもしれません。
音声をサポートしていない拡張子に変換すればファイルサイズを減らせると思ったのですが、そういうことでもありませんでした。ムズカシイですねぇ。
おしまい
あんまり減らせないかあ
難しかったか・・・。
以上になります!
コメント