master
王兵 3 months ago
commit 2436ba4c96

8
.gitignore vendored

@ -0,0 +1,8 @@
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
*.iml
.idea/

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>starter-jpg2mp4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<!--<packaging>war</packaging>--><!--需要打包成war时放开-->
<name>starter-img2mp4</name>
<description>project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>8</java.version>
<maven.test.skip>true</maven.test.skip>
</properties>
<repositories>
<!-- 将中央仓库地址指向阿里云聚合仓库,提高下载速度 -->
<repository>
<id>aliyun</id>
<name>Aliyun Repository</name>
<layout>default</layout>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
<pluginRepositories>
<!-- 将插件的仓库指向阿里云聚合仓库解决低版本maven下载插件异常或提高下载速度 -->
<pluginRepository>
<id>aliyun</id>
<name>Aliyun Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
<layout>default</layout>
</pluginRepository>
</pluginRepositories>
<dependencies>
<!--图片转MP4-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.4-1.5.6</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
</dependencies>
<build>
<!-- 项目名称 -->
<finalName>${artifactId}-${version}</finalName>
<!-- 默认的主代码目录 -->
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${project.basedir}/src/main/resources/lib</directory>
<targetPath>WEB-INF/lib</targetPath>
<includes>
<include>*.jar</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,182 @@
package com.example.jpg2mp4;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Date;
import java.util.List;
public class Image2Mp4 {
public static void main(String[] args) throws Exception {
String absolutePath = FileUtil.getAbsolutePath("");
// 图片集合目录
String imgs = FileUtil.getAbsolutePath("data\\album\\");
String auds = FileUtil.getAbsolutePath("data\\music\\");
// 图片集合目录
String target = FileUtil.getAbsolutePath("data\\target\\");
//合成的MP4
String mp4 = DateUtil.date().toString("yyyyMMddHHmmss");
String tempMp4 = target + mp4 + "temp.mp4";
String outMp4 = target + mp4 + ".mp4";
// 视频宽度
int width = 1920;
// 视频高度
int height = 1080;
createTempMp4(imgs, tempMp4, width, height);
if (FileUtil.loopFiles(auds).size() > 0) {
mergeMp4(tempMp4, auds, outMp4);
} else {
FileUtil.move(new File(tempMp4), new File(mp4), true);
}
}
/**
*
*
* @param tempMp4
* @param imgs
* @param width
* @param height
* @throws FrameRecorder.Exception
*/
private static void createTempMp4(String imgs, String tempMp4, int width, int height) throws FrameRecorder.Exception {
//视频宽高最好是按照常见的视频的宽高 169 或者 916
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(tempMp4, width, height);
//设置视频编码层模式
recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
// 设置视频图像数据格式 yuv420p 先默认吧,这个应该属于设置视频的处理模式吧
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFormat("mp4");
//视频帧,一般不能小于24否则有卡顿
int frameRate = 25;
recorder.setFrameRate(frameRate);
//这一步没有感觉到有多少影响,暂时不管
recorder.setGopSize(50);
//8000kb/s 这个说明视频每秒大小,值越大图片转过来的压缩率就越小质量就会越高
recorder.setVideoBitrate(8000000);
// 不可变(固定)音频比特率
recorder.setAudioOption("crf", "0");
// 最高质量
recorder.setAudioQuality(0);
// 音频比特率
recorder.setAudioBitrate(192000);
// 音频采样率11025Hz、22050Hz、24000Hz、44100Hz、48000Hz
recorder.setSampleRate(44100);
// 双通道(立体声)
recorder.setAudioChannels(2);
try {
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
List<File> files = FileUtil.loopFiles(imgs);
for (int i = 0; i < files.size(); i++) {
BufferedImage read = ImageIO.read(files.get(i));
//一秒是25帧 所以要记录25次
for (int j = 0; j < frameRate; j++) {
System.out.println("正在写入,第" + (i + 1) + "张,第" + (j + 1) + "帧");
//编码格式 ##后面参数用于解决生成视频颜色不对问题
recorder.record(converter.getFrame(read));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//最后一定要结束并释放资源
recorder.stop();
recorder.release();
}
}
/**
*
*
* @param videoPath
* @param audioPath
* @param outPut
* @return
* @throws Exception
*/
public static boolean mergeMp4(String videoPath, String audioPath, String outPut) throws Exception {
boolean isCreated = true;
File file = new File(videoPath);
if (!file.exists()) {
return false;
}
FrameRecorder recorder = null;
FrameGrabber grabber1 = null;
FrameGrabber grabber2 = null;
try {
//抓取视频帧
grabber1 = new FFmpegFrameGrabber(videoPath);
//抓取音频帧
grabber2 = new FFmpegFrameGrabber(FileUtil.loopFiles(audioPath).get(0));
grabber1.start();
grabber2.start();
//创建录制
recorder = new FFmpegFrameRecorder(outPut, grabber1.getImageWidth(), grabber1.getImageHeight(), grabber2.getAudioChannels());
recorder.setFormat("mp4");
recorder.setFrameRate(grabber1.getFrameRate());
recorder.setSampleRate(grabber2.getSampleRate());
// 视频质量0表示无损
recorder.setVideoQuality(0);
recorder.start();
Frame frame1;
//录入视频
while ((frame1 = grabber1.grabFrame()) != null) {
recorder.record(frame1);
}
//录入音频
audioEntry(grabber1, grabber2, recorder);
grabber1.stop();
grabber2.stop();
recorder.stop();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (recorder != null) {
recorder.release();
}
if (grabber1 != null) {
grabber1.release();
}
if (grabber2 != null) {
grabber2.release();
}
} catch (FrameRecorder.Exception e) {
e.printStackTrace();
}
}
return isCreated;
}
private static void audioEntry(FrameGrabber grabber1, FrameGrabber grabber2, FrameRecorder recorder) throws Exception {
Frame frame = null;
long grabber1Timestamp = grabber1.getTimestamp();
while ((frame = grabber2.grabFrame()) != null) {
//如果视频时长小于音频时长 则截断音频帧
if (grabber1Timestamp <= grabber2.getTimestamp()) break;
recorder.record(frame);
}
long differ = grabber1Timestamp - grabber2.getTimestamp();
//如果视频时长大于音频时长 则循环录入
if (differ > 0) {
grabber1.setTimestamp(differ);
audioEntry(grabber1, grabber2, recorder);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Loading…
Cancel
Save

Powered by TurnKey Linux.