脱初心者備忘録

[XAMPP] PHPでFFMPEGを使って動画変換

ファイルアップロードの際、特定の拡張子に変換したくなるケースがあります。
動画サイトやファイル共有サイトであれば、変換作業は必ずといっていいほど必須です。
今回は、特定のフォルダの動画ファイルをFFMPEGを使って変換する作業を記録します。

FFMPEGとは?

FFMPEGとは、動画と音声を記録・変換・再生するためのフリーソフトウェアである。

ウィキペディア

Windowsであれば、コマンドを使用して動作させます。
サポートしているファイル形式も多く、ほとんどのファイルの変換に使用できるといえます。
コマンドでは、FFMPEGを呼び出し、オプションで変換内容を操作する感じです。

ffmpeg -i 入力ファイル -f 出力フォーマット -y 出力ファイル 

上記が基本形になります。
コマンドで入力ファイルと出力ファイル、出力フォーマットを指定すると変換開始します。

例えば、video.aviをvideo.mp4に変換する場合はこうなります。
ffmpeg -i video.avi -f mp4 -y video.mp4

変換オプション

変換にはいろんなオプションがあります。よく使うものを記載します。

  • -i  入力ファイル
  • -y  出力ファイル
  • -f  出力フォーマット 
  • -b  動画のビットレート
  • -r  フレームレート
  • -s  動画サイズ
  • -ss  変換開始する時間
  • -aspect  アスペクト比
  • -vcodec  ビデオコーデック
  • -acodec  音声コーデック

FFMPEGをXAMPPに入れる

まずFFMPEGを公式サイトからダウンロードします。
FFMPEG公式サイト

今回はWindowsのマークをクリック。
すると、下にWindows EXE Filesと出るので、Windows builds from gyan.dev をクリック

サイトが開くので、中ほどの、latest git master branch build のものを選択します。
今回は ffmpeg-git-essential.7z を選択します。

すると、ダウンロードが開始され、自分にPCに保存されます。
今回は、ffmpeg-2022-03-24-git-28d011516b-essentials_build.7z が保存されました。
7zファイルなので、7zを扱えるアプリケーションで展開します。

展開すると、bin・doc・presetsの3つのフォルダで構成されています。
今回必要なのはbinだけです。このbinをxamppに移動したいと思います。
xamppの直下に新しいフォルダをffmpegという名前で作成し、その中にbinを入れます。

これでFFMPEGを使用できるようにはなったのですが、パスを通すことで、呼び出しやすくなるので、パスを通します。

FFMPEGのパスを通す

スクリプトやコマンドの中で、ffmpegと呼ぶだけで使用できるようにするには、パスを通す必要があります。
パスを通すとは、Windowsでは環境変数のPathに登録することを言います。

まず、Windowsのメニューを右クリックし、その中から、システムを選択します。
表示された中から左メニューの「詳細情報」を選び、表示されたら、一番下の「システムの詳細設定」を選択します。

表示されたウィンドウの一番下にある、環境変数をクリックします。

システム環境変数の中から、「Path」を選び、編集をクリックします。

新規ボタンをクリックして、ffmpeg\binの場所を書きます。
今回は、Dディスクのxamppに入れたので、
D:xampp/ffmpeg/bin
になっていますが、ご自身の環境に合わせて書き換えてください。
終わったら、OKを押してウィンドウを閉じます。
全部閉じたら、念のため、PCを再起動します。

FFMPEGを使ってみる

まず、コマンドで呼び出せるかどうかテストします。
xamppを立ち上げ、コントロールパネルの右にあるShellボタンをクリックします。
下記のコードを入力してみてください。

ffmpeg -version

こんな感じで表示されたら、間違いなくパスは通っています。

では、次に、PHPファイルを作成します。

htdocsの中に適当にフォルダを作成し、PHPファイルも作成します。
今回は、このような構成にしてあります。

  • tmp・・・・・・・・・変換したい動画ファイルのディレクトリ
  • upload・・・・・・・・変換後に動画を入れるディレクトリ
  • index.php・・・・・・・コマンドを書いたPHPファイル

