简介

本文将尝试指出在PHP Web脚本中使用FFmpeg时需要了解的所有重要事项。它还将显示一些使用示例,以使事情更清楚。这个想法也可以应用到其他web脚本语言。

从PHP脚本调用命令行工具

选择一个模型

网页设计为快速执行,以便浏览您的网站的人不必等待太多的响应。因为如果他们无聊的等待,他们只会导航到另一个,更灵敏(通常是您的竞争对手的)网站。话虽如此,你可以做的最糟糕的事情是从你的web脚本运行一个命令行工具(如ffmpeg),并等待它完成处理,以便能够将结果返回到等待在线用户(异常这是小/快的工具,其执行时间太小而不能注意到)。

您想要做的是将命令行工具的长处理与Web脚本执行分开,以使脚本更具响应性。所以,你有至少两个选项:

  1. 运行命令行工具(使用了shell_exec()在后台为例),并继续与web脚本执行,定期刷新状态页面,显示当前进度

  1. 创建一个新的“作业”(通常是数据库表中的一个新行),并有一些背景“工作”进程(cron作业,shell脚本,批处理脚本),它将监视“作业列表”需要处理的新工作

这两种方法看起来是一样的,但是他们不是。最重要的区别是,第二种方法可以更好地扩展更高的网站流量,因为它允许“工作”进程在完全独立的机器上运行。此外,可以有几个“工作”机器,一起工作,分裂工作负载,涉及小的同步。

第一种方法通常是大多数想要快速完成工作的人的首选,但是在他们的网站变得流行的时间,他们的web服务器变得不那么敏感,由于不断的cpu饥饿,由多个命令行工具(ffmpeg实例)在后台运行。在那一刻,他们通常开始考虑第二种方法。

在后台运行的ffmpeg

以下示例适用于基于Linux的操作系统。对于基于Windows的操作系统,请继续阅读本文,而是你读了之后,也看到了如何使用START和CMD后台运行的过程。这将给你一个想法如何应用相同的逻辑到基于Windows的操作系统。

让我们考虑从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()函数,上面写着:

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

该说的部分“ >的/ dev / null的 ”将FFmpeg的实例的标准输出(stdout)重定向到/ dev / null的(有效地忽略输出)和“ 2>的/ dev / null的 ”将重定向标准错误(错误)到/ dev / null(有效地忽略任何错误日志消息)。这两个可以组合成一个较短的表示:“ >的/ dev / null的2>&1 ”。如果你喜欢,你可以阅读更多关于I / O重定向

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

需要注意的另一件事是标准INPUT(stdin)。命令行ffmpeg工具被设计为一个交互式实用程序,它接受用户的输入(通常来自键盘),并在用户的当前屏幕/终端上报告错误日志。当我们在后台运行ffmpeg时,我们想要告诉ffmpeg没有从stdin接受任何输入(也不等待)。我们可以告诉这ffmpeg的,再次使用I / O重定向“ <的/ dev / null的 ”,这样最后一个例子,安全运行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)不要求是/否确认。如果需要相反的情况,如果输出文件已经存在,要自动取消整个过程,请改用“-n”选项。

包装库

一些PHP库允许将ffmpeg调用包装到PHP对象中,并且如果您不喜欢使用命令行,可以为您提供一个不错的语法。其中之一是在积极维护PHP-FFmpeg的。它只需要你下载一个最新的ffmpegffprobe从安装PHP组件构建分开。然后你可以这样运行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不兼容。

案例成功测试结果:

<?php
echo "正在启动ffmpeg...\n\n";
echo shell_exec("ffmpeg -y -i rtmp://tinywan.123.com/live/4001483413136 -c copy -f flv rtmp://131.180/live/4001483492781?vhost=13.168 </dev/null >/dev/null 2>/var/log/ffmpeg.log &");
echo "完成.\n";
正在启动ffmpeg...

完成.

日志文件:

ffmpeg version 2.3.git Copyright (c) 2000-2014 the FFmpeg developers
built on Sep 1 2014 19:01:47 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --prefix=/usr/local/ffmpeg/build --extra-cflags=-I/usr/local/ffmpeg/build/include --extra-ldflags=-L/usr/local/ffmpeg/build/lib --bindir=/usr/local/ffmpeg/bin --enable-gpl --enable-libass --enable-libfaac --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-openssl --enable-libspeex --enable-libxvid
libavutil 54. 7.100 / 54. 7.100
libavcodec 56. 1.100 / 56. 1.100
libavformat 56. 3.100 / 56. 3.100
libavdevice 56. 0.100 / 56. 0.100
libavfilter 5. 0.103 / 5. 0.103
libswscale 3. 0.100 / 3. 0.100
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 0.100 / 53. 0.100
[flv @ 0x2862000] Stream discovered after head already parsed
Last message repeated 1 times
Input #0, flv, from 'rtmp://tinywan.3213.com/live/4001483413136':
Metadata:
Server : Tengine
displayWidth : 1920
displayHeight : 1080
fps : 25
profile :
level :
Duration: 00:00:00.00, start: 765.097000, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(tv, bt709), 1920x1080, 1048 kb/s, 25 fps, 25 tbr, 1k tbn, 2k tbc
Stream #0:1: Data: none
Stream #0:2: Audio: aac, 44100 Hz, stereo, fltp
Output #0, flv, to 'rtmp://1232130/live/4001483492781?vhost=321312':
Metadata:
Server : Tengine
displayWidth : 1920
displayHeight : 1080
fps : 25
profile :
level :
encoder : Lavf56.3.100
Stream #0:0: Video: h264 ([7][0][0][0] / 0x0007), yuv420p, 1920x1080, q=2-31, 1048 kb/s, 25 fps, 1k tbn, 1k tbc
Stream #0:1: Audio: aac ([10][0][0][0] / 0x000A), 44100 Hz, stereo
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:2 -> #0:1 (copy)
Press [q] to stop, [?] for help

