图片合成效果,不再演示,主要演示视频合成效果,因为是视频合成的原理就是先将每一张帧图合成图片,再用合成的图片制作成视频。
视频左右翻转合成效果
javacv实现视频翻转,合成
四宫格视频
更多视频展示链接
https://live.csdn.net/v/164980
注:原视频都来自于抖音。
Java spring boot项目或者maven项目的pom文件中添加以下依赖
org.bytedeco
javacv-platform
1.5.5
核心代码,单类实现,idea创建VideoSynthesis 类,复制粘贴下面代码,右键点击run运行主方法即可。
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
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.IOException;
public class VideoSynthesis {
final static String videoFolderPath = "C:/Users/tarzan/Desktop/video/";
final static String videoName = "video.mp4";
final static String imageFolderPath = "C:/Users/tarzan/Desktop/image/";
final static String imageName1 = "logo.jpg";
final static String imageName2 = "newlogo.jpg";
public static void main(String[] args) throws Exception {
// mergeImage(imageFolderPath + imageName1, imageFolderPath + imageName2);
mergeVideo(videoFolderPath + videoName);
}
//视频处理
public static void mergeVideo(String filePath) {
//抓取视频图像资源
FFmpegFrameGrabber videoGrabber = new FFmpegFrameGrabber(filePath);
//抓取视频图像资源
FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber(filePath);
try {
videoGrabber.start();
audioGrabber.start();
//imageWidth和imageHeight根据需要合成的大小进行计算,比如左右2宫格宽度需要乘以2,四宫格宽、高都要乘以2,依次类推
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(videoFolderPath + "合成" + videoName, videoGrabber.getImageWidth()*2, videoGrabber.getImageHeight(), videoGrabber.getAudioChannels());
recorder.start();
//处理图像
int videoSize = videoGrabber.getLengthInVideoFrames();
for (int i = 0; i < videoSize; i++) {
Frame videoFrame = videoGrabber.grabImage();
if (videoFrame != null && videoFrame.image != null) {
System.out.println("视频共" + videoSize + "帧,正处理第" + (i + 1) + "帧图片");
Java2DFrameConverter converter = new Java2DFrameConverter();
//获得原图帧
BufferedImage bi = converter.getBufferedImage(videoFrame);
//获得翻转图帧
BufferedImage bi2= imageFlipLR(bi);
//获得左右合成图帧
BufferedImage bufImg=mergeImageLR(bi,bi2);
// bufImg= mergeImageCenter(bufImg,bi);
recorder.record(converter.convert(bufImg));
}
}
//处理音频
int audioSize = audioGrabber.getLengthInAudioFrames();
for (int i = 0; i < audioSize; i++) {
Frame audioFrame = audioGrabber.grabSamples();
if (audioFrame != null && audioFrame.samples != null) {
recorder.recordSamples(audioFrame.sampleRate, audioFrame.audioChannels, audioFrame.samples);
}
}
recorder.stop();
recorder.release();
videoGrabber.stop();
audioGrabber.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
//合拼图片
public static void mergeImage(String imgPath1, String imgPath2) {
try {
BufferedImage bi_1 = ImageIO.read(new File(imgPath1));
BufferedImage bi_2 = ImageIO.read(new File(imgPath2));
BufferedImage mergeImage = mergeImageLR(bi_1, bi_2);
ImageIO.write(mergeImage, "png", new File(imageFolderPath + imageName1 + "merge" + imageName2));
} catch (IOException e) {
e.printStackTrace();
}
}
//小图放到大图中间位置
public static BufferedImage mergeImageCenter(BufferedImage big, BufferedImage small) {
//new 一个新的图像
int w = small.getWidth();
int h = small.getHeight();
int wd = small.getWidth()/2;
int hd = small.getHeight()/2;
//像素一个一个复制过来
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
big.setRGB(x+wd, y+hd, small.getRGB(x, y));
}
}
return big;
}
//左右翻转
public static BufferedImage imageFlipLR(BufferedImage bi) {
int h = bi.getHeight();
int w = bi.getWidth();
BufferedImage image = new BufferedImage(w, h, bi.getType());
//像素一个一个复制过来
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
image.setRGB(x, y, bi.getRGB(w-x-1, y));
}
}
return image;
}
//左右合并
public static BufferedImage mergeImageLR(BufferedImage bi_1, BufferedImage bi_2) {
//new 一个新的图像
int w1 = bi_1.getWidth();
int w2 = bi_2.getWidth();
int h = bi_1.getHeight();
int w = w1 + w2;
BufferedImage bi = new BufferedImage(w, h, bi_1.getType());
//像素一个一个复制过来
for (int y = 0; y < h; y++) {
for (int x = 0; x < w1; x++) {
bi.setRGB(x, y, bi_1.getRGB(x, y));
}
for (int x = 0; x < w2; x++) {
bi.setRGB(w1 + x, y, bi_2.getRGB(x, y));
}
}
return bi;
}
//上下合并
public static BufferedImage mergeImageUD(BufferedImage bi_1, BufferedImage bi_2) {
//new 一个新的图像
int h1 = bi_1.getHeight();
int h2 = bi_2.getHeight();
int h = h1+h2;
int w = bi_1.getWidth();
BufferedImage bi = new BufferedImage(w, h, bi_1.getType());
//像素一个一个复制过来
for (int x = 0; x < w; x++) {
for (int y = 0; y < h1; y++) {
bi.setRGB(x, y, bi_1.getRGB(x, y));
}
for (int y = 0; y< h2; y++) {
bi.setRGB(x, h1+y, bi_2.getRGB(x, y));
}
}
return bi;
}
}
由于视频中的每一帧需要合成处理,过程可能辉有点慢,像文章中的视频,原视频3.93MB,经过翻转处理、左右合成处理的方法,处理时间月20s左右。
控制台运行输出日志
代码里还写了上下合成、小图放在大图的中心位置等方法,方便你处理各种需求。
相关文章推荐
《震惊,java仅用30行代码就实现了视频转音频的批量转换》
特别说明:如需转载此篇文章,请先关注本人后,注明作者名称,和文章链接地址即可。