FFMpeg for PHP

PHP使用FFMpeg来转换视频格式。Github上搜索FFMPEG,到https://github.com/PHP-FFMpeg/PHP-FFMpeg。

For Windows users : Please find the binaries at http://ffmpeg.zeranoe.com/builds/.详细使用过程,见我上一篇博客。

以下操作,默认是在Linux服务器环境下进行的。

安装

建议通过Composer来安装PHP-FFMpeg 

$ composer require php-ffmpeg/php-ffmpeg

基本使用

$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video
    ->filters()
    ->resize(new FFMpeg\Coordinate\Dimension(320, 240))
    ->synchronize();
$video
    ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
    ->save('frame.jpg');
$video
    ->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
    ->save(new FFMpeg\Format\Video\WMV(), 'export-wmv.wmv')
    ->save(new FFMpeg\Format\Video\WebM(), 'export-webm.webm');

文档

 这个文档是对API进行的引导介绍。建议去阅读源代码和配套的文档。

FFMpeg

FFMpeg\FFMpeg 是操作媒体主要的对象。可以使用静态调用FFMpeg\FFMpeg::create来创建。

$ffmpeg = FFMpeg\FFMpeg::create();

FFMpeg会自动探测 ffmpeg和ffprobe的二进制文件。如果你想给出确切的二进制文件路径, 可以通过一个数组来设置。 A Psr\Logger\LoggerInterface can also be passed to log binary executions.

$ffmpeg = FFMpeg\FFMpeg::create(array(
    'ffmpeg.binaries'  => '/opt/local/ffmpeg/bin/ffmpeg',
    'ffprobe.binaries' => '/opt/local/ffmpeg/bin/ffprobe',
    'timeout'          => 3600, // The timeout for the underlying process
    'ffmpeg.threads'   => 12,   // The number of threads that FFMpeg should use
), $logger);

媒体操作

FFMpeg\FFMpeg根据URIs来创建媒体. URIs可以是本地的系统资源, HTTP网络资源,FFmpeg支持的任意资源。

注意:如果你想列出你用的FFmpeg支持的所有资源类型, 使用 -protocols 命令:

ffmpeg -protocols

使用 FFMpeg\FFMpeg::open 方法来打开一个资源。
$ffmpeg->open('video.mpeg');

两种类型的视频可以被处理: FFMpeg\Media\Audio FFMpeg\Media\Video。第三种类型 FFMpeg\Media\Frame, 可以通过视频来处理。

Video

FFMpeg\Media\Video 可以被转码, ie: change codec, isolate audio or video. 帧可以提取。

转码

你可以通过FFMpeg\Media\Video:save方法对视频进行转码,你将通过 FFMpeg\Format\FormatInterface来实现。

请注意视频或音频的比特率需要在格式中设置。

$format = new Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
    echo "$percentage % transcoded";
});

$format
    -> setKiloBitrate(1000)
    -> setAudioChannels(2)
    -> setAudioKiloBitrate(256);

$video->save($format, 'video.avi');

 转码的过程可以被实时监控, 看下面有关Format的文档了解更过信息。

提取图片

你可以用FFMpeg\Media\Video::frame 方法来提取任意时间的帧画面。

代码返回了一个媒体文件第42秒所对应的FFMpeg\Media\Frame 实例。你可以使用 FFMpeg\Coordinate\TimeCode 作为参数, 看专业文档了解更多。

$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42));
$frame->save('image.jpg');

 如果你想从视频中获取多种图片,你可以使用下边的过滤器

$video
    ->filters()
    ->extractMultipleFrames(FFMpeg\Filters\Video\ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, '/path/to/destination/folder/')
    ->synchronize();

$video
    ->save(new FFMpeg\Format\Video\X264(), '/path/to/new/file');
生成一个波

你可以使用 FFMpeg\Media\Audio::waveform 方法来从音频文件中生成一个波。

代码返回一个 FFMpeg\Media\Waveform 实例。你可以设置不同的尺寸作为参数,  查看API文档了解更多。

输出文件必须使用PNG extension.

$waveform = $audio->waveform(640, 120);
$waveform->save('waveform.png');

 如果你想从视频文件中得到一个波, 需要先把视频文件转换成音频文件。

// Open your video file
$video = $ffmpeg->open( 'video.mp4' );

// Set an audio format
$audio_format = new FFMpeg\Format\Audio\Mp3();

// Extract the audio into a new file
$video->save('audio.mp3');

// Set the audio file
$audio = $ffmpeg->open( 'audio.mp3' );

// Create the waveform
$waveform = $audio->waveform();
$waveform->save( 'waveform.png' );
Filters

 你可以使用 FFMpeg\Media\Video::addFilter 方法在 FFMpeg\Media\Video上使用过滤器。 视频接受视频和音频的过滤器。

你可以创建你自己的过滤器并且PHP-FFMpeg也附带了一些,你可以通过 FFMpeg\Media\Video::filters 方法来使用它们。

过滤器是可以链接的

$video
    ->filters()
    ->resize($dimension, $mode, $useStandards)
    ->framerate($framerate, $gop)
    ->synchronize();
旋转

 用给定的角度来旋转视频。

$video->filters()->rotate($angle);

 $angle 的参数必须是下面的一个常量:

  • FFMpeg\Filters\Video\RotateFilter::ROTATE_90: 90° clockwise
  • FFMpeg\Filters\Video\RotateFilter::ROTATE_180: 180°
  • FFMpeg\Filters\Video\RotateFilter::ROTATE_270: 90° counterclockwise
调整尺寸

按照给定的尺寸调整视频的大小。

$video->filters()->resize($dimension, $mode, $useStandards);

调整尺寸的过滤器需要三个参数:

  • $dimension, 一个 FFMpeg\Coordinate\Dimension实例
  • $mode, FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_* constants常量中的一个。
  • $useStandards, 是否强制使用最新的比率标准的布尔

 如果你想要视频处在一个非标准的比率, 你可以使用padding 过滤器 调整视频大小到想要的尺寸,包上黑色的条。

$video->filters()->pad($dimension);

 pad 过滤器需要一个参数 :

  • $dimension, FFMpeg\Coordinate\Dimension的实例

 然后的话不要忘记保存。

$video->save(new FFMpeg\Format\Video\X264(), $new_file);
水印

用给定的图片给视频文件添加水印。

$video
    ->filters()
    ->watermark($watermarkPath, array(
        'position' => 'relative',
        'bottom' => 50,
        'right' => 50,
    ));

 watermark 过滤器需要两个参数:

$watermarkPath, 你水印文件的路径; $coordinates, 一个定义水印放置位置的数组。你可以使用相对路径像上面展示的那样。或者使用绝对路径像这样:

$video
    ->filters()
    ->watermark($watermarkPath, array(
        'position' => 'absolute',
        'x' => 1180,
        'y' => 620,
    ));
帧频

 改变视频的帧频

$video->filters()->framerate($framerate, $gop);

framerate(帧频)过滤器需要两个参数:

  • $framerate FFMpeg\Coordinate\Framerate的实例
  • $gop, a GOP value (integer)
Synchronize(同步)

同步的音频和视频

一些容器使用延迟可能会导致不同步的输出。过滤器可以解决这个问题。

$video->filters()->synchronize();
Clip(修剪)

在想要的点减掉视频。

$video->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15));

The clip filter(修剪的过滤器)需要两个参数:

  • $start一个FFMpeg\Coordinate\TimeCode实例, 指定开始剪切的点
  • $duration, 可选, 一个 FFMpeg\Coordinate\TimeCode实例, 指定要持续的时间

Audio(音频)

FFMpeg\Media\Audio 可以被转码, ie: 改变编码解码器, 隔离视频和音频。帧可以被提取。

Transcoding(转码)

你可以用FFMpeg\Media\Audio:save 方法来给音频文件转码。你可以通过FFMpeg\Format\FormatInterface 来实现。

Please note that audio kilobitrate is set on the audio format.

$ffmpeg = FFMpeg\FFMpeg::create();
$audio = $ffmpeg->open('track.mp3');

$format = new FFMpeg\Format\Audio\Flac();
$format->on('progress', function ($audio, $format, $percentage) {
    echo "$percentage % transcoded";
});

$format
    -> setAudioChannels(2)
    -> setAudioKiloBitrate(256);

$audio->save($format, 'track.flac');

转码过程可以被实时监控, 看API文档了解更多。

Filters(过滤器)

你可以用FFMpeg\Media\Audio::addFilterFFMpeg\Media\Audio上应用过滤器的效果。只接受音频过滤器。

你可以创建你自己的过滤器并且PHP-FFMpeg也附带了一些,你可以通过  FFMpeg\Media\Audio::filters 方法来使用它们。

Metadata(元数据)

向音频文件中添加元数据。你可以数组的key=value键值对的形式添加你想要的元数据。如果过滤器中没有任何参数传递进来,那么所有的元数据将被从输入文件中删除。目前支持的数据有 title, artist, album, artist, composer, track, year, description, artwork

$audio->filters()->addMetadata(["title" => "Some Title", "track" => 1]);

//remove all metadata and video streams from audio file
$audio->filters()->addMetadata();

 向音频文件中添加artwork

$audio->filters()->addMetadata(["artwork" => "/path/to/image/file.jpg"]);

注意: 当前ffmpeg (version 3.2.2) only supports 只支持 .mp3 文件的artwork输出

Resample(重采样)

 重采样一个音频文件。

$audio->filters()->resample($rate);

 重采样过滤器需要两个参数:

  • $rate, a valid audio sample rate value (integer)

帧是视频文件在某一个时间点的图片,看API了解更多。

你可以使用 FFMpeg\Media\Frame::save 方法来保存帧。

$frame->save('target.jpg');

这个方法还有一个可选的布尔类型的参数。设置这个参数为true可以获得更加精确的图片,可能稍微花多一点的时间去执行。

Gif

GIf是从视频文件中提取的一系列的动画图片。

 你可以使用 FFMpeg\Media\Gif::save 方法来保存gif文件。

$video = $ffmpeg->open( '/path/to/video' );
$video
    ->gif(FFMpeg\Coordinate\TimeCode::fromSeconds(2), new FFMpeg\Coordinate\Dimension(640, 480), 3)
    ->save($new_file);

 这个方法有一个可选的布尔类型的参数,就是动画的持续时间。如果设置的话,可以得到一个确切的gif图片。

Concatenation(串联)

这个特性能够让你用混合的资源来生成一个视频或者音频。

现在有两种串联视频的方式,根据资源的编码解码器。如果你的资源都是采用的同一种编码解码器的话,你使用  FFMpeg\Media\Concatenate::saveFromSameCodecs 更好一些。 如果你的资源采用不同的编码解码器, 你要用到 FFMpeg\Media\Concatenate::saveFromDifferentCodecs.

The first function will use the initial codec as the one for the generated file. With the second function, you will be able to choose which codec you want for the generated file.

You also need to pay attention to the fact that, when using the saveFromDifferentCodecs method, your files MUST have video and audio streams.

In both cases, you will have to provide an array of files.

To concatenate videos encoded with the same codec, do as follow:串联采用相同编码解码器的视频文件的话,参照下边的方法:

// In order to instantiate the video object, you HAVE TO pass a path to a valid video file.
// We recommand that you put there the path of any of the video you want to use in this concatenation.
$video = $ffmpeg->open( '/path/to/video' );
$video
    ->concat(array('/path/to/video1', '/path/to/video2'))
    ->saveFromSameCodecs('/path/to/new_file', TRUE);

保存函数中的布尔参数能让你使用拷贝的参数,这个参数可以大福度提高编码文件的生成过程。

To concatenate videos encoded with the same codec, do as follow:

