使用 PHP-FFMpeg 操作视频/音频文件

做音频合成的时候找到的一个php操作ffmpeg 的类库。GitHub地址:https://github.com/PHP-FFMpeg/PHP-FFMpeg/。本文的例子大部分都是上面的

在使用之前请安装好 FFMpeg 。如何安装?请看FFmpeg 安装教程

使用composer快速安装 > composer require php-ffmpeg/php-ffmpeg。

注意:请在 php.ini 中开启这两个函数proc_open,proc_get_status。找到 disable_functions 将里面的这两个函数去掉就行了

目录说明

/usr/loca/bin ffmpeg 的执行目录

/mnt/hgfs/www/test 本文章的测试目录

这里主要用 1080.mp4 这个视频做测试,下面就是这个 18 秒的视频(chrome 谷歌浏览器不显示播放器是因为https 的站不能使用未加密的http资源,唉)

https://www.bilibili.com/video/av17244788/

使用时请配置 ffmpeg,ffprobe 的执行文件绝对路径。我定义了一些测试用的视频音频文件

复制代码
$path = [
    'ffmpeg.binaries'  => '/usr/local/bin/avconv',
    'ffmpeg.binaries' => '/usr/local/bin/ffmpeg',
    'ffprobe.binaries' => '/usr/local/bin/avprobe',
    'ffprobe.binaries' => '/usr/local/bin/ffprobe',
];
$ffmpeg = FFMpeg\FFMpeg::create($path);
$a1 = '/mnt/hgfs/www/test/a1.mp3';
$v1 = '/mnt/hgfs/www/test/v1.mp4';
$v2 = '/mnt/hgfs/www/test/v2.mp4';
$v3 = '/mnt/hgfs/www/test/v3.mp4';
$v1080 = '/mnt/hgfs/www/test/1080.mp4';

1、拼接视频/音频

复制代码
$newFile = '/mnt/hgfs/www/test/video.mp4';
$video = $ffmpeg->open($v1);
$video->concat(array($v1,$v2,$v3))->saveFromSameCodecs($newFile, TRUE);

若是已存在合成的新文件 ($newFile 已存在),将会报错,请确保同一目录下不存在相同的文件

2、提取图像

提取一张

复制代码
$video = $ffmpeg->open($v1080);
$frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(2));//提取第几秒的图像
$frame->save('image.jpg');

抽取多张

复制代码
$video = $ffmpeg->open($v1080);
$video->filters()
    ->extractMultipleFrames(FFMpeg\Filters\Video\ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, '/mnt/hgfs/www/test/image/')
    ->synchronize();
 
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/v2new.mp4');

注意:此方法会抽取对应的图片帧,而且每次都提取 400 张,不知道是不是我参数设置的问题(试了 FRAMERATE_EVERY_SEC,FRAMERATE_EVERY_2SEC,FRAMERATE_EVERY_10SEC)

3、生成音频波形

复制代码
$audio = $ffmpeg->open($a1);
$waveform = $audio->waveform(640, 120, array('#00FF00'));
$waveform->save('waveform.png');//必须保存为 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 as mp3
$video->save($audio_format, 'audio.mp3');
// Set the audio file
$audio = $ffmpeg->open( 'audio.mp3' );
 
// Create the waveform
$waveform = $audio->waveform();
$waveform->save( 'waveform.png' );

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

4、调整视频大小

复制代码
$video = $ffmpeg->open($v1080);
$video->filters()->resize(new FFMpeg\Coordinate\Dimension(200,400), FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_FIT, true);
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/v1080_new.mp4');

注意:x264 类默认使用 libfaac 为编码器,但我安装的是 libfdk_aac,所以这里要指定为 libfdk_aac,不然会报错

参数说明:

resize(Dimension dimension, mode = ResizeFilter::RESIZEMODE_FIT, $forceStandards = true)

$dimension 调整后的视频宽高

$mode 四种缩放模式

RESIZEMODE_FIT 按给定值调整

RESIZEMODE_INSET 在给定的尺寸内调整大小,可能是按宽为基准(高等比缩放),也可能是按高为基准(宽等比缩放)

RESIZEMODE_SCALE_WIDTH 高为给定值,宽按比例缩放

RESIZEMODE_SCALE_HEIGHT 宽为给定值,高按比例缩放

$forceStandards ture / false,是否强制使用最近的纵横比标准

5、视频添加水印

复制代码
$video = $ffmpeg->open($v1080);
$watermarkPath = '/mnt/hgfs/www/test/water.png';
$absolute = ['x' => 50,'y' => 100];
$relative = [
    'position' => 'relative',
    'bottom' => 50,
    'right' => 50
 ];
$video->filters()->watermark($watermarkPath, $absolute);
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/1080_new.mp4');

watermark(imagePath, array coordinates = array())

$imagePath 水印图片路径

$coordinates 水印坐标

position 可选项 relative(相对定位) / absolute(绝对,默认)

若为 relative,有四个参数可选,top 、bottom、left、right ,分别对应四个方位

在上面的例子中就是在视频的右下角,距离右边50,距离下边50 的位置处添加水印(这个位置坐标是水印图片的左下角位置),如图

若为 absolute,直接填写 x 和 y 坐标即可 ,如图

6、调整视频的帧率

关于 帧率 和 GOP 介绍 http://blog.csdn.net/xiangjai/article/details/44238005

这玩意儿我也不懂,设置了几个值进行转换,但都time out 了,1g的虚拟机玩不起

复制代码
$video = $ffmpeg->open($v1080);
$video->filters()->framerate(new \FFMpeg\Coordinate\FrameRate(3000), 120);
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/1080_new.mp4');

7、截取视频/音频

复制代码
$video = $ffmpeg->open($v1080);
$video->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(10));
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/1080_new.mp4');

clip(start, duration = null)

从第 start 秒开始,取 duration 秒,若 $duration 不填,则截取至最后

8、裁剪视频

复制代码
$video = $ffmpeg->open($v1080);
$video->filters()->crop(new FFMpeg\Coordinate\Point("t*100", 0, true), new FFMpeg\Coordinate\Dimension(960, 540));
$video->save(new FFMpeg\Format\Video\X264('libfdk_aac'), '/mnt/hgfs/www/test/1080_new.mp4');

crop(Point point, Dimension dimension)

$dimension 为裁剪后的尺寸

Point(x, y, $dynamic = false)

x 和 y 为裁剪的起始坐标,$dynamic 为是否动态裁剪

动态裁剪是什么意思呢,比如:

Point("t*100", 0, true) 裁剪出来的视频就是画面从左边动态的移动到右边,然后就固定在左边

100 为速度,值越大,移动速度越快。话说这个动态裁剪没啥用的感觉

下面的视频为上面代码裁剪的,对比一下有什么不同

https://www.bilibili.com/video/av17244824/

9、音频转换

复制代码
$audio = $ffmpeg->open($a1);
$format = new FFMpeg\Format\Audio\Flac();
$format->on('progress', function ($audio, $format, $percentage) {
    echo "$percentage % 进度";
});
$format->setAudioChannels(2)->setAudioKiloBitrate(256);
$audio->save($format, 'a1.flac');

Flac 为无损压缩格式

setAudioChannels 声道设置,1单声道,2双声道,3立体声

setAudioKiloBitrate 比特率

11、音频添加元数据

复制代码
$audio = $ffmpeg->open($a1);
$audio->filters()->addMetadata([
    "title" => "Test Title",
    "artist" => "Jam00 artist",
    "album" => "Test album",
    "composer" => "Jam00",
    "track" => 1,
    "year" => 2017,
    "description" => "jam00 test description",
]);
$audio->save(new \FFMpeg\Format\Audio\Mp3, 'a1_new.mp3');

目前支持的数据是 title(标题),artist(艺术家),album(专辑),artist(艺术家),composer(作曲家),track(轨道),year(年),description(描述),artwork(艺术作品)

注:FFmpeg(3.2.2版本)只支持MP3文件添加 artwork 元数据

使用格式工厂查看a1_new.mp3的元数据

复制代码
...
Format                                   : MPEG Audio
File size                                : 1.43 MiB
Duration                                 : 1 min 33 s
Overall bit rate mode                    : Constant
Overall bit rate                         : 128 kb/s
Album                                    : Test album
Track name                               : Test Title
Track name/Position                      : 1
Performer                                : Jam00 artist
Composer                                 : Jam00
Writing library                          : LAME3.99.5
year                                     : 2017
description                              : jam00 test description
...

12、Frame 提取图像

复制代码
$video = $ffmpeg->open($v1080);
$frame = new FFMpeg\Media\Frame($video, FFMpeg\Driver\FFMpegDriver::load($path), FFMpeg\FFProbe::create($path), FFMpeg\Coordinate\TimeCode::fromSeconds(10));
$frame->save('frame.jpg');

其实 例子2 提取视频图像的方法 frame 调用的就是 Frame 类

13、从视频中提取动图

复制代码
$video = $ffmpeg->open($v1080);
$video->gif(FFMpeg\Coordinate\TimeCode::fromSeconds(10), new FFMpeg\Coordinate\Dimension(400, 200), 3)->save('1080.gif');

