作者:鹏63213 | 来源:互联网 | 2023-07-29 16:54
通过JavaCV框架的FFmpegFrameGrabber读取本地一个视频流的帧,接着Java2DFrameConverter先把帧转换为图片,由Graphics2D进行文本刷到图
通过Java CV框架的FFmpegFrameGrabber读取本地一个视频流的帧,接着Java2DFrameConverter先把帧转换为图片,由Graphics2D进行文本刷到图片上后,Java2DFrameConverter再把合成的图片转回帧,最后由FFmpegFrameRecorder把帧写入输出视频流。
直接上代码:
package com.lxy.service;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;
import org.bytedeco.opencv.opencv_core.*;
import sun.font.FontDesignMetrics;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class LiveMixService {
public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception {
// 构造测试字幕
String[] test = {
"世上无难事",
"只怕有心人",
"只要思想不滑坡",
"办法总比困难多",
"长江后浪推前浪",
"前浪死在沙滩上"
};
// 为连续的50帧设置同一个测试字幕
List testStr = new ArrayList<>();
for (int i = 0; i <300; i++) {
testStr.add(test[i / 50]);
}
// 设置源视频、加字幕后的视频
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault("E:\\BaiduNetdiskDownload\\testout.mkv");
FFmpegFrameRecorder recorder = FFmpegFrameRecorder.createDefault("E:\\BaiduNetdiskDownload\\outtest.mp4",
1280, 720);
System.out.println("准备开始推流...");
grabber.start();
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
Frame frame = null;
int i = 0;
while ((frame = grabber.grabImage()) != null) {
// 从视频帧中获取图片
BufferedImage bufferedImage = converter.getBufferedImage(frame);
bufferedImage = addSubtitle(bufferedImage, testStr.get(i++ % 300));
frame.image = converter.getFrame(bufferedImage).image;
recorder.record(frame);
}
grabber.stop();
recorder.stop();
}
/**
* 图片添加文本
* @param bufImg
* @param subTitleContent
* @return
*/
private static BufferedImage addSubtitle(BufferedImage bufImg, String subTitleContent) {
// 添加字幕时的时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Font font = new Font("微软雅黑", Font.BOLD, 32);
String timeContent = sdf.format(new Date());
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
Graphics2D graphics = bufImg.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//设置图片背景
graphics.drawImage(bufImg, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
//设置左上方时间显示
graphics.setColor(Color.orange);
graphics.setFont(font);
graphics.drawString(timeContent, 0, metrics.getAscent());
// 计算文字长度,计算居中的x点坐标
int textWidth = metrics.stringWidth(subTitleContent);
int widthX = (bufImg.getWidth() - textWidth) / 2;
graphics.setColor(Color.red);
graphics.setFont(font);
graphics.drawString(subTitleContent, widthX, bufImg.getHeight() - 50);
graphics.dispose();
return bufImg;
}
}
看下效果: