You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让FFmpeg持续转换新增图片至HLS并可随时停止及清理TS文件?

解决FFmpeg处理摄像头图片转HLS时的TS文件堆积与持续转换问题

首先得说,你现在遇到的TS文件堆积问题,根源在于每次新增图片就启动新的FFmpeg进程——delete_segments参数是针对单个FFmpeg进程生成的片段生效的,新进程根本不知道旧进程生成的文件,自然没法清理。要解决这个问题,核心是让FFmpeg保持一个持续运行的进程,处理源源不断的图片流,而不是频繁启停。

用FFmpeg管道输入实现持续转换(你的方案2的具体实现)

不用把图片存到目录再触发FFmpeg,直接把Java获取的摄像头图片通过管道流传给FFmpeg,让它一直运行并处理帧:

1. 搭建数据流管道

Java端获取到摄像头的图片(比如逐帧的JPEG数据)后,直接把数据流输出到标准输出(stdout);同时启动一个FFmpeg进程,让它从标准输入(stdin)读取图片流。

2. FFmpeg命令示例

ffmpeg -f image2pipe -vcodec mjpeg -i - -c:v libx264 -preset ultrafast -f hls \
  -hls_time 2 \
  -hls_list_size 10 \
  -hls_delete_threshold 3 \
  -hls_flags delete_segments \
  -hls_segment_filename "stream_%03d.ts" \
  output.m3u8

参数解释:

  • -f image2pipe -i -:告诉FFmpeg从标准输入读取图片流
  • -vcodec mjpeg:指定输入的图片编码是JPEG(和你的摄像头输出匹配)
  • -hls_time 2:每个TS片段时长2秒
  • -hls_list_size 10:m3u8列表里只保留最新的10个片段
  • -hls_delete_threshold 3:当片段数量超过列表大小3个时,自动删除旧片段
  • -hls_flags delete_segments:启用自动删除超出列表的旧TS文件

这样FFmpeg会持续运行,只要Java不断传图片过来,它就会一直生成TS片段,同时自动清理超出保留数量的旧文件——完美解决你的存储占用问题。

如何随时停止FFmpeg进程

当用户停止观看时,你不需要粗暴杀死进程,而是给FFmpeg发一个优雅停止的信号:

  • 在Linux/macOS环境下,用C++的kill()函数给FFmpeg进程发送SIGINT(等同于按Ctrl+C)或者SIGTERM信号
  • 在Windows环境下,用GenerateConsoleCtrlEvent发送CTRL_C_EVENT信号

FFmpeg收到信号后,会先写完当前的TS片段,更新m3u8索引,然后才退出,不会留下损坏的文件或未清理的冗余片段。

架构调整建议(轻量重构,不用大改)

不用每次有图片就启动新进程,改成:

  1. 用户发起观看请求时,C++启动一个绑定该用户的FFmpeg进程,同时建立Java到FFmpeg的管道流
  2. Java持续把摄像头图片输出到这个管道,FFmpeg实时转码生成HLS流
  3. 用户停止观看时,C++给对应的FFmpeg进程发送停止信号,进程优雅退出,自动清理多余TS文件

这个方案比你说的方案1(独立删文件)更可靠,完全用FFmpeg自身的HLS管理功能解决问题,还减少了频繁创建进程的系统开销。

额外注意点

  • Java端要尽量保证图片的帧率稳定(比如每秒15帧),否则FFmpeg可能生成卡顿的视频;如果摄像头帧率不稳定,可以给FFmpeg加-r 15参数强制设置输出帧率
  • 如果有多个用户同时观看,你可以考虑为每个用户启动独立的FFmpeg进程,这种方式更简单易维护;如果要优化资源,也可以研究HLS的多码率复用,但复杂度会更高
  • 测试时可以先手动模拟图片流,比如用cat *.jpg | ffmpeg ...命令验证管道输入是否正常工作

内容的提问来源于stack exchange,提问作者Jongseok Yoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:02:35