ファイルアップロードの際、特定の拡張子に変換したくなるケースがあります。
動画サイトやファイル共有サイトであれば、変換作業は必ずといっていいほど必須です。
今回は、特定のフォルダの動画ファイルを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に合わせて、良さそうな時間に静止画を作成すると良いと思います。