20
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

laravel-ffmpegを使って動画の変換をしてみる

Last updated at Posted at 2019-08-31

はじめに

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が作成されていることを確認します。

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を修正する場合

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を修正する場合

.env
FFMPEG_BINARIES=/usr/bin/ffmpeg
FFPROBE_BINARIES=/usr/bin/ffprobe

修正後は、php artisan cache:clearでキャッシュクリアしておきます。

これで準備完了!

変換してみる

storage/app/public/配下のsample.mp4の動画の長さとコーデック名を取得し、変換前後の解像度とビットレートを画面に表示してみます。

laravel authで作成した素のHomeControllerを修正して/homeにアクセスした時に処理を実行します。

HomeController
<?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,
        ]);
    }
}
home.blade.php
@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

実行結果はこんな感じ。
スクリーンショット 2019-08-31 20.00.01.png

ビットレートを指定して変換してみる

変換の処理を以下のように書き換えて500kbpsで変換してみます。

HomeController
        // 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');

実行結果はこんな感じ。
スクリーンショット 2019-08-31 20.20.50.png

フレームレートの指定もできるようなので、色々試してみたいと思います!

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'))
20
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?