$name = md5(date('YmdHis')).".png";
php
$from = "E:\\UPLOAD\\cw\\20150626\\558d0d11ae285.mp4";
html
$to = "E:\\UPLOAD\\cover_images\\";
git
$str = "ffmpeg -i ".$from." -y -f mjpeg -ss 3 -t 1 -s 740x500 ".$to.$name;
github
system($str);
web
本文将尝试指出在PHP Web脚本中使用FFmpeg时须要了解的全部重要事项。它还将显示一些使用示例,以使事情更清楚。这个想法也能够应用到其余web脚本语言。shell
网页设计为快速执行,以便浏览您的网站的人没必要等待太多的响应。由于若是他们无聊的等待,他们只会导航到另外一个,更灵敏(一般是您的竞争对手的)网站。话虽如此,你能够作的最糟糕的事情是从你的web脚本运行一个命令行工具(如ffmpeg),并等待它完成处理,以便可以将结果返回到等待在线用户(异常这是小/快的工具,其执行时间过小而不能注意到)。数据库
您想要作的是将命令行工具的长处理与Web脚本执行分开,以使脚本更具响应性。因此,你有至少两个选项:ubuntu
这两种方法看起来是同样的,可是他们不是。最重要的区别是,第二种方法能够更好地扩展更高的网站流量,由于它容许“工做”进程在彻底独立的机器上运行。此外,能够有几个“工做”机器,一块儿工做,分裂工做负载,涉及小的同步。安全
第一种方法一般是大多数想要快速完成工做的人的首选,可是在他们的网站变得流行的时间,他们的web服务器变得不那么敏感,因为不断的cpu饥饿,由多个命令行工具(ffmpeg实例)在后台运行。在那一刻,他们一般开始考虑第二种方法。服务器
如下示例适用于基于Linux的操做系统。对于基于Windows的操做系统,请继续阅读本文,而是你读了以后,也看到了如何使用START和CMD后台运行的过程。这将给你一个想法如何应用相同的逻辑到基于Windows的操做系统。
让咱们考虑从PHP脚本运行ffmpeg的天然方式:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -i input.avi output.avi &"); echo "Done.\n"; ?>
这里有几个问题须要指出。第一个是,虽然咱们指定咱们但愿在后台执行ffmpeg(使用和号运算符“&”),PHP脚本将不会继续执行,直到ffmpeg完成其执行。这是因为这样的事实,在该票据中说起了PHP的exec()函数,上面写着:
若是程序使用此函数启动,为了使其在后台继续运行,程序的输出必须重定向到文件或另外一个输出流。若是不这样作,将致使PHP挂起,直到程序的执行结束。
不要混淆的例子显示了shell_exec()调用,而不是EXEC() 。全部的PHP的程序执行功能共享相同的代码库和限制。
因此,要解决这个问题,咱们须要作这样的事情:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -i input.avi output.avi >/dev/null 2>/dev/null &"); echo "Done.\n"; ?>
该说的部分“ >的/ dev / null的 ”将FFmpeg的实例的标准输出(stdout)重定向到/ dev / null的(有效地忽略输出)和“ 2>的/ dev / null的 ”将重定向标准错误(错误)到/ dev / null(有效地忽略任何错误日志消息)。这两个能够组合成一个较短的表示:“ >的/ dev / null的2>&1 ”。若是你喜欢,你能够阅读更多关于I / O重定向。
这里应该提到一个重要的注意事项。ffmpeg命令行工具使用stderr输出错误日志消息,而且保留stdout用于可能使用的管道(将从ffmpeg生成的输出媒体流重定向到其余命令行工具)。也就是说,若是你在后台运行你的ffmpeg,你极可能想把stderr重定向到一个日志文件,以便可以检查它。
须要注意的另外一件事是标准INPUT(stdin)。命令行ffmpeg工具被设计为一个交互式实用程序,它接受用户的输入(一般来自键盘),并在用户的当前屏幕/终端上报告错误日志。当咱们在后台运行ffmpeg时,咱们想要告诉ffmpeg没有从stdin接受任何输入(也不等待)。咱们能够告诉这ffmpeg的,再次使用I / O重定向“ <的/ dev / null的 ”,这样最后一个例子,安全运行ffmpeg的命令行工具在后台将与此相似:
<?php echo "Starting ffmpeg...\n\n"; echo shell_exec("ffmpeg -y -i input.avi output.avi </dev/null >/dev/null 2>/var/log/ffmpeg.log &"); echo "Done.\n"; ?>
在“-y”选项用于自动覆盖输出文件(output.avi)不要求是/否确认。若是须要相反的状况,若是输出文件已经存在,要自动取消整个过程,请改用“-n”选项。
一些PHP库容许将ffmpeg调用包装到PHP对象中,而且若是您不喜欢使用命令行,能够为您提供一个不错的语法。其中之一是在积极维护PHP-FFmpeg的。它只须要你下载一个最新的ffmpeg和ffprobe从安装PHP组件构建分开。而后你能够这样运行PHP代码:
$ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video->filters() ->resize(new FFMpeg\Coordinate\Dimension(320, 240)) ->synchronize(); $video->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
固然,你须要在后台运行这样的任务。图书馆如GearmanClient促成。
注: ffmpeg的- PHP的是,2007年以来未开发的扩展名(和要求“的ffmpeg-0.4.9_pre1或更高版本”),这意味着你仅限于使用一种很是古老的版本的ffmpeg,没有可能把它更新到最新版本。因为进行了大量的更改/改进,在ffmpeg的代码中,天天,它使得ffmpeg-php与最新的ffmpeg不兼容。
案例成功测试结果:
<?php echo "正在启动ffmpeg...\n\n"; echo shell_exec("ffmpeg -y -i rtmp://tinywan.123.com/live/4001483413136 -c copy -f flv rtmp://131.180/live/4001483492781?vhost=13.168 </dev/null >/dev/null 2>/var/log/ffmpeg.log &"); echo "完成.\n";
正在启动ffmpeg... 完成.
日志文件:
ffmpeg version 2.3.git Copyright (c) 2000-2014 the FFmpeg developers built on Sep 1 2014 19:01:47 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1) configuration: --prefix=/usr/local/ffmpeg/build --extra-cflags=-I/usr/local/ffmpeg/build/include --extra-ldflags=-L/usr/local/ffmpeg/build/lib --bindir=/usr/local/ffmpeg/bin --enable-gpl --enable-libass --enable-libfaac --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-openssl --enable-libspeex --enable-libxvid libavutil 54. 7.100 / 54. 7.100 libavcodec 56. 1.100 / 56. 1.100 libavformat 56. 3.100 / 56. 3.100 libavdevice 56. 0.100 / 56. 0.100 libavfilter 5. 0.103 / 5. 0.103 libswscale 3. 0.100 / 3. 0.100 libswresample 1. 1.100 / 1. 1.100 libpostproc 53. 0.100 / 53. 0.100 [flv @ 0x2862000] Stream discovered after head already parsed Last message repeated 1 times Input #0, flv, from 'rtmp://tinywan.3213.com/live/4001483413136': Metadata: Server : Tengine displayWidth : 1920 displayHeight : 1080 fps : 25 profile : level : Duration: 00:00:00.00, start: 765.097000, bitrate: N/A Stream #0:0: Video: h264 (High), yuv420p(tv, bt709), 1920x1080, 1048 kb/s, 25 fps, 25 tbr, 1k tbn, 2k tbc Stream #0:1: Data: none Stream #0:2: Audio: aac, 44100 Hz, stereo, fltp Output #0, flv, to 'rtmp://1232130/live/4001483492781?vhost=321312': Metadata: Server : Tengine displayWidth : 1920 displayHeight : 1080 fps : 25 profile : level : encoder : Lavf56.3.100 Stream #0:0: Video: h264 ([7][0][0][0] / 0x0007), yuv420p, 1920x1080, q=2-31, 1048 kb/s, 25 fps, 1k tbn, 1k tbc Stream #0:1: Audio: aac ([10][0][0][0] / 0x000A), 44100 Hz, stereo Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:2 -> #0:1 (copy) Press [q] to stop, [?] for help
测试成功!