gif(TimeCode at, Dimension dimension, $duration = null)

从第 at 秒开始提取,持续 duration 秒,保存为 $dimension指定大小(下面的例子为400x200) 的gif图

若不设置 $duration ,将会得到一个静止的gif图

动图太大,我就不上传了

14、视频格式转换

复制代码
$video = $ffmpeg->open($v1080);
$format = new FFMpeg\Format\Video\X264('libfdk_aac');
$format->setKiloBitrate(1000)->setAudioChannels(2)->setAudioKiloBitrate(256);
$format->on('progress', function ($video, $format, $percentage) {
    echo "$percentage % 进度";
});
$video->save($format, '/mnt/hgfs/www/test/video.avi');

setKiloBitrate 设置视频比特率

setAudioChannels 声道设置,1单声道,2双声道,3立体声

setAudioKiloBitrate 设置音频比特率

15、添加额外参数(若你精通 ffmpeg 命令行参数)

复制代码
$video = $ffmpeg->open($v1080);
$format = new FFMpeg\Format\Video\X264('libfdk_aac');
$format->setAdditionalParameters(array('foo', 'bar'));
$video->save($format, 'video.avi');

foo / bar 为 ffmpeg 支持的参数,这个就不测了

16、使用 FFProbe 提取元数据

复制代码
$ffprobe = FFMpeg\FFProbe::create($path);
//视频
$videoInfo = $ffprobe->format($v1080);
//音频
$audioInfo = $ffprobe->format($a1);
//也可以使用 get 获取特定值,第二个参数为默认值(若该参数不存在将返回此默认值)
$duration = $ffprobe->format($v1080)->get('duration',100);
echo "<pre>";
print_r($videoInfo);
print_r($audioInfo);
echo "</pre>";
echo '视频时长:'.$duration;

FFMpeg\FFProbe\DataMapping\Format Object
(
    [properties:FFMpeg\FFProbe\DataMapping\AbstractData:private] => Array
        (
            [filename] => /mnt/hgfs/www/test/1080.mp4
            [nb_streams] => 2
            [nb_programs] => 0
            [format_name] => mov,mp4,m4a,3gp,3g2,mj2
            [format_long_name] => QuickTime / MOV
            [start_time] => 0.000000
            [duration] => 18.882000
            [size] => 9062983
            [bit_rate] => 3839840
            [probe_score] => 100
            [tags] => Array
                (
                    [major_brand] => isom
                    [minor_version] => 512
                    [compatible_brands] => isomiso2mp41
                    [encoder] => Lavf57.41.100
                )
 
        )
 
)
FFMpeg\FFProbe\DataMapping\Format Object
(
    [properties:FFMpeg\FFProbe\DataMapping\AbstractData:private] => Array
        (
            [filename] => /mnt/hgfs/www/test/a1.mp3
            [nb_streams] => 1
            [nb_programs] => 0
            [format_name] => mp3
            [format_long_name] => MP2/3 (MPEG audio layer 2/3)
            [start_time] => 0.000000
            [duration] => 93.348000
            [size] => 186696
            [bit_rate] => 16000
            [probe_score] => 51
        )
 
)
视频时长:18.882000

本内容为博主原创,转载请注明出处。

本文链接使用 PHP-FFMpeg 操作视频/音频文件

相关推荐
瑶光守护者17 分钟前
【卫星通信】超低码率语音编码ULBC:EnCodec神经音频编解码器架构深度解析
深度学习·音视频·卫星通信·语音编解码·ulbc
枫叶梨花6 小时前
从 M4S 到 MP4:用 FFmpeg 轻松合并音视频文件
ffmpeg·音视频
胖虎17 小时前
(二十一)深入了解AVFoundation-编辑:导出视频与格式转换的全流程
音视频·音视频导出·音视频格式转换
米优9 小时前
FFmpeg添加水印
ffmpeg
林深时见鹿74914 小时前
使用k8s k3s kuboard 部署 php hyperf 框架
php
长城202414 小时前
从词源和输出生成等角度详细解析PHP中常用文件操作类函数
php·文件·函数·文件操作函数
长城202414 小时前
PHP如何使用JpGraph生成3D饼形图?
开发语言·php·jpgraph·3d饼形图
blanks202020 小时前
qt mac 解决 info.plist 自定义问题
ffmpeg
熬夜苦读学习21 小时前
Reactor 反应堆模式
运维·服务器·网络·网络协议·http·智能路由器·php
小森林821 小时前
分享一次Guzzlehttp上传批量图片优化的经历
后端·php