はじめに
ffmpegは、動画と音声を記録・変換・再生するためのソフトです。
phpでffmpegを使用できるPHP-FFMpegをラッパーしたのがlaravel-ffmpegです。
laravel-ffmpegを使うにはffmpeg自体も必要なので、事前にインストールしておきます。
インストール
※ ffmpegはインストールされている前提で進めます。
laravelプロジェクトのルートディレクトリで
```を実行します。
composer.jsonとcomposer.lockにlaravel-ffmpegが追記されればOK。
# config/app.phpの修正
以下を追記します。
```php:app.php
'providers' => [
...
Pbmedia\LaravelFFMpeg\FFMpegServiceProvider::class,
...
];
'aliases' => [
...
'FFMpeg' => Pbmedia\LaravelFFMpeg\FFMpegFacade::class
...
];
artisanコマンド実行
laravelプロジェクトのルートディレクトリで
php artisan vendor:publish --provider="Pbmedia\LaravelFFMpeg\FFMpegServiceProvider"
を実行します。
configディレクトリ配下にlaravel-ffmpeg.phpが作成されていることを確認します。
<?php
return [
'default_disk' => 'local',
'ffmpeg' => [
'binaries' => env('FFMPEG_BINARIES', 'ffmpeg'),
'threads' => 12,
],
'ffprobe' => [
'binaries' => env('FFPROBE_BINARIES', 'ffprobe'),
],
'timeout' => 3600,
];
ffmpegとffprobeのパスを設定
以下のコマンドを実行してffmpegとffprobeのパスを確認します。
which ffmpeg
>> /usr/bin/ffmpeg
which ffprobe
>> usr/bin/ffprobe
このパスをlaravel-ffmpeg.phpか.envに追記します。
laravel-ffmpeg.phpを修正する場合
<?php
return [
'default_disk' => 'local',
'ffmpeg' => [
'binaries' => env('FFMPEG_BINARIES', '/usr/bin/ffmpeg'),
'threads' => 12,
],
'ffprobe' => [
'binaries' => env('FFPROBE_BINARIES', '/usr/bin/ffprobe'),
],
'timeout' => 3600,
];
修正後は、php artisan config:clear
でキャッシュクリアしておきます。
.envを修正する場合
FFMPEG_BINARIES=/usr/bin/ffmpeg
FFPROBE_BINARIES=/usr/bin/ffprobe
修正後は、php artisan cache:clear
でキャッシュクリアしておきます。
これで準備完了!
変換してみる
storage/app/public/配下のsample.mp4の動画の長さとコーデック名を取得し、変換前後の解像度とビットレートを画面に表示してみます。
laravel authで作成した素のHomeControllerを修正して/homeにアクセスした時に処理を実行します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use FFMpeg;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
// 変換前のファイル取得
$media = FFMpeg::fromDisk('public')->open('sample.mp4');
$mediaStreams = $media->getStreams()->first();
// 再生時間を取得
$durationInSeconds = $media->getDurationInSeconds();
// コーデックを取得
$codec = $mediaStreams->get('codec_name');
// 解像度(縦)を取得
$height = $mediaStreams->get('height');
// 解像度(横)を取得
$width = $mediaStreams->get('width');
// ビットレートを取得
$bit_rate = $mediaStreams->get('bit_rate');
// SD画質に変換
$media->addFilter(function ($filters) {
$filters->resize(new \FFMpeg\Coordinate\Dimension(720, 480));
})
->export()
->toDisk('public')
->inFormat(new \FFMpeg\Format\Video\X264('aac'))
->save('sample_SD.mp4');
// 変換後のファイル取得
$mediaSD = FFMpeg::fromDisk('public')->open('sample_SD.mp4');
$mediaStreamsSD = $mediaSD->getStreams()->first();
// 解像度(縦)を取得
$height_SD = $mediaStreamsSD->get('height');
// 解像度(横)を取得
$width_SD = $mediaStreamsSD->get('width');
// ビットレートを取得
$bit_rate_SD = $mediaStreamsSD->get('bit_rate');
// Viewで確認
return view('home')->with([
"durationInSeconds" => $durationInSeconds,
"codec" => $codec,
"height" => $height,
"width" => $width,
"bit_rate" => $bit_rate,
"height_SD" => $height_SD,
"width_SD" => $width_SD,
"bit_rate_SD" => $bit_rate_SD,
]);
}
}
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
動画の再生時間は{{$durationInSeconds}}秒です。<br>
コーデックは{{$codec}}です。<br>
変換前は解像度{{$width}}×{{$height}}でビットレートは{{$bit_rate}}bpsです。<br>
変換後は解像度{{$width_SD}}×{{$height_SD}}でビットレートは{{$bit_rate_SD}}bpsです。<br>
</div>
</div>
</div>
</div>
</div>
@endsection
ビットレートを指定して変換してみる
変換の処理を以下のように書き換えて500kbpsで変換してみます。
// SD画質に変換
$video = new \FFMpeg\Format\Video\X264('aac');
$video->setKiloBitrate(500);
$media->addFilter(function ($filters) {
$filters->resize(new \FFMpeg\Coordinate\Dimension(720, 480));
})
->export()
->toDisk('public')
->inFormat($video)
->save('sample_SD.mp4');
フレームレートの指定もできるようなので、色々試してみたいと思います!
2020/5/10追記
addFilterを使うとコマンドと同じように値を指定できることを発見したので追記です。
こんな感じ
->addFilter('-vf', config('scale=320:180,pad=y=(ih-oh)/2:aspect=4/3'))
->addFilter('-r', config('15'))
->addFilter('-level', config('2'))
->addFilter('-ar', config('8000'))