Merge two videos in Java , video fade in from right side and fade out to left
Two videos , one video fade out from right to left side , the other video fade in from right to left.
We can use JavaCV FFmpeg package to create such video effective.
The steps:
1.Load two video , video one and video two
2.Get the video information like frame rate , frame number,duration
3.Get the start frame number that start to fade out/in for both videos
4.Get the end frame number that fade out/in complete for both videos
5.Merge above two frames with corresponding gradient
The code:
public void mergeVideo() { String videoOne = "video-1.mp4" String videoTwo = "video-2.mp4" String mergedVideo="mergedVideo.mp4"; try { //load video one FFmpegFrameGrabber grabberOne = FFmpegFrameGrabber.createDefault(videoOne); grabberOne.start(); //load video two FFmpegFrameGrabber grabberTwo = FFmpegFrameGrabber.createDefault(videoTwo); grabberTwo.start(); //get the width and height for merged video int maxWidth=grabberOne.getImageWidth()>grabberTwo.getImageWidth()?grabberOne.getImageWidth():grabberTwo.getImageWidth(); int maxHeight=grabberOne.getImageHeight()>grabberTwo.getImageHeight()?grabberOne.getImageHeight():grabberTwo.getImageHeight(); //create merged video FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mergedVideo, maxWidth, maxHeight); recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4); recorder.setFormat("mp4"); recorder.setFrameRate(grabberOne.getFrameRate()); recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); recorder.start(); //get amount of frame int totalOne =grabberOne.getLengthInFrames(); double frameRateOne=grabberOne.getFrameRate(); int totalTwo=grabberTwo.getLengthInFrames(); double frameRateTwo=grabberTwo.getFrameRate(); //get duration in seconds long durationInSec = grabberOne.getFormatContext().duration() / 1000000; long durationTwoInSec = grabberTwo.getFormatContext().duration() / 1000000; //get start frame number for video one fade out int startFrameNum = getStartOrEndFrameNumber(3, durationInSec, totalOne); int endFrameNum = getStartOrEndFrameNumber(8, durationInSec, totalOne); //get start framte number for video two fade in int grabeTwoEndFrameNum =getStartOrEndFrameNumber(5, durationTwoInSec, totalTwo); LOGGER.info("1st duration {}",durationInSec); LOGGER.info("1st total {}",totalOne); LOGGER.info("1st frameRate {}",frameRateOne); LOGGER.info("1st start frame num {}",startFrameNum); LOGGER.info("1st end frame num {}",endFrameNum); LOGGER.info("2nd duration {}",durationTwoInSec); LOGGER.info("2nd total {}",totalTwo); LOGGER.info("2nd frameRate {}",frameRateTwo); LOGGER.info("2nd end frame num {}",grabeTwoEndFrameNum); LOGGER.info("Uniform width {}, height {}",maxWidth,maxHeight); int i=0; double progress; Frame fTwo,fOne; Mat fadeInMat,fadeOutMat,resizedMat; OpenCVFrameConverter.ToMat conveter = new OpenCVFrameConverter.ToMat(); DecimalFormat df = new DecimalFormat("#.00"); while (i<=totalTwo) { i++; // record video one frame if (i <= startFrameNum) { fOne = grabberOne.grabImage(); recorder.record(fOne); } // video one fade out , video two fade in else if (i > startFrameNum && i < endFrameNum) { resizedMat=new Mat(); fOne = grabberOne.grabImage(); fTwo = grabberTwo.grabImage(); //org.bytedeco.opencv.global.opencv_imgproc.resize //resize frame resize(conveter.convertToMat(fOne), resizedMat, new Size(maxWidth, maxHeight)); fadeOutMat = resizedMat; fadeInMat = conveter.convertToMat(fTwo); //calculate the picture weight progress = (i - startFrameNum) / (double) (endFrameNum - startFrameNum); //merge two frame and record it recorder.record(mergePhotoToFrame(fadeOutMat, fadeInMat, Double.valueOf(df.format(progress)))); } else { fTwo = grabberTwo.grabImage(); if (fTwo == null) break; recorder.record(fTwo); } } recorder.close(); grabberOne.close(); grabberTwo.close(); } catch (Exception e) { LOGGER.error("", e); } } public static int getStartOrEndFrameNumber(long startOrEndAtSecond, long durationInSecond, int totalFrame) { if (startOrEndAtSecond >= durationInSecond) return (int) durationInSecond; double percent = startOrEndAtSecond / (double) durationInSecond; return (int) Math.round(totalFrame * percent); } public static Frame mergePhotoToFrame(Mat srcFadeOut,Mat srcFadeIn,double progress) { OpenCVFrameConverter.ToMat conveter = new OpenCVFrameConverter.ToMat(); return conveter.convert(mergePhoto(srcFadeOut,srcFadeIn,progress)); } public static Mat mergePhoto(Mat srcFadeOut,Mat srcFadeIn,double progress) { if(progress <0||progress>1) return null; double srcAlpha=1-progress; Mat dest=new Mat(); opencv_core.addWeighted(srcFadeOut,srcAlpha , srcFadeIn,progress, 0.0, dest); return dest; }