// In order to instantiate the video object, you HAVE TO pass a path to a valid video file.
// We recommand that you put there the path of any of the video you want to use in this concatenation.
$video = $ffmpeg->open( '/path/to/video' );

$format = new FFMpeg\Format\Video\X264();
$format->setAudioCodec("libmp3lame");

$video
    ->concat(array('/path/to/video1', '/path/to/video2'))
    ->saveFromDifferentCodecs($format, '/path/to/new_file');

  在 FFMPEG中更多关于串联的细节 可看这里 here, here and here.

Formats(格式)

格式要实现 FFMpeg\Format\FormatInterface。FFMpeg\Format\VideoInterface来保存视频文件, 用 FFMpeg\Format\AudioInterface 来保存音频文件。

 FFMpeg\Format\ProgressableInterface的话可以获得转码的实时信息。

预定义的格式已经提供了事件的过程信息。

$format = new Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
    echo "$percentage % transcoded";
});

$video->save($format, 'video.avi');

为事件提供的回调函数可以随时调用。

Add additional parameters

你可以根据你的视频格式为你的编码提供额外的参数。

setAdditionalParameters 方法的参数是一个数组。

$format = new Format\Video\X264();
$format->setAdditionalParameters(array('foo', 'bar'));
$video->save($format, 'video.avi');
创建你自己的格式

 创建一种新的格式最简单的方法就是集成抽象类 FFMpeg\Format\Video\DefaultVideo and FFMpeg\Format\Audio\DefaultAudio,并且实现下面的方法。

class CustomWMVFormat extends FFMpeg\Format\Video\DefaultVideo
{
    public function __construct($audioCodec = 'wmav2', $videoCodec = 'wmv2')
    {
        $this
            ->setAudioCodec($audioCodec)
            ->setVideoCodec($videoCodec);
    }

    public function supportBFrames()
    {
        return false;
    }

    public function getAvailableAudioCodecs()
    {
        return array('wmav2');
    }

    public function getAvailableVideoCodecs()
    {
        return array('wmv2');
    }
}

Coordinates(坐标)

FFMpeg 使用很多单元来确定时间和空间坐标。

  • FFMpeg\Coordinate\AspectRatio  表示长宽比
  • FFMpeg\Coordinate\Dimension  表示一个维度
  • FFMpeg\Coordinate\FrameRate  表示帧速率
  • FFMpeg\Coordinate\Point  表示一个点
  • FFMpeg\Coordinate\TimeCode  表示一个时间码

FFProbe

FFMpeg\FFMpeg 内部使用FFMpeg\FFProbe来检查媒体文件。你也可以用它提取元数据。

$ffprobe = FFMpeg\FFProbe::create();
$ffprobe
    ->streams('/path/to/video/mp4') // extracts streams informations
    ->videos()                      // filters video streams
    ->first()                       // returns the first video stream
    ->get('codec_name');            // returns the codec_name property
$ffprobe = FFMpeg\FFProbe::create();
$ffprobe
    ->format('/path/to/video/mp4') // extracts file informations
    ->get('duration');             // returns the duration property

使用 Silex Microframework

Service provider is easy to set up:

$app = new Silex\Application();
$app->register(new FFMpeg\FFMpegServiceProvider());

$video = $app['ffmpeg']->open('video.mpeg');

下面是一些可能的选项:

$app->register(new FFMpeg\FFMpegServiceProvider(), array(
    'ffmpeg.configuration' => array(
        'ffmpeg.threads'   => 4,
        'ffmpeg.timeout'   => 300,
        'ffmpeg.binaries'  => '/opt/local/ffmpeg/bin/ffmpeg',
        'ffprobe.timeout'  => 30,
        'ffprobe.binaries' => '/opt/local/ffmpeg/bin/ffprobe',
    ),
    'ffmpeg.logger' => $logger,
));
posted @ 2017-02-28 10:38 Mr.peter 阅读(...) 评论(...) 编辑 收藏