[ PC系セットアップ覚書 Top]

PC系セットアップ覚書

2011年まで「俺的な非 UN*X 環境をめざして」という題でしたが、 「UNIX系」と「非UNIX系」の区別がだんだん難しくなってきましたので、 あれこれ区別しないことにしました(^_^;


[前] Googleフォトの保存容量を減らす 2022/06c

[FFmpeg 覚書] 分割動画(m3u8)作成 2022/06b

[Table of Contents]

はじめに

動画をWWW などを使って公開する場合。サイトによっては1ファイルサイズの 上限が決まっていて(たとえば上限1MBなど)、それでは動画置けないじゃん! なんて こともあると思います。そういうときは YouTube を使うなどの方法もあると思いますが、 1分程度の長さの動画を、それも全部で1〜2個程度紹介する程度だった場合、 それでわざわざ YouTube 使うのは億劫‥なんて場合です。

[Table of Contents]

HLS(HTTP Live Streaming)形式で動画分割

そんなときは動画を分割する方法が使えます。 たとえば動画 IN.mp4 (68秒)を分割する方法は以下:

% ffmpeg -i IN.mp4 -c:a copy -f hls -hls_time 10 -hls_playlist_type vod -hls_segment_filename "sample-%%3d.ts" sample.m3u8
こんな感じで動画を分割することができます(hls系のオプション群は現状あちこちの サイトからの受け売りですw; segment 系のオプションでも同じようなことができる みたいですけど、違いがわからない‥)。

上の例では -hls_time 10 としていますが、 これで「動画を10秒ほどで区切れ」と指定しています。 分割した動画のファイル名は "sample-%%3d.ts" のところで指定していて、 分割された順に %%3d のところが 000,001,002,... という感じで番号に変換された ファイル名が付きます。また分割された動画ファイルのプレイリスト(?)な感じの ファイル名をここでは sample.m3u8 と指定しています。分割された動画を再生するときは m3u8 に対応した動画プレーヤ、たとえば VLC などでこの sample.m3u8 を再生すると 分割された動画ファイル群をひとつの動画のように再生することができます。

分割の結果、 それぞれの動画のファイルサイズが思ったほど小さくならないこともあると思います。 そのときは動画の表示サイズを調整する -vf オプションを使って -vf scale=-2:350 のようにしてみたり、あるいは -hls_time で指定する数字をもっと小さい数字、 つまりそれぞれの分割動画の秒数を少なくする感じに調整することができます。

[Table of Contents]

キーフレームの調整

‥でも。場合によっては思ったように動画を分割できない時もあると思います。 -hls_time 6 と指定した場合、分割される動画はだいたい6秒程度の長さになることが 期待されているのに、分割された各動画を見てみると 10秒以上に分割される動画がある! これじゃあ「ファイルサイズの上限」に引っかかるじゃん!! はあ?! 何それ??!! ‥という経験を、私はしました。

いろいろ調べてみると、どうやら -hls_time 6 を「6秒で動画を分割」と解釈したのは実は正しくなくて、 「指定された6秒のところを起点にして それより後にある 『キーフレーム』とかいうやつを探し、それが見つかった場所で動画を分割」 という動作をさせるオプションのようなのです。なので -hls_time 6 を指定しても、 指定箇所の4秒後まで行かないとキーフレームがない場合、動画の分割箇所が 6+4=10 で10秒後になってしまうようなのです。んー。

つまり。自分がイメージしたのに近い動画分割をするためには 「キーフレーム」というやつを適切な場所に設置してやる必要があるということです。 ‥‥てか、そもそも「キーフレーム」って何だ?! ということで検索してみた結果。 キーフレームについては以下がメッチャわかりやすかったです:

んでキーフレームの設定は GOP (Group of Picture) に関する設定項目、具体的には ffmpeg では -g オプションで指定可能のようです。 指定する値はどれくらいにすれば良いのか? ‥んー、正直言って、 さっぱりわかりません。なので あちこちのサイトを見てみる訳なんですけど、 fps の 5〜10倍程度が推奨されているようです。それだと 5〜10秒くらいの間隔で キーフレームが入るみたいですけど、今回の目的では5秒おきだと 分割動画の長さにかなりのバラつきが出てしまいますので、空けすぎです。 そこで元動画の fps (Frame per second; 1秒あたりのコマ数) を調べてみると 29.97 でしたので、その2倍程度の 60 を指定してみました。 これでキーフレームの間隔が約2秒おきになるはずです。 (でも、あちこちのサイト見ると -g で指定する数値のデフォルトは 12 みたいですけど、 それだと0.4秒おきくらいにキーフレームが入るはずで、そんな頻繁に入るものなの??)

[Table of Contents]

結果オーライ

というわけで。分割動画の長さをなるべく揃えるために -g オプションを追加して 以下:

ffmpeg -i IN.mp4 -vf scale=-2:350 -g 60 -c:a copy -f hls -hls_time 8 -hls_playlist_type vod -hls_segment_filename "sample-%%3d.ts" sample.m3u8
こんな感じに書いて実行してみたところ、だいたい思ったとおりに ファイルサイズが割と揃った感じで動画分割することができましたYO! (^o^)

再生すると右のような感じ:
(HTML への埋め込み方法については、 [ .hlsをブラウザ関係なく一発再生する “hls.js” ] という サイトで紹介されていたコードを基本丸ごとコピペ、細かいところをちょっと書き換えて 使用しました。)

最初から最後まで68秒の動画なんですけど。 サイズがそれぞれ 925, 949, 991, 948, 984, 873, 724, 431, 287 (すべて単位は KByte) となる 9 つの動画ファイルと、 1つの m3u8 ファイル(1KB) が作成されました。 どのファイルもサイズが1MB以下に収まってます。やったね。







[次] [FFmpeg 覚書] 動画変換 AVI に 2022/06a