【视频压缩】全网最好用的JAVA视频压缩(附代码)
最近要用到视频压缩功能。通过搜索发现了ffmpeg,javacv。
这两个是比较主流的流媒体组件。
但是研究下来发现。如果仅仅是需要视频压缩的话,那么就有点大材小用了。
FFmpeg是C语言开发的,对于我们java来说使用起来有点难,而javacv是java语言写的,源码读起来还容易上手,但是由于这两个组件功能较多,就被作者放弃了。
最后找到了另外一个小众的工具JAVE,这也是本文推荐的技术。
前言
在了解视频压缩之前,首先要先了解几个流媒体领域的专业词汇,因为下面这些参数你都会要用到。
1.视频转码
视频转码(Video Transcoding)是指将已经压缩编码的视频码流转换成另一个视频码流,以适应不同的网络带宽、不同的终端处理能力和不同的用户需求。转码本质上是一个先解码,再编码的过程,因此转换前后的码流可能遵循相同的视频编码标准,也可能不遵循相同的视频编码标准。
——摘自:百度百科
2.比特率
比特率是指每秒传送的比特(bit)数。单位为 bps(Bit Per Second),比特率越高,每秒传送数据就越多,画质就越清晰。声音中的比特率是指将模拟声音信号转换成数字声音信号后,单位时间内的二进制数据量,是间接衡量音频质量的一个指标。视频中的比特率(码率)原理与声音中的相同,都是指由模拟信号转换为数字信号后,单位时间内的二进制数据量。
——摘自:百度百科
3.采样频率
采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样频率的倒数是采样周期或者叫作采样时间,它是采样之间的时间间隔。通俗的讲采样频率是指计算机每秒钟采集多少个信号样本。
——摘自:百度百科
4.视频帧率
视频帧率(Frame rate)是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second,简:FPS)或“赫兹”(Hz)。此词多用于影视制作和电子游戏。
——摘自:百度百科
正文
在了解了上面几个流媒体领域的专业名词后,接下来就进入正题:视频压缩
视频压缩
JAVE简介
简单的说,JAVE是对ffmege进行了简单的封装,只提供了视频和音频的转码功能。(视频转码(Video Transcoding)是指将已经压缩编码的视频码流转换成另一个视频码流,以适应不同的网络带宽、不同的终端处理能力和不同的用户需求。转码本质上是一个先解码,再编码的过程)所以如果你需要视频压缩的话,那么这个组件是最好的选择。
官网:http://www.sauronsoftware.it/projects/jave/manual.php
package tomatocc.zip;
/**
* @author tomatocc
* @email [email protected]
* @desc
*
* 比特率是指将模拟声音信号转换成数字声音信号后,单位时间内的二进制数据量,比特率越大的音质就越好(在相同的编码格式下,不同格式,无法比较)。
* 作为一种数字音乐压缩效率的参考性指标,比特率表示单位时间(1秒)内传送的比特数bps(bit per second,位/秒)的速度。
* 通常使用kbps(通俗地讲就是每秒钟1000比特)作为单位。
* CD中的数字音乐比特率为1411.2kbps(也就是记录1秒钟的cd音乐,需要1411.2×1000比特的数据),音乐文件的BIT RATE高是意味着在单位时间(1秒)内需要处理的数据量(BIT)多,也就是音乐文件的音质好的意思。
* 但是,BIT RATE高时文件大小变大,会占据很多的内存容量,音乐文件最常用的bit rate是128kbps,MP3文件可以使用的一般是8-320kbps,但不同MP3机在这方面支持的范围不一样,大部分的是32-256Kbps,这个指数当然是越广越好了,不过320Kbps是暂时最高等级了。
*/
import java.io.File;
import it.sauronsoftware.jave.*;
public class VideoZip {
public static void main(String[] args) {
// 压缩前文件路径
File source = new File("D:/video/000.mp4");
// 压缩后的文件路径
File target = new File("D:/video/test000.mp4");
try {
long start = System.currentTimeMillis();
System.out.println("begin");
// 音频编码属性配置
AudioAttributes audio= new AudioAttributes();
audio.setCodec("libmp3lame");
// 比特率越高,清晰度/音质越好
audio.setBitRate(new Integer(56000));//设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 56000 = 56kb)
audio.setChannels(new Integer(1));// 设置重新编码的音频流中使用的声道数(1 =单声道,2 = 双声道(立体声))。如果未设置任何声道值,则编码器将选择默认值 0。
// 采样率越高声音的还原度越好,文件越大
audio.setSamplingRate(new Integer(44100));//设置音频采样率,单位:赫兹 hz
// 设置编码时候的音量值,未设置为0,如果256,则音量值不会改变
// audio.setVolume();
// 视频编码属性配置
VideoAttributes video=new VideoAttributes();
video.setCodec("mpeg4");
// 比特率越高,清晰度/音质越好
video.setBitRate(new Integer(56000));//设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 5600000 = 5600kb)
// 视频帧率:15 f / s 帧率越低,效果越差
video.setFrameRate(new Integer(15));// 设置视频帧率(帧率越低,视频会出现断层,越高让人感觉越连续),视频帧率(Frame rate)是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second,简:FPS)或“赫兹”(Hz)。
// 编码设置
EncodingAttributes attr=new EncodingAttributes();
attr.setFormat("mp4");
attr.setAudioAttributes(audio);
attr.setVideoAttributes(video);
// 设置值编码
Encoder encoder = new Encoder();
encoder.encode(source, target, attr);
System.out.println("end");
long end = System.currentTimeMillis();
System.out.println("压缩前大小:"+source.length() + " 压缩后大小:" + target.length());
System.out.println("压缩耗时:" + (end -start));
} catch (Exception e) {
e.printStackTrace();
}
}
}
* 经验总结:
* 1.如果压缩前的视频时长很短,但是文件很大,比如4秒钟,10m,那么压缩的时候视频的比特率必须要设置很大,才能保证压缩后的视频失真度较少,否则压缩后的视频会很模糊。
* 2.如果你用压缩4秒钟,10m文件大小的压缩参数,区压缩1分钟10兆的视频,那么你会发现压缩后的视频竟然变大了!!!!
* 这个原因是由于两个文件大小相差不大,但是时长却相差很大,如果你查看这两个视频的比特率信息就会发现。4秒钟的那个文件比特率可能是1分钟那个文件的10倍以上!!
* 这样,我们可以得到结论,那就是在压缩的时候,比特率应该是一个变量,而这个变量应该跟时长,原文件比特率相关,这
* 里我建议先获得源文件的视频比特率,然后在进行减少其数值,以达到压缩目的。
package tomatocc.zip;
import it.sauronsoftware.jave.*;
import java.io.File;
/**
* @author tomatocc
* @email [email protected]
* @desc
*/
public class TestThree {
public static void main(String[] args) throws EncoderException {
File source = new File("D:/video/8.mp4");
File target = new File("D:/video/test00088.mp4");
Encoder encoder = new Encoder();
// 获取源视频参数
MultimediaInfo info = encoder.getInfo(source);
AudioInfo sourceAudio = info.getAudio();
System.out.println(sourceAudio.getBitRate() + " -- " +sourceAudio.getChannels() + " -- " + sourceAudio.getSamplingRate() + " -- " +sourceAudio.getDecoder() );
VideoInfo sourceVideo = info.getVideo();
System.out.println(sourceVideo.getBitRate() + " -- " + sourceVideo.getFrameRate() + " -- " + sourceVideo.getDecoder() + " -- " + sourceVideo.getSize().getHeight());
long duration = info.getDuration();// 视频时长(毫秒)
System.out.println(duration);
String format = info.getFormat();
System.out.println(format);
// 音频编码属性配置
AudioAttributes audio= new AudioAttributes();
audio.setCodec("libmp3lame");
// 比特率越高,清晰度/音质越好
audio.setBitRate(sourceAudio.getBitRate());//设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 56000 = 56kb)
audio.setChannels(sourceAudio.getChannels());// 设置重新编码的音频流中使用的声道数(1 =单声道,2 = 双声道(立体声))。如果未设置任何声道值,则编码器将选择默认值 0。
// 采样率越高声音的还原度越好,文件越大
audio.setSamplingRate(sourceAudio.getSamplingRate());//设置音频采样率,单位:赫兹 hz
// 设置编码时候的音量值,未设置为0,如果256,则音量值不会改变
// 视频编码属性配置
VideoAttributes video=new VideoAttributes();
video.setCodec("mpeg4");
// 比特率越高,清晰度/音质越好
video.setBitRate(sourceVideo.getBitRate() * 100);;//设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 56000 = 56kb)
// 视频帧率:15 f / s 帧率越低,效果越差
int i = Math.round(sourceVideo.getFrameRate());
video.setFrameRate(new Integer(15));// 设置视频帧率(帧率越低,视频会出现断层,越高让人感觉越连续),视频帧率(Frame rate)是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second,简:FPS)或“赫兹”(Hz)。
video.setSize(sourceVideo.getSize());
// 编码设置
EncodingAttributes attr=new EncodingAttributes();
attr.setFormat("mpegvideo");
attr.setAudioAttributes(audio);
attr.setVideoAttributes(video);
// 设置值编码
Encoder ec = new Encoder();
ec.encode(source, target, attr);
}
}
视频压缩升级版:JAVE2
上面的版本,尽管可以压缩。但是如果压缩安卓手机拍摄后的视频的话。会出现视频方向旋转90度的问题。
具体原因是由于安卓手机视频编码为yuv420p的问题。
针对这个问题,本人又找到了一个升级版的jave->jave2
jave2官网
https://github.com/a-schild/jave2
package tomatocc.java2;
import ws.schild.jave.*;
import java.io.File;
/**
* @author tomatocc
* @email [email protected]
* @desc
*/
public class Jave2 {
public static void main(String[] args) {
// 压缩前文件路径
File source = new File("D:/video/000.mp4");
// 压缩后的文件路径
File target = new File("D:/video/comp000.mp4");
compre(source,target,1);
}
/**
* 视频压缩
* @param source 源文件
* @param target 目标文件
* @param rate 压缩比
*/
public static void compre(File source , File target , Integer rate) {
try {
System.out.println("begin");
long start = System.currentTimeMillis();
// 音频编码属性配置
AudioAttributes audio= new AudioAttributes();
audio.setCodec("libmp3lame");
// 设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 56000 = 56kb)
audio.setBitRate(new Integer(56_000));
// 设置重新编码的音频流中使用的声道数(1 =单声道,2 = 双声道(立体声))
audio.setChannels(1);
// 采样率越高声音的还原度越好,文件越大
audio.setSamplingRate(new Integer(44100));
// 视频编码属性配置
VideoAttributes video=new VideoAttributes();
// 设置编码
video.setCodec("mpeg4");
//设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 5600000 = 5600kb)
video.setBitRate(new Integer(5_600_000 / rate));
// 设置视频帧率(帧率越低,视频会出现断层,越高让人感觉越连续),这里 除1000是为了单位转换
video.setFrameRate(new Integer(15));
// 编码设置
EncodingAttributes attr=new EncodingAttributes();
attr.setFormat("mp4");
attr.setAudioAttributes(audio);
attr.setVideoAttributes(video);
// 设置值编码
Encoder ec = new Encoder();
ec.encode(new MultimediaObject(source), target, attr);
System.out.println("end");
long end = System.currentTimeMillis();
System.out.println("压缩前大小:"+source.length() + " 压缩后大小:" + target.length());
System.out.println("压缩耗时:" + (end -start));
} catch (EncoderException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
写在最后的话
长
按
关
注
解锁更多精彩内容