前言
最近要实现将相机返回的照片合并成视频流并推送的功能,目前的话是通过JavaCV来实现对图片的合并以及推流,流媒体服务器选择Zlmediakit,一款基于C++的高性能流媒体服务器。
JavaCV网址
https://github.com/bytedeco/javacv
Zlmediakit网址
1. Zlmediakit搭建
官方提供docker镜像可以直接docker部署,就是需要注意把配置文件拷贝出来,方便修改
我是在Ubuntu22.04上部署的,参考指令如下:
# 创建 zlmediakit 目录
sudo mkdir -p /home/docker/zlmediakit
sudo chmod 777 /home/docker/zlmediakit
# 先拉取镜像并运行 zlmediakit
sudo docker run -id -p 1935:1935 -p 8080:80 -p 8443:443 \
-p 8554:554 -p 10000:10000 -p 10000:10000/udp \
-p 8000:8000/udp -p 9000:9000/udp \
--name zlmediakit \
zlmediakit/zlmediakit:master
# 复制 zlmediakit 容器文件到指定目录
sudo docker cp -a zlmediakit:/opt/media /home/docker/zlmediakit
# 删除 zlmediakit 容器
sudo docker rm -f zlmediakit
# 自定义修改/home/docker/zlmediakit/media/conf/config.ini文件
# 重新创建容器并挂载自定义的配置
sudo docker run -id -p 1935:1935 -p 8080:80 -p 8443:443 \
-p 8554:554 -p 10000:10000 -p 10000:10000/udp \
-p 8000:8000/udp -p 9000:9000/udp \
--name zlmediakit \
-v /home/docker/zlmediakit/media/bin:/opt/media/bin \
-v /home/docker/zlmediakit/media/conf:/opt/media/conf \
zlmediakit/zlmediakit:master
2. JavaCV的demo代码
添加Maven依赖,整体jar包比较大需要耐心下载
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.9</version>
</dependency>
demo代码,读取文件夹下的图片转成Frame对象并推流到流媒体服务器
这里推流的地址是:rtsp://192.168.10.80:8554/live/1
这里需要注意rtsp默认的端口号是554,默认端口号是不用加的,但是我用docker部署把554端口映射成了8554,这边必须要加上才行
package com.example;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
public class RtspPusherDemo {
public static void main(String[] args) {
String imageDirectory = "D:\\temp\\images"; // 图片文件夹路径
String rtspUrl = "rtsp://192.168.10.80:8554/live/1";
FFmpegLogCallback.set(); //打印ffmpeg的日志
int frameRate = 30; // 视频帧率
int imageWidth = 384; // 图片宽度
int imageHeight = 283; // 图片高度
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtspUrl, imageWidth, imageHeight);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
recorder.setFormat("rtsp");
recorder.setFrameRate(frameRate);
recorder.setOption("rtsp_transport", "tcp"); // 设置 RTSP 传输协议为 TCP
try {
recorder.start();
Frame capturedFrame = null;
Java2DFrameConverter converter = new Java2DFrameConverter();
File imageFolder = new File(imageDirectory);
File[] imageFiles = imageFolder.listFiles();
while (true) {
for (File imageFile : imageFiles) {
if (imageFile.isFile()) {
BufferedImage image = ImageIO.read(new FileInputStream(imageFile.getAbsolutePath()));
capturedFrame = converter.getFrame(image);
recorder.record(capturedFrame);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行后用vlc播放器拉取流
拉流地址是:rtsp://192.168.10.80:8554/live/1