[英]ffmpeg live HLS inside Java ProcessBuilder- OK at first, then stalls on an empty output file
I am operating ffmpeg in live HLS broadcasting mode, executed by a ProcessBuilder under Java 16. We send PCM audio data via a pipe to the process's stdin.我在 HLS 直播模式下操作 ffmpeg,由 Java 16 下的 ProcessBuilder 执行。我们通过 pipe 向进程发送 PCM 音频数据。 Everything seems to run perfectly at first— I can open the resulting.m3u8 file locally in VLC, and the playback sounds perfect.一开始一切似乎都运行得很完美——我可以在 VLC 中本地打开生成的.m3u8 文件,并且播放听起来很完美。
Here's my StreamEncoder.java comprising said functionality.这是我的StreamEncoder.java包含所述功能。
However, after about 10 seconds, the stream stops.但是,大约 10 秒后,stream 停止。 There is no visible failure message from ffmpeg or Java.没有来自 ffmpeg 或 Java 的可见故障消息。 However, I see that the latest file ffmpeg created has 0 bytes.但是,我看到创建的最新文件 ffmpeg 有 0 个字节。
Here's the full log output from my program.这是我程序中的完整日志 output 。 At first, ffmpeg seems to be healthy.起初,ffmpeg 似乎是健康的。 Here are some highlights of what's being sent back from the inner ffmpeg process:以下是从内部 ffmpeg 流程发回的内容的一些亮点:
ffmpeg version 4.2.4-1ubuntu0.1 Copyright (c) 2000-2020 the FFmpeg developers
Output #0, hls, to '/tmp/livemusic.m3u8':
Metadata:
encoder : Lavf58.29.100
Stream #0:0: Audio: mp2, 48000 Hz, stereo, s16, delay 481, 128 kb/s
...
[hls @ 0x55c9ac4bb300] Opening '/tmp/livemusic-163910309.ts' for writing
[mpegts @ 0x55c9ac475d40] muxrate VBR, pcr every 4 pkts, sdt every 2147483647, pat/pmt every 2147483647 pkts
Output #0, hls, to '/tmp/livemusic.m3u8':
Metadata:
encoder : Lavf58.29.100
Stream #0:0: Audio: mp2, 48000 Hz, stereo, s16, delay 481, 128 kb/s
Metadata:
encoder : Lavc58.54.100 mp2
[AVIOContext @ 0x55c9ac4e5b00] Statistics: 0 seeks, 1 writeouts
[hls @ 0x55c9ac4bb300] Opening '/tmp/livemusic.m3u8.tmp' for writing
EXT-X-MEDIA-SEQUENCE:163910309
...
EXT-X-MEDIA-SEQUENCE:163910309
[AVIOContext @ 0x55c9ac4a9a00] Statistics: 0 seeks, 1 writeouts
[hls @ 0x55c9ac4bb300] Opening '/tmp/livemusic-163910316.ts' for writing
After successfully writing the first .ts files, there appears an empty file:成功写入第一个.ts文件后,出现一个空文件:
ls /tmp/*.m3u8 /tmp/*.ts -l
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:25 /tmp/livemusic-163910309.ts
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:25 /tmp/livemusic-163910310.ts
-rw-rw-r-- 1 charney charney 168260 Dec 9 18:25 /tmp/livemusic-163910311.ts
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:25 /tmp/livemusic-163910312.ts
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:25 /tmp/livemusic-163910313.ts
-rw-rw-r-- 1 charney charney 168260 Dec 9 18:25 /tmp/livemusic-163910314.ts
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:25 /tmp/livemusic-163910315.ts
-rw-rw-r-- 1 charney charney 0 Dec 9 18:25 /tmp/livemusic-163910316.ts
-rw-rw-r-- 1 charney charney 387 Dec 9 18:25 /tmp/livemusic.m3u8
The ffmpeg process is still running: ffmpeg 进程仍在运行:
ps -aef | grep ffmpeg
charney 22819 22621 0 18:25 ? 00:00:00 ffmpeg -v verbose -i pipe:0 -f hls -ac 2 -c:a mp2 -b:a 128k -minrate 128k -maxrate 128k -hls_playlist_type event -hls_segment_filename /tmp/livemusic-%d.ts -hls_time 10 -initial_offset 163910309 -start_number 163910309 /tmp/livemusic.m3u8
And, ffmpeg appears to be holding on to a filehandle for that empty file:而且,ffmpeg 似乎保留了该空文件的文件句柄:
lsof -p 22819
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ffmpeg 22819 charney cwd DIR 253,1 4096 30412671 /home/charney/livemusicproject
ffmpeg 22819 charney rtd DIR 253,1 4096 2 /
ffmpeg 22819 charney txt REG 253,1 280880 24916709 /usr/bin/ffmpeg
(...skipping items like /usr/lib/x86_64-linux-gnu/ ...)
ffmpeg 22819 charney 0r FIFO 0,12 0t0 319126 pipe
ffmpeg 22819 charney 1w FIFO 0,12 0t0 319127 pipe
ffmpeg 22819 charney 2w FIFO 0,12 0t0 319128 pipe
ffmpeg 22819 charney 3w REG 253,1 0 19146562 /tmp/livemusic-163910316.ts
When I close my program, which sends a.destroy() to the process, then suddenly and without fanfare, that last file appears at the correct size:当我关闭我的程序时,它将 a.destroy() 发送到进程,然后突然而没有大张旗鼓地,最后一个文件以正确的大小出现:
ls /tmp/*.m3u8 /tmp/*.ts -l
(...skipping same same files...)
-rw-rw-r-- 1 charney charney 168636 Dec 9 18:33 /tmp/livemusic-163910316.ts
This is not a proper answer but a rather long comment.这不是一个正确的答案,而是一个相当长的评论。 The loop looks a bit suspicious as it would be possible for bytes = queue.poll()
to be set when .ffmpeg.isAlive()
so discarding some input:该循环看起来有点可疑,因为在 .ffmpeg.isAlive() 时可能会设置bytes = queue.poll()
.ffmpeg.isAlive()
从而丢弃一些输入:
while (active) {
var bytes = queue.poll();
if (Objects.isNull(bytes)) continue;
if (!ffmpeg.isAlive()) {
LOG.error("Exited with code {}", ffmpeg.exitValue());
active = false;
continue;
}
It's hard to help without seeing more of the code including the code feeding queue
and what determines end of stream.如果没有看到更多代码,包括代码馈送queue
以及决定 stream 结束的因素,就很难提供帮助。 You need another way to signal end of processing (such as a pre-defined EOF value in the queue
- if (bytes == MYEOF) break;
. When you determine that no more data is being sent to ffmpeg queue
, you could try signalling the end of ffmpeg STD input stream by calling ffmpeg.getOutputStream().close()
.您需要另一种方式来表示处理结束(例如queue
中的预定义 EOF 值 - if (bytes == MYEOF) break;
。当您确定没有更多数据发送到 ffmpeg queue
时,您可以尝试发信号通过调用ffmpeg.getOutputStream().close()
结束 ffmpeg STD 输入 stream 。
Also you don't call ffmpeg.waitFor()
to confirm that the ffmpeg
sub-process has ended.此外,您不要调用ffmpeg.waitFor()
来确认ffmpeg
子流程已结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.