项目需要准备用的opencv进行多张图加入mp3的音频合成视频,经查找需要javacv的支持。项目需要网上看了好多有关javacv的资料,没有找到合适的,最后慢慢研究了下javacv并记录下,方便以后使用,于是找到最新的opencv-3.4.1,然后下载了对应的java支持javacv1.3.3
1:准备资料下载opencv、javacv
opencv-3.4.1 百度网盘:链接:https://pan.baidu.com/s/1bETa6KxKHD4MDHsyXgpHng 提取码:un9u
javacv-platfrom 1.3.3 版本 链接:https://pan.baidu.com/s/1dlulDw5BCtjphJIggm6BMw 提取码:c1ac
2:配置环境
方式 (1)
解压下载的 opencv,解压javacv (eclipse、tomcat、jdk 配置不需要再说)
配置opencv的路径,在Path增加指向opencv
(本人是64位系统,我的指向路径是d:\opencv\build\x64\vc15\bin;d:\opencv\build\java\x64;)
说明一下 ...vc15\bin 是告诉java程序使用opencv的哪个版本进行视频的处理
...\build\java\x64 是告诉java程序 系统的支持需要的dll文件
其他环境说明:Tomcat用的是8 ,jdk用的是1.8
方式(2)
在需要运行的类上配置下面一段代码,替代方式(1)中的环境变量值
-Djava.library.path="d:\opencv\build\x64\vc15\bin;d:\opencv\build\java\x64;"
3:创建普通的java项目
(1):创建普通的java-project 项目,添加 ffmpeg.jar、javacpp.jar、javacv.jar、opencv.jar、opencv-341.jar、javacv-platform.jar、ffmpge-windows-x86_64.jar、opencv-windows-x86_64.jar导到新项目中
(2):编写代码
import java.io.File;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.avutil;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacpp.opencv_imgcodecs;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameRecorder.Exception;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.opencv.core.Core;
public class PictureAndAudioToVideo {
public static void main(String[] args) throws Exception,
org.bytedeco.javacv.FrameGrabber.Exception {
// 图片转换器
// 在main函数中时要让系统去加载这个opencv的相关变量
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// ------------------->begin 初始化视频录制器
// 参数说明mp4Path.mov,视频的宽和高
//mp4Path 视频存储位置
//imageWidth 视频宽
//imageHeight 视频高
String mp4Path = "D:\\MyDrivers\\f.mp4";
int imageWidth = 600;
int imageHeight = 800;
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4Path, imageWidth, imageHeight);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
// 设置格式mp4
recorder.setFormat("mp4");
// 此处说明每一秒多少帧,即说明1秒会录多少张照片
recorder.setFrameRate(0.5);
// 8000kb/s 这个说明视频每秒大小,值越大图片转过来的压缩率就越小质量就会越高
recorder.setVideoBitrate(8000000);
// yuv420p
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
// 先默认吧,这个应该属于设置视频的处理模式 不可变(固定)音频比特率
recorder.setAudioOption("crf", "0");
// 最高质量
recorder.setAudioQuality(0);
// 音频比特率
recorder.setAudioBitrate(1000000);
// 音频采样率
// recorder.setSampleRate(44100);
// 双通道(立体声)
recorder.setAudioChannels(2);
// ------------------->end 初始化视频录制器
recorder.start();// 开始录制
// ------------------->begin 图片处理开始
OpenCVFrameConverter.ToIplImage conveter = new OpenCVFrameConverter.ToIplImage(); // 申明一个图片处理的变量
// 图片目录的位置
String imagesPath = "D:\\MyDrivers\\img\\";
// 列出目录中所有的图片,都是jpg的,以1.jpg,2.jpg的方式,方便操作
File file = new File(imagesPath);
File[] flist = file.listFiles();
for (int i = 1; i <= flist.length; i++) {
IplImage image = opencv_imgcodecs.cvLoadImage(imagesPath + i + ".jpg"); // 非常吃内存!!
Frame frame = conveter.convert(image);
recorder.record(frame); // 录制
// 释放内存 非常吃内存!!
opencv_core.cvReleaseImage(image);
}
// ------------------->end 图片处理开始
// ------------------->begin 开始录制音频
String mp3Path = "D:\\MyDrivers\\1.mp3";
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(mp3Path);
grabber.start();// 开始录制音频
Frame audioSamples;
while ((audioSamples = grabber.grab()) != null) {
recorder.setTimestamp(grabber.getTimestamp()); // 告诉录制器这个audioSamples的音频时长
recorder.record(audioSamples); // 录入音频
}
// ------------------->end 开始录制音频
grabber.stop();
grabber.release();
recorder.stop();
recorder.release();
}
}
顺便写个视频随机截取几张图片demo:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_imgcodecs;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter;
public abstract class FrameGrabberKit {
public static void main(String[] args) throws Exception {
String inputFilePth = "D:\\MyDrivers\\2.mp4";
randomGrabberFFmpegImage(inputFilePth, 5);
}
public static void randomGrabberFFmpegImage(String filePath, int randomSize)
throws Exception {
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
ff.start();
int ffLength = ff.getLengthInFrames();
List<Integer> randomGrab = random(ffLength, randomSize);
int maxRandomGrab = randomGrab.get(randomGrab.size() - 1);
Frame f;
int i = 0;
while (i < ffLength) {
f = ff.grabImage();
if (randomGrab.contains(i)) {
doExecuteFrame(f, i);
}
if (i >= maxRandomGrab) {
break;
}
i++;
}
ff.stop();
}
public static void doExecuteFrame(Frame f, int index) {
if (null == f || null == f.image) {
return;
}
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
opencv_core.Mat mat = converter.convertToMat(f);
opencv_imgcodecs.imwrite("d:\\MyDrivers\\picture\\" + index + ".png",
mat);// 存储图像
}
public static List<Integer> random(int baseNum, int length) {
List<Integer> list = new ArrayList<>(length);
while (list.size() < length) {
Integer next = (int) (Math.random() * baseNum);
if (list.contains(next)) {
continue;
}
list.add(next);
}
Collections.sort(list);
return list;
}
}
到此图片和音频的动作就合成成功了,会在D:\MyDrivers\f.mp4目录下生成一个f.mp4的视频文件
需要源码的同学可以下载:链接:https://pan.baidu.com/s/1j3y01dCKJVI1FO9uyu3-Ow 提取码:dora