- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
当尝试使用 ffmpeg
将 wmv 文件(转换为 flv)转换为 flv 时,我在 Windows 上遇到了 proc_open
问题,但我怀疑我会遇到每当某些情况发生时,都会发生相同的情况。
基本上我的代码如下:
$descriptorspec = array
(
array("pipe", "r"),
array("pipe", "w"),
array("pipe", "w")
);
$pipes = array();
$procedure = proc_open('cd "C:/Program Files/ffmpeg/bin" && "ffmpeg.exe" -i "C:/wamp/www/project/Wildlife.wmv" -deinterlace -qdiff 2 -ar 22050 "C:/wamp/www/project/Wildlife.flv"', $descriptorspec, $pipes);
var_dump(stream_get_contents($pipes[1]));
现在,这段代码将导致 PHP 无限期挂起(如果我使用 fgets
或 stream_select
而不是 stream_get_contents
并不重要>,行为是一致的)。
它的原因(我怀疑)是,当 STDOUT 流成功打开时,进程不会向它写入任何内容(即使在 cmd 中运行相同的命令显示输出),因此,试图从这样的流,会导致与描述相同的问题 here ,所以 - PHP 等待流中有任何内容,进程不会向其中写入任何内容。
但是(额外的乐趣),设置 stream_set_timeout
或 stream_set_blocking
没有任何效果。
因此 - 有人可以确认/否认正在发生的事情,并且如果可能的话,说明我该如何应对这种情况?我查看了 PHP 错误,所有 proc_open 挂起
错误似乎都已修复。
目前我已经实现了这样的解决方案:
$timeout = 60;
while (true) {
sleep(1);
$status = proc_get_status($procedure);
if (!$status['running'] || $timeout == 0) break;
$timeout--;
}
但是,我真的不想依赖这样的东西:
此外,我真的不想等待一整分钟来检查流程(例如 - 从命令行转换给定的视频需要 <10 秒),我会制作需要更多时间的视频转换。
根据@Sjon 的评论,这是我正在使用的 stream_select
,由于相同的问题而阻塞 - STDOUT 未写入:
$descriptorspec = array
(
array("pipe", "r"),
array("pipe", "w"),
array("pipe", "w")
);
$pipes = array();
$procedure = proc_open('cd "C:/Program Files/ffmpeg/bin" && "ffmpeg.exe" -i "C:/wamp/www/sandbox/Wildlife.wmv" -deinterlace -qdiff 2 -ar 22050 "C:/wamp/www/sandbox/Wildlife.flv"', $descriptorspec, $pipes);
$read = array($pipes[0]);
$write = array($pipes[1], $pipes[2]);
$except = array();
while(true)
if(($num_changed_streams = stream_select($read, $write, $except, 10)) !== false)
{
foreach($write as $stream)
var_dump(stream_get_contents($stream));
exit;
}
else
break;
每次与@Sjon 的对话 - 从 Windows 上的缓冲流读取被破坏。最后的解决方案是通过 shell 使用流重定向,然后读取创建的文件 - 就这样
$descriptorspec = array
(
array("pipe", "r"),
array("pipe", "w"),
array("pipe", "w")
);
$pipes = array();
$procedure = proc_open('cd "C:/Program Files/ffmpeg/bin" && "ffmpeg.exe" -i "C:/wamp/www/sandbox/Wildlife.mp4" -deinterlace -qdiff 2 -ar 22050 "C:/wamp/www/sandbox/Wildlife.flv" > C:/stdout.log 2> C:/stderr.log', $descriptorspec, $pipes);
proc_close($procedure);
$output = file_get_contents("C:/stdout.log");
$error = file_get_contents("C:/stderr.log");
unlink("C:/stdout.log");
unlink("C:/stderr.log");
由于流是缓冲的,在文件中我们将得到未缓冲的输出(我也想要这样)。而且我们不需要检查文件是否更改,因为 shell 的结果是无缓冲和同步的。
最佳答案
这需要一些时间来重现,但我发现了你的问题。您运行的命令会在运行时输出一些诊断信息;但它不输出到 stdout,而是输出到 stderr。其原因在 man stderr
中解释:
Under normal circumstances every UNIX program has three streams opened for it when it starts up, one for input, one for output, and one for printing diagnostic or error messages
如果你愿意 properly use streams ;这不是问题;但是您改为调用 stream_get_contents($pipes[1])
。这导致 PHP 等待来自 stdout 的输出,而该输出永远不会到达。这个修复很简单;改为从 stderr stream_get_contents($pipes[2])
读取,脚本将在进程结束后立即退出
扩展您在问题中添加的 stream_select; stream_select 没有在 windows 中的 php 中实现,它在手册中是这样说的:
Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
因此,如果上面发布的代码不起作用;我不确定会发生什么。您是否考虑过放弃您的流解决方案,转而使用简单的 exec() 调用?如果您将 >%TEMP%/out.log 2>%TEMP%/err.log
附加到您的命令,您仍然可以从进程中读取输出并且它可能会更快地完成(无需等待不可修改的超时)
关于php - 尝试从流中读取时 proc_open 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31194152/
这个问题在这里已经有了答案: Why filter() after flatMap() is "not completely" lazy in Java streams? (8 个答案) 关闭 6
我正在创建一个应用程序来从 Instagram 收集数据。我正在寻找像 Twitter 流 API 这样的流 API,这样我就可以自动实时收集数据而无需发送请求。 Instagram 有类似的 API
我正在使用 Apache Commons 在 Google App Engine 中上传一个 .docx 文件,如此链接中所述 File upload servlet .上传时,我还想使用 Apach
我尝试使用 DynamoDB 流和 AWS 提供的 Java DynamoDB 流 Kinesis 适配器捕获 DynamoDB 表更改。我正在 Scala 应用程序中使用 AWS Java 开发工具
我目前有一个采用 H.264 编码的 IP 摄像机流式视频 (RTSP)。 我想使用 FFmpeg 将此 H.264 编码流转换为另一个 RTSP 流,但 MPEG-2 编码。我该怎么做?我应该使用哪
Redis 流是否受益于集群模式?假设您有 10 个流,它们是分布在整个集群中还是都分布在同一节点上?我计划使用 Redis 流来实现真正的高吞吐量(200 万条消息/秒),所以我担心这种规模的 Re
这件事困扰了我一段时间。 所以我有一个 Product 类,它有一个 Image 列表(该列表可能为空)。 我想做 product.getImages().stream().filter(...) 但
是否可以使用 具有持久存储的 Redis 流 还是流仅限于内存数据? 我知道可以将 Redis 与核心数据结构的持久存储一起使用,但我已经能够理解是否也可以使用 Redis 中的流的持久存储。 最佳答
我开始学习 Elixir 并遇到了一个我无法轻松解决的挑战。 我正在尝试创建一个函数,该函数接受一个 Enumerable.t 并返回另一个 Enumerable.t ,其中包含下 n 个项目。它与
我试图从 readLine 调用创建一个无限的字符串流: import java.io.{BufferedReader, InputStreamReader} val in = new Buffere
你能帮我使用 Java 8 流 API 编写以下代码吗? SuperUser superUser = db.getSuperUser; for (final Client client : super
我正在尝试服用补品routeguide tutorial,并将客户端变成rocket服务器。我只是接受响应并将gRPC转换为字符串。 service RouteGuide { rpc GetF
流程代码可以是run here. 使用 flow,我有一个函数,它接受一个键值对对象并获取它的值 - 它获取的值应该是字符串、数字或 bool 值。 type ValueType = string
如果我有一个函数返回一个包含数据库信息的对象或一个空对象,如下所示: getThingFromDB: async function(id:string):Promise{ const from
我正在尝试使用javascript api和FB.ui将ogg音频文件发布到流中, 但是我不知道该怎么做。 这是我给FB.ui的电话: FB.ui( { method: '
我正在尝试删除工作区(或克隆它以使其看起来像父工作区,但我似乎两者都做不到)。但是,当我尝试时,我收到此消息:无法删除工作区 test_workspace,因为它有一个非空的默认组。 据我所知,这意味
可以使用 Stream|Map 来完成此操作,这样我就不需要将结果放入外部 HashMap 中,而是使用 .collect(Collectors.toMap(...)); 收集结果? Map rep
当我们从集合列表中获取 Stream 时,幕后到底发生了什么?我发现很多博客都说Stream不存储任何数据。如果这是真的,请考虑代码片段: List list = new ArrayList(); l
我对流及其工作方式不熟悉,我正在尝试获取列表中添加的特定对象的出现次数。 我找到了一种使用Collections来做到这一点的方法。其过程如下: for (int i = 0; i p.conten
我希望将一个 map 列表转换为另一个分组的 map 列表。 所以我有以下 map 列表 - List [{ "accId":"1", "accName":"TestAcc1", "accNumber
我是一名优秀的程序员,十分优秀!