明滅するプログラマの思索

WEBエンジニアとして勤務している一介の男が、日々気づいたことをまとめるブログです

PHPのMediaInfoパッケージを利用してHLS用に動画分割する

HTTP Live Streaming を実装する際、もともとの動画ファイルを分割し、プレイリストファイル(m3u8)を作成する必要があります。

HLS(HTTP Live Streaming) を構築する - 明滅するプログラマの思索

で分割する流れをまとめてありますが、今回はこれをPHPで自動化します。

導入環境

ソフトウェア バージョン
CentOS 6.8
PHP 5.6

MediaInfo インストール

まずはさまざまなメディアファイルの情報を取得できるツールmediainfoをインストールします。 CentOS なら yum を使って簡単にインストールできます。

yum install -y mediainfo libmediainfo

mediainfo のツールを入れたら、これをPHPで簡単に扱えるようにするラッパーをインストールします。 今回は composer で入れてしまうことにします。 composer の使い方については、たくさんの記事がネット上にありますので今回は触れません。

vi composer.json
# 以下を追記
 "mhor/php-mediainfo": "*"
composer update

これで PHP 上で MediInfo を使うための準備が整いました。

ffmpeg に必要なパラメータを取得して、コマンドを整形する

動画ファイルの分割に必要なパラメータは主に以下のようなものです。

これらを MediaInfo クラスで取得します。 MediaInfo クラスは getInfo() メソッドでファイルパスを渡すと、ファイルを解析して動画部分と音声部分の情報を取得できるようになります。 動画ファイルの情報を取得したら、ffmpeg コマンドのオプションにそれぞれ指定して、実行すれば分割処理を行うことができます。 以下はそのサンプルです。

<?php
// composer パッケージのオートロード
require_once('vendor/autoload.php');

// ffmpeg のコマンドパス
$ffmpeg_path = '/usr/local/bin/ffmpeg';
// プリセットファイル
$ffmpeg_preset_filepath = '/home/movies/lib/libx264-hls.ffpreset';
// 分割秒数
$segment_tile = 10;

// 動画ファイルの置き場所は固定にしときます
$filedir = "/home/movies";

// 引数でファイル名を渡すことにします
$file = @$argv[1];

// ファイルが見つからなければ終了
$filepath = $filedir . "/" . $file;
if (is_file($filepath) === false) {
    echo 'file not found.';
    exit;
}

// 拡張子を除いたファイル名を取得(出力ファイル名に使用します)
$path_data = pathinfo($filepath);
$file_name = $path_data['filename'];

$media_info = new MediaInfo();
$media_info_container = $media_info->getInfo($filepath);

$video = $media_info_container->getVideos();
// 解像度
$width = preg_replace('@[^0-9]@', '', $video[0]->get('width'));
$height = preg_replace('@[^0-9]@', '', $video[0]->get('height'));
// アスペクト
$ratio = $video[0]->get('display_aspect_ratio');
// 動画ビットレート
$movie_bitrate = preg_replace('@[^0-9]@', '', $video[0]->get('bit_rate'));

$audio = $media_info_container->getAudios();
// 音声コーデック
$acodec = strtolower($audio[0]->get('format'));
// サンプリングレート
$sampling_rate = preg_replace('@[^0-9]@', '', $audio[0]->get('sampling_rate')) * 100;
// 音声ビットレート
$audio_bitrate = preg_replace('@[^0-9]@', '', $audio[0]->get('bit_rate'));
// 音声チャンネル数
$channels = preg_replace('@[^0-9]@', '', $audio[0]->get('channel_s'));

// 出力されるファイルの置き場に移動しておく
chdir("/home/movies_output");
// コマンドを生成
$command = sprintf("%s -i %s -threads 2 -codec:v libx264 -s:v %s:%s -aspect:v %s -b:v %sk -fpre:v %s -acodec %s -strict experimental -ar:a %s -b:a %sk -ac:a %s -map 0 -f segment -segment_time %s -segment_list %s.m3u8 %s/s%%03d.ts",
$ffmpeg_path,
$filepath,
$width,
$height,
$ratio,
$movie_bitrate,
$ffmpeg_preset_filepath,
$acodec,
$sampling_rate,
$audio_bitrate,
$channels,
$segment_time,
$file_name,
$file_name
);
exec($command, $output);
echo $output;
exit;

まとめ

  • mediainfo ツールを使うとさまざまなメディアファイルの情報を取得できる。PHP にはラッパークラスがあり composer でインストールできる
  • mediainfo で取得した情報を使えば ffmpeg でのコンバートも楽