FFMpeg在命令行中工作,但在PHP脚本中没有

时间:2014-11-07 04:52:58

标签: php video ffmpeg flv server

我正在使用FFMpeg转换视频,它在命令行中工作正常。我使用以下命令:

ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv

但是,当我使用PHP脚本运行命令时,输出视频不会被编码。

exec("ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv",$output, $returnvalue);

$returnvalue = 127;

FFMPEG安装路径:

[root@localhost ~]# which ffmpeg

/root/bin/ffmpeg

我的脚本路径:

www.domainname.com/core/foldername/ffmpeg.php

请尽快为我提供解决方案。

谢谢。

2 个答案:

答案 0 :(得分:4)

从PHP脚本运行ffmpeg的自然方式如下:

<?php
    echo "Starting ffmpeg...\n\n";
    echo shell_exec("ffmpeg -i input.avi output.avi &");
    echo "Done.\n";
?>

这里有几个问题需要指出。第一个是,虽然我们指定我们希望ffmpeg在后​​台执行(使用&符号运算符&#34;&amp;&#34;),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";
?>

&#34;&gt; / dev / null&#34; 的部分会将ffmpeg实例的标准OUTPUT(标准输出)重定向到/dev/null(有效地忽略输出)和&#34; 2&gt; / dev / null&#34; 会将标准ERROR(stderr)重定向到/dev/null(实际上忽略任何错误日志消息)。这两个可以组合成一个较短的表示:&#34;&gt; / dev / null 2&gt;&amp; 1&#34; 。如果您愿意,可以阅读有关I / O重定向的更多信息。

这里应该提到一个重要的注意事项。 ffmpeg命令行工具使用stderr输出错误日志消息,stdout保留用于管道的可能使用(将ffmpeg生成的输出媒体流重定向到一些其他命令行工具)。话虽如此,如果您在后台运行ffmpeg,您很可能希望将stderr重定向到日志文件,以便稍后进行检查。

需要注意的另一件事是标准INPUT(标准输入)。命令行ffmpeg工具被设计为交互式实用程序,其接受用户的输入(通常来自键盘)并在用户的当前屏幕/终端上报告错误日志。当我们在后台运行ffmpeg时,我们想要告诉ffmpeg stdin不应接受(也不等待)任何输入。我们可以告诉ffmpeg,再次使用I / O重定向**&#34;后台的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";
?>

&#34; -y&#34; 选项用于自动覆盖输出文件(output.avi),而不要求yes/no确认。如果您需要相反的方案,要在输出文件已存在的情况下自动取消整个过程,请改用&#34; -n&#34; 选项。

包装库

某些PHP库允许将ffmpeg调用包装到PHP对象中,如果您不想使用命令行,则可以使用一种很好的语法。其中之一是积极维护PHP-FFMpeg。除了安装PHP组件之外,它只需要您下载最近的ffmpegffprobe版本。然后你可以像这样运行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年以来未开发的扩展程序(并且需要&#34; ffmpeg-0.4.9_pre1或更高版本&#34; ),这意味着您只能使用非常旧版本的ffmpeg,而无法将其更新到最新版本。由于每天都在ffmpeg's代码内进行了大量更改/改进,因此ffmpeg-php与最新的ffmpeg不兼容。

阅读official documentation了解详情。

答案 1 :(得分:1)

我介绍了解决方案,帮助大多数人在另一个帖子中与我交谈过。

https://stackoverflow.com/a/38626752/2074077

实际上,您的用户需要访问公共目录。

<?php 
   exec('whoami'); // Gives you the running user; often it's www-data
?>

然后将您的公开所有权更改为whoami用户。

sudo chown -R www-data:root /var/www