【问题标题】:How to programmatically start/stop FFMPEG stream transcoding如何以编程方式启动/停止 FFMPEG 流转码
【发布时间】:2014-02-27 01:21:23
【问题描述】:

我有一个提供 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 会话并开始将实时流保存到我的 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 进程没有结束/终止(可能是因为它再次分叉)
  2. 当我手动终止 ffmpeg 进程时,视频文件不可读

【问题讨论】:

    标签: php macos bash ffmpeg webcam


    【解决方案1】:

    所以我做错了一些事情。

    对于初学者,我需要将输出表单 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 &
    

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

    通过将 -t(用于时间限制)参数添加 1 秒,我确定 ffmpeg 录制 1 秒的视频平均需要 15 秒。将时间限制增加到 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(); 
    ?>
    

    【讨论】:

      【解决方案2】:

      发送“q”键:

      process.StandardInput.WriteLine("q");
      

      【讨论】:

      • 你能用什么语言做到这一点?!
      • 我忘了说我用的是C#
      • 啊。不过,问题是关于 PHP 的。从这个意义上说,我认为您的答案没有用。
      【解决方案3】:

      向后台进程发送SIGQUIT信号,正常终止ffmpeg命令。

      随便用

      kill -s QUIT $PID
      

      该过程将以未损坏的 MP4 视频文件结束。

      【讨论】:

        猜你喜欢
        • 2017-11-10
        • 2016-08-19
        • 2019-03-16
        • 1970-01-01
        • 1970-01-01
        • 2011-06-13
        • 1970-01-01
        • 1970-01-01
        • 2018-10-12
        相关资源
        最近更新 更多