簡體   English   中英

ffmpeg 在 Java ProcessBuilder 中運行 HLS - 首先是好的,然后停在一個空的 output 文件上

[英]ffmpeg live HLS inside Java ProcessBuilder- OK at first, then stalls on an empty output file

我在 HLS 直播模式下操作 ffmpeg,由 Java 16 下的 ProcessBuilder 執行。我們通過 pipe 向進程發送 PCM 音頻數據。 一開始一切似乎都運行得很完美——我可以在 VLC 中本地打開生成的.m3u8 文件,並且播放聽起來很完美。

這是我的StreamEncoder.java包含所述功能。

但是,大約 10 秒后,stream 停止。 沒有來自 ffmpeg 或 Java 的可見故障消息。 但是,我看到創建的最新文件 ffmpeg 有 0 個字節。

這是我程序中的完整日志 output 起初,ffmpeg 似乎是健康的。 以下是從內部 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

成功寫入第一個.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

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

而且,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                           

當我關閉我的程序時,它將 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

這不是一個正確的答案,而是一個相當長的評論。 該循環看起來有點可疑,因為在 .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;
    }

如果沒有看到更多代碼,包括代碼饋送queue以及決定 stream 結束的因素,就很難提供幫助。 您需要另一種方式來表示處理結束(例如queue中的預定義 EOF 值 - if (bytes == MYEOF) break; 。當您確定沒有更多數據發送到 ffmpeg queue時,您可以嘗試發信號通過調用ffmpeg.getOutputStream().close()結束 ffmpeg STD 輸入 stream 。

此外,您不要調用ffmpeg.waitFor()來確認ffmpeg子流程已結束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM