Commit 7ed5cf69 authored by yanzg's avatar yanzg

压缩视频

parent 33e3822a
......@@ -37,5 +37,10 @@
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.yanzuoguang</groupId>
<artifactId>yzg-util-base</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.yanzuoguang.util;
import com.yanzuoguang.util.log.Log;
import it.sauronsoftware.jave.*;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
......@@ -18,12 +20,275 @@ import java.io.OutputStream;
/**
* 视频帮助类
* <p>
* 59s视频,抖音上拍摄59s,下载后是27.79mb。先从手机上拍摄59s,原视频是111mb,上传抖音后下载的视频是47.32mb
*
* @author 颜佐光
*/
public class MediaHelper {
public static final int FIRST_FRAME = 5;
public static final int DEFAULT_BIT_RATE = 372 * 1000;
public static final float DEFAULT_SIZE = 1f;
public static final String FORMAT_EMPTY = "";
public static final String FORMAT_FLV = "flv";
public static final String FORMAT_MPEG = "mpegvideo";
public static final String FORMAT_MPEG_CODEC = "mpeg4";
public static final String FORMAT_3PG = "3gp";
public static final String FORMAT_3PG_CODEC = "mpeg4";
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @return
* @throws IOException
*/
public static void zipVideo(String fromFile, String toFile) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_EMPTY, FORMAT_EMPTY, DEFAULT_SIZE, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @return
* @throws IOException
*/
public static void zipVideo(String fromFile, String toFile, float size) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_EMPTY, FORMAT_EMPTY, size, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @return
* @throws IOException
*/
public static void zipVideo(String fromFile, String toFile, float size, int bitRate) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_EMPTY, FORMAT_EMPTY, size, bitRate);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @return
* @throws IOException
*/
public static void zipVideo3pg(String fromFile, String toFile) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_3PG, FORMAT_3PG_CODEC, DEFAULT_SIZE, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @return
* @throws IOException
*/
public static void zipVideo3pg(String fromFile, String toFile, float size) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_3PG, FORMAT_3PG_CODEC, size, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @return
* @throws IOException
*/
public static void zipVideo3pg(String fromFile, String toFile, float size, int bitRate) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_3PG, FORMAT_3PG_CODEC, size, bitRate);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @return
* @throws IOException
*/
public static void zipVideoMpeg(String fromFile, String toFile) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_MPEG, FORMAT_MPEG_CODEC, DEFAULT_SIZE, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @return
* @throws IOException
*/
public static void zipVideoMpeg(String fromFile, String toFile, float size) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_MPEG, FORMAT_MPEG_CODEC, size, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @return
* @throws IOException
*/
public static void zipVideoMpeg(String fromFile, String toFile, float size, int bitRate) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_MPEG, FORMAT_MPEG_CODEC, size, bitRate);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @return
* @throws IOException
*/
public static void zipVideoFlv(String fromFile, String toFile) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_FLV, FORMAT_FLV, DEFAULT_SIZE, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @return
* @throws IOException
*/
public static void zipVideoFlv(String fromFile, String toFile, float size) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_FLV, FORMAT_FLV, size, DEFAULT_BIT_RATE);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @return
* @throws IOException
*/
public static void zipVideoFlv(String fromFile, String toFile, float size, int bitRate) throws EncoderException {
zipVide(fromFile, toFile, FORMAT_FLV, FORMAT_FLV, size, bitRate);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param format 要支持的格式
* @param codeC 视频的格式
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @return
* @throws IOException
*/
public static void zipVide(String fromFile, String toFile,
String format, String codeC,
float size, int bitRate) throws EncoderException {
if (size > 1) {
throw new RuntimeException("size请在0~1之间");
}
File source = new File(fromFile);
File target = new File(toFile);
if (!target.getParentFile().exists()) {
target.getParentFile().mkdirs();
}
// 编码方式
Encoder encoder = new Encoder();
MultimediaInfo fromInfo = encoder.getInfo(source);
VideoInfo fromVideo = fromInfo.getVideo();
AudioInfo fromAudio = fromInfo.getAudio();
if (FORMAT_EMPTY.equals(format) || format == null) {
format = fromInfo.getFormat();
}
if (FORMAT_EMPTY.equals(codeC) || codeC == null) {
codeC = fromVideo.getDecoder();
}
// 音频编码设置
int toBitRate = fromAudio.getBitRate();
if (toBitRate == -1) {
toBitRate = 64000;
}
int toChannels = fromAudio.getChannels();
int toSamplingRate = Math.min(22050, fromAudio.getSamplingRate());
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
audio.setBitRate(toBitRate);
audio.setChannels(toChannels);
audio.setSamplingRate(toSamplingRate);
// 视频编码设置
VideoAttributes video = new VideoAttributes();
video.setCodec(codeC);
int fromFrameRate = (int) (fromVideo.getFrameRate());
int toFrameRate = 15;
video.setFrameRate(toFrameRate);
// 压缩比特率
video.setBitRate(bitRate);
// 压缩宽高
VideoSize fromSize = fromVideo.getSize();
VideoSize toSize = new VideoSize((int) (fromSize.getWidth() * size), (int) (fromSize.getHeight() * size));
video.setSize(toSize);
Log.info(MediaHelper.class, "%s-%s " +
"原音频:bitRate=%d,channels=%d,samplingRate=%d " +
"新音频:bitRate=%d,channels=%d,samplingRate=%d \n" +
"原视频:width=%d,height=%d,bitRate=%d,frameRate=%d " +
"新视频:width=%d,height=%d,bitRate=%d,frameRate=%d ",
format, codeC,
fromAudio.getBitRate(), fromAudio.getChannels(), fromAudio.getSamplingRate(),
toBitRate, toChannels, toSamplingRate,
fromSize.getWidth(), fromSize.getHeight(), fromVideo.getBitRate(), toFrameRate,
toSize.getWidth(), toSize.getHeight(), bitRate, toFrameRate
);
// 视频转码编码设置
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat(format);
attrs.setAudioAttributes(audio);
attrs.setVideoAttributes(video);
// 编码器
encoder.encode(source, target, attrs);
System.out.println("压缩完成...");
}
/**
* 从视频文件中获取第一张图片
......@@ -33,7 +298,7 @@ public class MediaHelper {
* @return
* @throws IOException
*/
public static String getFirstImage(String fromFile, String toFile) throws IOException {
public static void getVideoFirstImage(String fromFile, String toFile) throws IOException {
File file2 = new File(fromFile);
if (file2.exists()) {
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file2);
......@@ -56,16 +321,15 @@ public class MediaHelper {
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
ImageIO.write(FrameToBufferedImage(frame), "jpg", targetFile);
ImageIO.write(frameToBufferedImage(frame), "jpg", targetFile);
} finally {
ff.close();
ff.stop();
}
}
return null;
}
private static RenderedImage FrameToBufferedImage(Frame frame) {
private static RenderedImage frameToBufferedImage(Frame frame) {
//创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
......
package helper;
import com.yanzuoguang.util.MediaHelper;
import com.yanzuoguang.util.thread.RunnableListAuto;
import com.yanzuoguang.util.thread.ThreadHelper;
import it.sauronsoftware.jave.EncoderException;
import jdk.management.resource.internal.inst.ThreadRMHooks;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TestMediaHelper {
private boolean isFirstImage = false;
public float[] sizes = new float[]{1f, 0.5f, 1f, 1f, 0.5f, 0.5f};
public float[] quotes = new float[]{1f, 1f, 0.5f, 0.25f, 0.5f, 0.25f};
private String getFile() {
// 注意,路径应为文件在工程中的相对路径
......@@ -26,7 +34,7 @@ public class TestMediaHelper {
return;
}
String file = getFile();
MediaHelper.getFirstImage(file, file + ".jpg");
MediaHelper.getVideoFirstImage(file, file + ".jpg");
isFirstImage = true;
}
......@@ -37,4 +45,65 @@ public class TestMediaHelper {
String file = getFile();
MediaHelper.compressPic(file + ".jpg", file + ".zip.jpg", 0.25f);
}
@Test
public void testVideoZipFlv() {
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < sizes.length; i++) {
list.add(testVideoZipFlvThread(sizes[i], quotes[i]));
}
RunnableListAuto.run(list);
}
private Runnable testVideoZipFlvThread(float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testVideoZipFlv(size, quote);
} catch (EncoderException e) {
throw new RuntimeException(e);
}
}
};
}
private void testVideoZipFlv(float size, float quote) throws EncoderException {
String file = getFile();
String name = String.format("%s.size_%d.quot_%d.flv",
file, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideoFlv(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
@Test
public void testVideoZipMpeg() throws EncoderException {
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < sizes.length; i++) {
list.add(testVideoZipMpegThread(sizes[i], quotes[i]));
}
RunnableListAuto.run(list);
}
private Runnable testVideoZipMpegThread(float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testVideoZipMpeg(size, quote);
} catch (EncoderException e) {
throw new RuntimeException(e);
}
}
};
}
private void testVideoZipMpeg(float size, float quote) throws EncoderException {
String file = getFile();
String name = String.format("%s.size_%d.quot_%d.mpeg.mp4",
file, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideoMpeg(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment