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

Jit*_*ati 5 php video flv ffmpeg server

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

ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv
Run Code Online (Sandbox Code Playgroud)

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

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

$returnvalue = 127;
Run Code Online (Sandbox Code Playgroud)

FFMPEG安装路径:

[root@localhost ~]# which ffmpeg

/root/bin/ffmpeg
Run Code Online (Sandbox Code Playgroud)

我的脚本路径:

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

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

谢谢.

bod*_*di0 7

ffmpeg从 PHP 脚本运行的自然方式类似于:

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

这里有几个问题需要指出。第一个是,尽管我们指定要ffmpeg在后台执行(使用与号运算符“&”),但 PHP 脚本在执行完成之前不会继续ffmpeg执行。这是由于在 ?PHPexec()函数的注释之一中提到的事实,它说:

如果一个程序使用这个函数启动,为了让它在后台继续运行,程序的输出必须被重定向到一个文件或另一个输出流。如果不这样做,将导致 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";
?>
Run Code Online (Sandbox Code Playgroud)

表示“>/dev/null”的部分会将ffmpeg实例的标准输出(stdout)重定向到/dev/null(有效忽略输出),而“2>/dev/null”会将标准错误(stderr)重定向到/dev/null(有效忽略输出)任何错误日志消息)。这两个可以组合成更短的表示:">/dev/null 2>&1"。如果您愿意,可以阅读有关 I/O 重定向的更多信息。

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

需要注意的另一件事是标准 INPUT (stdin)。命令行ffmpeg工具被设计为一种交互式实用程序,它接受用户的输入(通常来自键盘)并报告用户当前屏幕/终端上的错误日志。当我们运行ffmpeg的背景下,我们要告诉ffmpeg不输入应该被接受(也不等待)从stdin。我们可以告诉这个ffmpeg,再次使用 I/O 重定向 **“后台的 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";
?>
Run Code Online (Sandbox Code Playgroud)

这 ?“-y”选项用于在不要求yes/no确认的情况下自动覆盖输出文件(output.avi)。如果您需要相反的场景,如果输出文件已经存在,要自动取消整个过程,请改用“-n”选项。

包装库

一些 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')
Run Code Online (Sandbox Code Playgroud)

当然,您需要注意在后台运行这样的任务。图书馆,如 ? GearmanClient促进了这一点。

注意: ? ffmpeg-php是自 2007 年以来未开发的扩展(并且需要“ffmpeg-0.4.9_pre1 或更高版本”),这意味着您只能使用非常旧版本的 ffmpeg,无法将其更新到最新版本. 由于ffmpeg's每天都在代码内部进行大量更改/改进,因此它ffmpeg-php与最新的ffmpeg.

阅读官方文档了解更多信息。