测试成功!

 

参考文献:http://trac.ffmpeg.org/wiki/PHP

PHP基础知识之————PHP Web脚本中使用FFmpeg的更多相关文章

  1. 《JAVASCRIPT高级程序设计》表单基础知识和文本框脚本

    在HTML中,表单是由<form>元素来表示,在javascript中,表单对应的是HTMLFormElement类型,它具有一些独有的属性和方法: 一.表单基础知识 1.取得表单的方式 ...

  2. C#基础知识汇总(不断更新中)

    ------------------------------目录---------------------------- 1.隐式类型2.匿名类型3.自动属性4.初始化器5.委托6.泛型7.泛型委托8 ...

  3. 视频基础知识:浅谈视频会议中H.264编码标准的技术发展

    浅谈视频会议中H.264编码标准的技术发展 浅谈视频会议中H.264编码标准的技术发展 数字视频技术广泛应用于通信.计算机.广播电视等领域,带来了会议电视.可视电话及数字电视.媒体存储等一系列应用,促 ...

  4. java基础知识汇总(持续更新中....)

    1.java四大特性:抽象.继承.封装,多态 构造函数: http://blog.csdn.net/qq_33642117/article/details/51909346 2.java数据基本类型: ...

  5. Java基础知识强化106:Java中 int 的各进制之间的转换

    1.二.八.十.十六进制之间的转换  下面是示例代码,我们直接通过JDK工具库中的方法实现的,如下: public static Integer valueOf(String s, int radix ...

  6. Java基础知识强化101:Java 中的 String对象真的不可变吗 ?

    1. 什么是不可变对象?       众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...

  7. Java基础知识强化03:Java中的堆与栈

    1.在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题. 一般,JV ...

  8. Java基础知识强化13:Java中单例模式案例使用(懒汉式)

    1.古往今来历史上皇帝通常只有一人.为了保证其唯一性,古人采用增加"防伪标识"的办法,如玉玺.更为简单的办法就是限制皇帝的创建.本案例中就是使用单例模式从而保证皇帝的唯一性.实例运 ...

  9. Java基础知识强化12:Java中运用数组的四种排序方法

    1.使用JavaApi文档中的Arrays类中的sort()进行快速排序 首先我们直接看代码如下: package himi.text; import java.util.Arrays; public ...

随机推荐

  1. JavaWeb-spring

    Java反射机制 import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Reflect ...

  2. jQuery EasyUI 使用笔记

    大家有四次抢票机会.第一次是放票时间之后的30分钟.第二次机会是开车前的15天.第三个机会是开车前的48小时.第四个机会是开车前的24小时. $("#gys_key").combo ...

  3. qt之串口

                                          qt串口讲解在QT中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也使用这个 ...

  4. java compiler level does not match the version of the installed java project facet

    Java compiler level does not match the version of the installed java project facet错误的解决 因工作的关系,Eclip ...

  5. jqGrid APi 详解

    jqGrid APi 详解 jqGrid皮肤 从3.5版本开始,jqGrid完全支持jquery UI的theme.我们可以从http://jqueryui.com/themeroller/下载我们所 ...

  6. Meteor全栈开发平台 - 不仅仅是前端

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...

  7. Repeater的Item项绑定DropDownList

    前台页面: <asp:Repeater ID="rptJgtList" runat="server" OnItemDataBound="rptJ ...

  8. Make cnblogs mobile Compatible

    Introduction 博客园的许多页面都是只支持PC的,没有手机端的,也没有手机端的app.每次查看都有放大了才能看清楚字体,手指和游泳似的,左右开弓,很不方便.还有上次我修改了theme之后,手 ...

  9. STM32的USART中断死循环,形成死机。

    作者:观海  QQ:531622 直接说重点:我用的是 STM32F103 芯片 USART2_IRQHandler 总是中断,程序死循环. 1.出现问题: 原程序的中断处理程序是: void USA ...

  10. Logstash学习-配置语法

    区段(section) Logstash 用{}来定义区域.区域内可以包括插件区域定义,你可以在一个区域定义多个插件,插件区域内则可以定义键值对设置. 数据类型 Logstash支持少量的数据值类型: ...