Commit 7533cb00 authored by yanzg's avatar yanzg

视频转换

parent 4951ed52
package com.yanzuoguang.util;
import com.yanzuoguang.util.log.Log;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacv.*;
......@@ -20,8 +21,6 @@ import java.util.List;
* @author 颜佐光
*/
public class MediaHelper extends ImageHelper {
private static final String IMAGEMAT = "png";
private static final String ROTATE = "rotate";
/**
* 默认截取视频的中间帧为封面
*/
......@@ -31,99 +30,98 @@ public class MediaHelper extends ImageHelper {
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 第一帧图片
* @param format 要支持的格式
* @param codeC 视频的格式
* @param size 宽度和高度是否压缩
* @param bitRate 它为新的重新编码的视频流设置比特率值。如果未设置比特率值,编码器将选择默认值。
* 该值应以位/秒表示。在这个例子中,如果你想要一个360kb/s的比特率,你应该调用setBitRate(新整数(360000))。
* @param toFile 转码后保存的文件
* @param parameter 转码后的参数,在转码完成后该参数值会被改变
*/
public static void zipVideoMp4(String fromFile, String toFile, MediaParameter parameter) throws IOException {
// 视频压缩参数初始化
if (parameter == null) {
parameter = new MediaParameter();
}
parameter.initZipMp4();
convertVideo(fromFile, toFile, parameter);
}
/**
* 转换成mp4
*
* @param fromFile
* @param toFile
* @param parameter
*/
public static void convertVideoMp4(String fromFile, String toFile, MediaParameter parameter) throws IOException {
// 视频压缩参数初始化
if (parameter == null) {
parameter = new MediaParameter();
}
parameter.initMp4();
convertVideo(fromFile, toFile, parameter);
}
/**
* 从视频文件中获取第一张图片
*
* @param fromFile 视频文件
* @param toFile 转码后保存的文件
* @param parameter 转码后的参数,在转码完成后该参数值会被改变
*/
public static void zipVideo(String fromFile, String toFile,
String format, String codeC,
int width, int height, float sizeZip,
int videoBitRate, float videoBitRateZip,
int videoBitRate, float videoBitRateZip) {
if (size > 1) {
throw new RuntimeException("size请在0~1之间");
public static void convertVideo(String fromFile, String toFile, MediaParameter parameter) throws IOException {
// 视频压缩参数初始化
if (parameter == null) {
parameter = new MediaParameter();
}
parameter.check();
// 源文件判断
File source = new File(fromFile);
if (!source.exists()) {
throw new RuntimeException("视频转码压缩时不存在");
}
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 (fromAudio == null) {
fromAudio = new AudioInfo();
}
if (fromVideo == null) {
fromVideo = new VideoInfo();
}
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(VideoAttributes.DIRECT_STREAM_COPY);
video.setCodec(codeC);
// video.setTag("DIVX");
int toFrameRate = 15;
video.setFrameRate(toFrameRate);
// 压缩比特率
video.setBitRate(bitRate);
// 压缩宽高
VideoSize fromSize = fromVideo.getSize();
int toWidth = (int) (fromSize.getWidth() * size);
int toHeight = (int) (fromSize.getHeight() * size);
VideoSize toSize = new VideoSize(toWidth, toHeight);
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);
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(fromFile);
try {
grabber.start();
// 设置视频参数
parameter.init(grabber);
Log.info(MediaHelper.class, "开始转换...源文件:%s 目标文件:%s 旋转参数:%s",
fromFile, toFile, parameter.toString());
// 定义转码工具
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
toFile,
parameter.getVideoWidthFinally(),
parameter.getVideoHeightFinally(),
grabber.getAudioChannels()
);
parameter.init(grabber, recorder);
try {
// 开始转换
recorder.start(grabber.getFormatContext());
avcodec.AVPacket packet;
long dts = 0;
while ((packet = grabber.grabPacket()) != null) {
long currentDts = packet.dts();
if (currentDts >= dts) {
recorder.recordPacket(packet);
}
dts = currentDts;
}
} finally {
recorder.stop();
recorder.release();
}
// 编码器
encoder.encode(source, target, attrs);
Log.info(MediaHelper.class, "转换完成...源文件:%s 目标文件:%s 旋转参数:%s ",
fromFile, toFile, parameter.toString());
} finally {
grabber.stop();
grabber.close();
}
System.out.println("压缩完成...");
}
/**
......@@ -161,7 +159,7 @@ public class MediaHelper extends ImageHelper {
// 打开视频
ff.start();
// 获取视频的角度
String rotate = ff.getVideoMetadata(ROTATE);
String rotate = ff.getVideoMetadata(MediaParameter.ROTATE);
// 整个视频的长度
int ffLength = ff.getLengthInFrames();
// 取得能够取得的帧数
......
package helper;
import com.yanzuoguang.util.ImageHelper;
import com.yanzuoguang.util.MediaHelper;
import com.yanzuoguang.util.MediaParameter;
import com.yanzuoguang.util.thread.RunnableListAuto;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import org.junit.Test;
import java.io.File;
......@@ -19,57 +17,6 @@ public class TestMediaHelper {
public float[] quotes = new float[]{1f, 1f, 0.5f, 0.25f, 0.5f, 0.25f};
@Test
public void testMediaType() throws EncoderException, IOException {
System.out.println("100M.mp4 " + ImageHelper.getMediaType(getFile("100M.mp4")));
System.out.println("100M.mp4.jpg " + ImageHelper.getMediaType(getFile("100M.mp4.jpg")));
System.out.println("xuziming.mp4 " + ImageHelper.getMediaType(getFile("xuziming.mp4")));
System.out.println("z001594372388232a3017ad69c82a342.MOV " + ImageHelper.getMediaType(getFile("z001594372388232a3017ad69c82a342.MOV")));
}
@Test
public void printEncoding() throws EncoderException {
Encoder encoder = new Encoder();
String[] audioEncoders = encoder.getVideoEncoders();
for (String item : audioEncoders) {
System.out.println(item);
}
}
@Test
public void testConvert() throws EncoderException {
Encoder encoder = new Encoder();
String[] audioEncoders = encoder.getVideoEncoders();
List<Runnable> list = new ArrayList<>();
for (String item : audioEncoders) {
list.add(testConvertThread(item, 1f, 1f));
}
RunnableListAuto.run(list);
}
private Runnable testConvertThread(String item, float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testConvert(item, size, quote);
} catch (EncoderException e) {
throw new RuntimeException(e);
}
}
};
}
private void testConvert(String item, float size, float quote) throws EncoderException {
String file = getFile("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
String name = String.format("%s.size_%d.quot_%d.%s.mp4",
targetFile, (int) (size * 100), (int) (quote * 100), item);
MediaHelper.zipVideo(file, name, "mp4", item, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
private String getFile(String file) {
// 注意,路径应为文件在工程中的相对路径
File f = new File("src/test/java/helper/" + file);
......@@ -88,198 +35,36 @@ public class TestMediaHelper {
}
@Test
public void testVideoFirstImage() throws IOException {
if (isFirstImage) {
return;
}
String file = getFile("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
MediaHelper.getVideoFirstImage(file, targetFile + ".jpg");
isFirstImage = true;
}
@Test
public void testVideoFirstImage1() throws IOException {
if (isFirstImage) {
return;
}
String file = getFile("xuziming.mp4");
String targetFile = getTargetFile("target/xuziming.mp4");
MediaHelper.getVideoFirstImage(file, targetFile + ".jpg");
isFirstImage = true;
}
@Test
public void testImageZip() throws IOException {
// 生成测试图片
testVideoFirstImage();
public void testConvert() {
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < sizes.length; i++) {
list.add(testImageZipThread(sizes[i], quotes[i]));
list.add(testConvertThread(sizes[i], quotes[i]));
}
RunnableListAuto.run(list);
}
private Runnable testImageZipThread(float size, float quote) {
private Runnable testConvertThread(float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testImageZip(size, quote);
testConvert(size, quote);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
}
private void testImageZip(float size, float quote) throws IOException {
String file = getTargetFile("target/100M.mp4") + ".jpg";
String targetFile = getTargetFile("target/100M.mp4");
String toName = String.format("%s.size_%d.quot_%d.jpg",
targetFile, (int) (size * 100), (int) (quote * 100));
String toNameSystem = String.format("%s.size_%d.quot_%d.system.jpg",
targetFile, (int) (size * 100), (int) (quote * 100));
MediaHelper.compressPic(file, toName, quote, size);
MediaHelper.compressPicBySystem(file, toNameSystem, quote, size);
}
@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("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
String name = String.format("%s.size_%d.quot_%d.flv",
targetFile, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideoFlv(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
@Test
public void testVideoZipMpeg_50_50() throws EncoderException {
testVideoZipMpeg(0.5f, 0.5f);
}
@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);
e.printStackTrace();
}
}
};
}
private void testVideoZipMpeg(float size, float quote) throws EncoderException {
private void testConvert(float size, float quote) throws IOException {
String file = getFile("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
String name = String.format("%s.size_%d.quot_%d.mpeg.mp4",
targetFile, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideoMpeg(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
String toFile = String.format("%s.size_%d.quot_%d.mp4", targetFile, (int) (size * 100), (int) (quote * 100));
@Test
public void testVideoZip3pg() throws EncoderException {
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < sizes.length; i++) {
list.add(testVideoZip3pgThread(sizes[i], quotes[i]));
}
RunnableListAuto.run(list);
}
MediaParameter parameter = new MediaParameter();
parameter.setVideoSizeZip(size);
parameter.setVideoBitRateZip(quote);
private Runnable testVideoZip3pgThread(float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testVideoZip3pg(size, quote);
} catch (EncoderException e) {
throw new RuntimeException(e);
}
}
};
}
private void testVideoZip3pg(float size, float quote) throws EncoderException {
String file = getFile("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
String name = String.format("%s.size_%d.quot_%d.3pg",
targetFile, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideo3pg(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
}
@Test
public void testVideoZip_50_50() throws EncoderException {
testVideoZip(0.5f, 0.5f);
}
@Test
public void testVideoZip() throws EncoderException {
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < sizes.length; i++) {
list.add(testVideoZipThread(sizes[i], quotes[i]));
}
RunnableListAuto.run(list);
}
private Runnable testVideoZipThread(float size, float quote) {
return new Runnable() {
@Override
public void run() {
try {
testVideoZip(size, quote);
} catch (EncoderException e) {
throw new RuntimeException(e);
}
}
};
}
private void testVideoZip(float size, float quote) throws EncoderException {
String file = getFile("100M.mp4");
String targetFile = getTargetFile("target/100M.mp4");
String name = String.format("%s.size_%d.quot_%d.mp4",
targetFile, (int) (size * 100), (int) (quote * 100));
MediaHelper.zipVideo(file, name, size, (int) (MediaHelper.DEFAULT_BIT_RATE * quote));
MediaHelper.convertVideoMp4(file, toFile, parameter);
}
}
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