php - 如何以编程方式启动/停止 FFMPEG 流转码

标签 php macos bash ffmpeg webcam

我有一个提供 MJPEG 流的 ip 网络摄像头。我可以在 OSX 下使用 ffmpeg 成功转码并保存该流。以下几乎可以满足我的需求:

ffmpeg -f mjpeg -i "http://user:pass@10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4

这将启动一个 FFMPEG session 并开始将实时流保存到我的 test.mp4 文件中。按 q 将退出 ffmpeg 并保存文件。

我想使用 PHP 或 Bash shell 脚本以编程方式开始和停止录制。我尝试了以下方法:

<?php

$pid = pcntl_fork();

if($pid == -1){
    die("could not fork"); 
}elseif($pid){
    // we are the parent...
    print $pid.' started recording. waiting 10 seconds...';
    sleep(10); // Wait 10 seconds

    print_r(shell_exec("kill ".$pid)); // Kill the child recording process

    echo 'done';
    exit(); 
}else{
    // we are the child process. call ffmpeg.
    exec('../lib/ffmpeg -f mjpeg -i "http://user:pass@10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4');
}

但是有两个问题:

  1. ffmpeg 进程没有结束/死亡(可能是因为它再次 fork )
  2. 当我手动杀死 ffmpeg 进程时,视频文件不可读

最佳答案

所以我做错了一些事情。

对于初学者,我需要将输出形式的 ffmpeg 推送到日志文件,并告诉它覆盖我的临时文件而不提示使用 -y 参数。

所以代替

ffmpeg -f mjpeg -i "http://user:pass@10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4

我正在使用

ffmpeg -y -f mjpeg -i "http://user:pass@10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4 </dev/null >/dev/null 2>/tmp/ffmpeg.log &

第二个问题是我在向 ffmpeg 发送 kill 命令之前等待的时间不够长,因此创建了一个损坏的文件。

通过添加带有 1 秒的 -t(时间限制)参数,我确定 ffmpeg 平均需要 15 秒来录制 1 秒的视频。将时间限制增加到 10 秒会使平均增加到 25 秒,所以看起来至少在我的服务器上,有 14 秒的开销。通过将我的 php 脚本中的 sleep 命令增加到 30 秒,我能够获得可用的视频文件。

因此,让 PHP 杀死 ffmpeg 进程会导致未知(或最多近似)的记录时间长度,这完全取决于 CPU 功率、网络带宽等。

这有点令人失望,因为我曾希望能够根据一些外部变量来增加记录长度(我有输入数据库的 insteon 运动传感器,我想记录直到运动停止)。

无论如何,这是一个有效的 PHP 脚本,以防将来对某人有所帮助:

<?php
print date('H:i:s')."\nStarted recording. waiting 60 seconds...\n";
exec('../lib/ffmpeg -y -f mjpeg -i "http://user:pass@10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4 </dev/null >/dev/null 2>/tmp/ffmpeg.log &');
sleep(60); // Wait long enough before killing, otherwise the video will be corrupt!

shell_exec('pkill ffmpeg'); // find and kill    
echo "done\n\n";
exit(); 
?>

关于php - 如何以编程方式启动/停止 FFMPEG 流转码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21529348/

相关文章:

java - Linux cp 命令在 Java ProcessBuilder 中不起作用

php - 使用codeigniter在mysql中插入多行: it inserts only one row and in that one row stores only one first character

php - 如何更新 mysql 数据库 WHERE value = PHP 数组中的值?

javascript - 单击按钮时将 twig 中的 javascript 变量传递给 php Controller

macos - OS X 使用安全框架加载 PEM 证书

单个 View 的 macOS SwiftUI 导航

bash - 在不影响 Vim 和行返回的情况下将最后执行的命令的输出捕获到变量中

bash - 如何让空参数在命令替换中继续存在?

php - 从 CronJob 启动时,Unix .sh 文件工作不正确

macos - 防止多个用户在 macOS 上同时运行应用程序