phpファイルの内容は以下の通りです。

<?php

ini_set('display_errors', 1);

$file = 'fhd.mov';
$upload_dir = 'upload/';
$tmp_dir = 'tmp/';
$tmp_file = $tmp_dir . $file;

$ext = substr(strrchr($file, '.'), 1);
$ext_length = strlen($ext);
$file_length = strlen($file);
$need = $file_length - ($ext_length + 1);
$base_name = substr($file, 0, $need);

$new_video_ext = 'mp4';
$new_video_name = $base_name . '_new.' . $new_video_ext;

$up_video = $upload_dir . $new_video_name;

define("FFMPEG_COMMAND", ' ffmpeg -i %s -f mp4 -vcodec libx264 -acodec aac -b 2000k -y %s 2>&1');

$command = sprintf(FFMPEG_COMMAND, $tmp_file, $up_video);
$log = '';
exec($command,  $log);
var_dump($log);

【コードの説明】

$file = 'fhd.mov';
$upload_dir = 'upload/';
$tmp_dir = 'tmp/';
$tmp_file = $tmp_dir . $file;

今回使用するファイルとディレクトリの指定です。$tmp_file で変換元のファイルとなります。

$ext = substr(strrchr($file, '.'), 1);//拡張子取得
$ext_length = strlen($ext);
$file_length = strlen($file);
$need = $file_length - ($ext_length + 1);
$base_name = substr($file, 0, $need);//名前だけ抽出

元のファイルから拡張子を切り取り、名前だけを抽出しています。
元ファイルの拡張子を指定して変換したいときにも、役立つと思います。

$new_video_ext = 'mp4';
$new_video_name = $base_name . '_new.' . $new_video_ext;//変換後の名前

$up_video = $upload_dir . $new_video_name;

今回はMP4に変換するので、変換後のファイルの拡張子をmp4と指定しています。
さらに、変換後のファイルの名前に_newをつけて保存したいので、このように記述しています。

define("FFMPEG_COMMAND", ' ffmpeg -i %s -f mp4 -vcodec libx264 -acodec aac -b 2000k -y %s 2>&1');

$command = sprintf(FFMPEG_COMMAND, $tmp_file, $up_video);

コマンドを定数にして、sprintfに渡しています。
ココだけでなく、プログラムの中で、使用したいときに、ファイル名は動的なので、コマンド自体を定数にしておくと何かと便利です。

コマンドの最後の「2>&1」は、シェルコマンドで使用する際、標準エラー出力が全て、ファイル に出力されるので エラーログが取得できるようになり便利なので、書くようにします。

$log = '';
exec($command,  $log);
var_dump($log);

execでコマンドを実行し、ログをすべて$logに記録します。
最後に、logの内容を表示します。

実行してみます。

index.phpの表示です。ログ内容が記載されています。tmp/fhd.movや、Duration: 00:00:14.32,という文字も見えます。

uploadフォルダには、正常に指定した名前で、動画が保存されています。

コマンドにオプションを追加すると、指定したサイズで保存出来たり、サムネイルを作成したりなど、いろんなことが可能になります。

動画のサムネイルをFFMPEGで作成する

動画を作成するついでに、その動画のポスターも作成することができます。
〇秒目から始めて、△frame目で終了し、出力ファイルといった名前で出力する。といったコードが必要になります。

ffmpeg -ss 〇 -i 入力ファイル -vframes △ -f image2 出力ファイル
  • -ss  静止画を開始したい時間
  • -i  使用するファイル
  • -vframes  何frame切り出すか
  • -f  出力ファイルのフォーマット
  • image2  画像として出力

入力ファイルのあとに、-s 640×360 などと書くと、出力サイズを指定できます。
また -ssが-iより前にあることで、出力速度を速くできます。

動画を作成したら、その動画のポスターを動画のDurationに合わせて、良さそうな時間に静止画を作成すると良いと思います。