Java实战:将RTSP/RTMP流转换为浏览器可播放的FLV格式
·
背景与痛点
最近在做一个视频监控项目时,遇到了一个经典问题:摄像头输出的RTSP流无法直接在浏览器中播放。这是因为现代浏览器基本不再支持RTSP/RTMP协议,而更倾向于使用HTTP-FLV、HLS等基于HTTP的流媒体协议。

FLV格式有几个显著优势:
- 兼容性:所有现代浏览器都支持通过flv.js等库播放FLV流
- 低延迟:相比HLS通常有2-3秒的延迟,FLV可以做到1秒以内
- 实现简单:不需要切片文件,适合实时监控场景
技术方案选型
经过调研,主要有三种实现方案:
- FFmpeg转码+WebSocket
- 优点:延迟最低,实现灵活
-
缺点:需要维护WebSocket连接
-
FFmpeg转码+HTTP-FLV
- 优点:兼容性好
-
缺点:需要HTTP服务器支持
-
商业转码服务
- 优点:开箱即用
- 缺点:成本高,可控性差
综合考虑延迟和实现复杂度,我们选择了第一种方案。
核心实现
1. FFmpeg转码
首先需要在服务器安装FFmpeg,然后通过Java调用:
ProcessBuilder pb = new ProcessBuilder(
"ffmpeg",
"-i", rtspUrl, // 输入流地址
"-c:v", "libx264", // 视频编码
"-preset", "ultrafast", // 速度优先
"-tune", "zerolatency", // 零延迟
"-f", "flv", // 输出格式
"pipe:1" // 输出到标准输出
);
Process process = pb.start();
2. WebSocket传输
使用Java的WebSocket API建立连接:
@ServerEndpoint("/live/{streamId}")
public class VideoSocket {
@OnOpen
public void onOpen(Session session) {
// 新连接建立时,创建转码进程
FFmpegProcess process = new FFmpegProcess(rtspUrl);
process.addOutputConsumer(data -> {
session.getBasicRemote().sendBinary(data);
});
}
}
3. 前端播放
使用flv.js库播放WebSocket流:
const player = flvjs.createPlayer({
type: 'flv',
url: 'ws://your-server/live/stream1',
isLive: true
});
player.attachMediaElement(videoElement);
player.load();
player.play();
性能优化
- FFmpeg参数调优
- 使用
-threads 2限制CPU占用 -
设置
-bufsize 1000k避免缓冲延迟 -
内存管理
- 使用环形缓冲区防止内存暴涨
-
及时关闭空闲连接释放资源
-
并发处理
- 每个流单独进程隔离
- 使用连接池管理WebSocket会话
常见问题
Q: 延迟越来越高怎么办? A: 检查FFmpeg的-preset和-tune参数,确保使用最低延迟配置。
Q: 内存不断增长? A: 可能是WebSocket消息积压,需要实现背压控制。
Q: 连接频繁断开? A: 增加心跳机制保持连接活跃。
安全建议
- 对输入流URL进行严格校验
- 使用wss协议加密传输
- 限制单个IP的连接数
- 实现鉴权机制

总结
这套方案在实际项目中运行稳定,1080p流平均延迟在800ms左右,CPU占用率约15%。关键点在于FFmpeg参数调优和WebSocket的合理管理。完整示例代码已放在GitHub上,欢迎交流讨论。
对于更高并发的场景,可以考虑引入Kafka等消息队列做流量削峰,这也是我们下一步的优化方向。
更多推荐


所有评论(0)