最近做一个项目需要对视频进行处理,网上看了一写资料和教程,大部分都是使用ffmpeg对视频进行处理。话不多说直接上代码,很简单,一看就懂。参考博客,博主写的非常简单易懂,我自己根据业务做了一点简单的调整
首先是一个路径配置类代码如下:
public class Contants {
/**
* @Description:(3.工具类主类)设置转码工具的各个路径
* @param:@param args
* @return:void
* @author:Zoutao
* @date:2018-6-22
* @version:V1.0
*/
public static final String ffmpegpath = "D:/ffmpeg-20171225-be2da4c-win64-static/bin/ffmpeg.exe"; // ffmpeg工具安装位置
public static final String videofolder = "d://file/"; // 需要被转换格式的视频目录
public static final String targetfolder = "d://temp/"; // 转码后视频保存的目录
}
import com.tk.blogadmin.utils.DateUtils;
/**
* @ClassName ConverVideoTest
* @Desecription TODO
* @Author tkk
* @Date 2019/11/13 9:43
**/
public class ConverVideoTest {
/**
* @Description:(1.转码功能调用)
* @param:@param yuanPATH
* @return:void
* @author:Zoutao
* @date:2018-6-23
* @version:V1.0
*/
/*本地测试专用--zoutao*/
public static void main(String[] args) {
System.out.println(DateUtils.getCurrentDateTime());
ConverVideoTest c = new ConverVideoTest();
String yuanPATH = "D:/file/IMG_4141.MP4"; //本地源视频
c.run(yuanPATH);
System.out.println(DateUtils.getCurrentDateTime());
}
//web调用
public void run(String yuanPATH) {
try {
// 转码开始
//String filePath = "D:/testfile/video/rmTest.rm"; //本地源视频测试
String filePath = yuanPATH; //web传入的源视频
System.out.println("ConverVideoTest说:传入工具类的源视频为:"+filePath);
ConverVideoUtils zout = new ConverVideoUtils(filePath); //传入path
String targetExtension = ".mp4"; //设置转换的格式
boolean isDelSourseFile = true; //删除源文件
boolean beginConver = zout.beginConver(targetExtension,isDelSourseFile);
System.out.println(beginConver);
} catch (Exception e) {
e.printStackTrace();
}
}
}
mport java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
*
* @Title: ConverVideoUtils.java
* @Package:com.resource.mytools
* @Description:(2.转码和截图功能)
* @see:接收Contants实体的路径
* @author:Zoutao
* @date:2018-7-15
* @version:V1.0
*/
public class ConverVideoUtils {
private String sourceVideoPath; //源视频路径
private String filerealname; //文件名不包括后缀名
private String filename; //包括后缀名
private String videofolder = Contants.videofolder; // 别的格式视频的目录
private String targetfolder = Contants.targetfolder; // flv视频的目录
private String ffmpegpath = Contants.ffmpegpath; // ffmpeg.exe的目录
public ConverVideoUtils() {
}
//重构构造方法,传入源视频
public ConverVideoUtils(String path) {
sourceVideoPath = path;
}
//set和get方法传递path
public String getPATH() {
return sourceVideoPath;
}
public void setPATH(String path) {
sourceVideoPath = path;
}
/**
* 转换视频格式
* @param String targetExtension 目标视频后缀名 .xxx
* @param boolean isDelSourseFile 转换完成后是否删除源文件
* @return
*/
public boolean beginConver(String targetExtension, boolean isDelSourseFile) {
File fi = new File(sourceVideoPath);
filename = fi.getName();//获取文件名+后缀名
filerealname = filename.substring(0, filename.lastIndexOf(".")); //获取不带后缀的文件名-后面加.toLowerCase()小写
System.out.println("----接收到文件("+sourceVideoPath+")需要转换-------");
//检测本地是否存在
/*if (checkfile(sourceVideoPath)) {
System.out.println(sourceVideoPath + "========该文件存在哟 ");
return false;
}*/
System.out.println("----开始转文件(" + sourceVideoPath + ")-------------------------- ");
//执行转码机制
if (process(targetExtension,isDelSourseFile)) {
System.out.println("视频转码结束================= ");
//删除原视频+临时视频
/*if (isDelSourseFile) {
deleteFile(sourceVideoPath);
}*/
/*File file1 = new File(sourceVideoPath);
if (file1.exists()){
System.out.println("删除原文件-可用:"+sourceVideoPath);
file1.delete();
}*/
String temppath=videofolder + filerealname + ".avi";
File file2 = new File(temppath);
if (file2.exists()){
System.out.println("删除临时文件:"+temppath);
file2.delete();
}
sourceVideoPath = null;
return true;
} else {
sourceVideoPath = null;
return false;
}
}
/**
* 检查文件是否存在-多处都有判断
* @param path
* @return
*/
/*private boolean checkfile(String path) {
path = sourceVideoPath;
File file = new File(path);
try {
if (file.exists()) {
System.out.println("视频文件不存在============="+path);
return true;
} else {
System.out.println("视频文件存在"+path);
return false;
}
} catch (Exception e) {
// TODO: handle exception
System.out.println("拒绝对文件进行读访问");
}
return false;
}*/
/**
* 实际转换视频格式的方法
* @param targetExtension 目标视频后缀名
* @param isDelSourseFile 转换完成后是否删除源文件
* @return
*/
private boolean process(String targetExtension, boolean isDelSourseFile) {
//先判断视频的类型-返回状态码
int type = checkContentType();
boolean status = false;
//根据状态码处理
if (type == 0) {
System.out.println("ffmpeg可以转换,统一转为mp4文件");
status = processVideoFormat(sourceVideoPath,targetExtension,isDelSourseFile);//可以指定转换为什么格式的视频
} else if (type == 1) {
//如果type为1,将其他文件先转换为avi,然后在用ffmpeg转换为指定格式
System.out.println("ffmpeg不可以转换,先调用mencoder转码avi");
String avifilepath = processAVI(type);
if (avifilepath == null){
// 转码失败--avi文件没有得到
System.out.println("mencoder转码失败,未生成AVI文件");
return false;
}else {
System.out.println("生成AVI文件成功,ffmpeg开始转码:");
status = processVideoFormat(avifilepath,targetExtension,isDelSourseFile);
}
}
return status; //执行完成返回布尔类型true
}
/**
* 检查文件类型
* @return
*/
private int checkContentType() {
//取得视频后缀-
String type = sourceVideoPath.substring(sourceVideoPath.lastIndexOf(".") + 1, sourceVideoPath.length()).toLowerCase();
System.out.println("源视频类型为:"+type);
// 如果是ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
if (type.equals("avi")) {
return 0;
} else if (type.equals("mpg")) {
return 0;
} else if (type.equals("wmv")) {
return 0;
} else if (type.equals("3gp")) {
return 0;
} else if (type.equals("mov")) {
return 0;
} else if (type.equals("mp4")) {
return 0;
} else if (type.equals("asf")) {
return 0;
} else if (type.equals("asx")) {
return 0;
} else if (type.equals("flv")) {
return 0;
}else if (type.equals("mkv")) {
return 0;
}
System.out.println("上传视频格式异常");
return 9;
}
/**
* 转换为指定格式--zoutao
* ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
* @param oldfilepath
* @param targetExtension 目标格式后缀名 .xxx
* @param isDelSourseFile 转换完成后是否删除源文件
* @return
*/
private boolean processVideoFormat(String oldfilepath, String targetExtension, boolean isDelSourceFile) {
System.out.println("调用了ffmpeg.exe工具");
//先确保保存转码后的视频的文件夹存在
File TempFile = new File(targetfolder);
if (TempFile.exists()) {
if (TempFile.isDirectory()) {
System.out.println("该文件夹存在。");
}else {
System.out.println("同名的文件存在,不能创建文件夹。");
}
}else {
System.out.println("文件夹不存在,创建该文件夹。");
TempFile.mkdir();
}
List commend = new ArrayList();
commend.add(ffmpegpath); //ffmpeg.exe工具地址
commend.add("-i");
commend.add(oldfilepath); //源视频路径
commend.add("-vf"); //视频分辨率处理
commend.add("scale=180:320"); //9:16
commend.add("-vcodec");
commend.add("h263"); //
commend.add("-ab"); //新增4条
commend.add("64"); //高品质:128 低品质:64
commend.add("-acodec");
commend.add("mp3"); //音频编码器:原libmp3lame
commend.add("-ac");
commend.add("2"); //原1
commend.add("-ar");
commend.add("22050"); //音频采样率22.05kHz
commend.add("-r");
commend.add("15"); //高品质:29.97 低品质:15
commend.add("-c:v");
commend.add("libx264"); //视频编码器:视频是h.264编码格式
commend.add("-strict");
commend.add("-2");
commend.add(targetfolder + filerealname + targetExtension); // //转码后的路径+名称,是指定后缀的视频
//打印命令--zoutao
StringBuffer test = new StringBuffer();
for (int i = 0; i < commend.size(); i++) {
test.append(commend.get(i) + " ");
}
System.out.println("ffmpeg输入的命令:"+test);
try {
//多线程处理加快速度-解决rmvb数据丢失builder名称要相同
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start(); //多线程处理加快速度-解决数据丢失
final InputStream is1 = p.getInputStream();
final InputStream is2 = p.getErrorStream();
new Thread() {
public void run() {
BufferedReader br = new BufferedReader(
new InputStreamReader(is1));
try {
String lineB = null;
while ((lineB = br.readLine()) != null) {
if (lineB != null)
System.out.println(lineB); //打印mencoder转换过程代码
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
BufferedReader br2 = new BufferedReader(
new InputStreamReader(is2));
try {
String lineC = null;
while ((lineC = br2.readLine()) != null) {
if (lineC != null)
System.out.println(lineC); //打印mencoder转换过程代码
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
p.waitFor(); //进程等待机制,必须要有,否则不生成mp4!!!
System.out.println("生成mp4视频为:"+videofolder + filerealname + ".mp4");
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
}