php - FFMpeg 在命令行中工作但不在 PHP 脚本中工作

标签 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

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

谢谢。

最佳答案

从 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() 函数的注释之一中提到:

If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

不要对显示 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" 将标准 ERROR (stderr) 重定向到 /dev/null(有效地忽略任何错误日志消息)。这两个可以组合成一个更短的表示:">/dev/null 2>&1"。如果愿意,您可以阅读有关 I/O 重定向的更多信息。

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

需要注意的另一件事是标准输入 (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";
?>

“-y” 选项用于自动覆盖输出文件 (output.avi) 而无需请求 yes/no 确认。如果您需要相反的场景,在输出文件已经存在的情况下自动取消整个过程,请改用 "-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')

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

注意: ffmpeg-php是自 2007 年以来未开发的扩展(并且需要 “ffmpeg-0.4.9_pre1 或更高版本”),这意味着您只能使用非常旧的 ffmpeg 版本,无法更新它到最新版本。由于每天在 ffmpeg 的 代码中进行大量更改/改进,这使得 ffmpeg-php 与最新的 ffmpeg 不兼容。

阅读official documentation了解更多信息。

关于php - FFMpeg 在命令行中工作但不在 PHP 脚本中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26794297/

相关文章:

php - 如何使 PHP 库适应 Codeigniter?

ffmpeg - 如何使用 tee 输出 rtmp 和 ffmpeg 命令的一个标准输出?

android - 如何使用cygwin和android ndk r9c在windows上编译ffmpeg-2.2.2

video - 限制在其他网站上嵌入 youtube

audio - 如何在包含两个或多个音轨的视频文件中使用 ffmpeg 更改音频语言

php - 我如何使用 phpseclib 创建自签名证书

php - Laravel 5 - Nginx/PHP 配置问题

php - Joomla 模块 “know” 可以在什么位置? (2)

xcode - Ipad MPMovieplayerController 视频加载但播放时自动暂停

c++ - 优化 YUY2 到 I420 的转换