效果图如下,h5资源请查看 发布网站
准备FFmpeg调用方法
/**
* 视频转码
*
* @param ffmpegPath 转码工具的存放路径
* @param upFilePath 用于指定要转换格式的文件,要截图的视频源文件
* @param codcFilePath 格式转换后的的文件保存路径
* @param mediaPicPath 截图保存路径
* @return
* @throws Exception
*/
public static boolean executeCodecs(String ffmpegPath, String upFilePath, String codcFilePath,
String mediaPicPath) throws Exception {
// 创建一个List集合来保存转换视频文件为flv格式的命令
List<String> convert = new ArrayList<String>();
convert.add(ffmpegPath); // 添加转换工具路径
convert.add("-i"); // 添加参数"-i",该参数指定要转换的文件
convert.add(upFilePath); // 添加要转换格式的视频文件的路径
convert.add("-qscale"); //指定转换的质量
convert.add("6");
convert.add("-ab"); //设置音频码率
convert.add("64");
convert.add("-ac"); //设置声道数
convert.add("2");
convert.add("-ar"); //设置声音的采样频率
convert.add("22050");
convert.add("-r"); //设置帧频
convert.add("24");
convert.add("-y"); // 添加参数"-y",该参数指定将覆盖已存在的文件
convert.add(codcFilePath);
boolean mark = true;
ProcessBuilder builder = new ProcessBuilder();
try {
builder.command(convert);
builder.redirectErrorStream(true);
Process videoProcess = builder.start();
new PrintStream(videoProcess.getInputStream()).start();
videoProcess.waitFor();
return true;
// builder.command(cutpic);
// builder.redirectErrorStream(true);
// 如果此属性为 true,则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并,
//因此两者均可使用 Process.getInputStream() 方法读取。这使得关联错误消息和相应的输出变得更容易
// builder.start();
} catch (Exception e) {
mark = false;
System.out.println(e);
e.printStackTrace();
}
return mark;
}
测试过程中,当调用此方法时,mark结果是瞬间返回的,也就是说转换过程是异步的,当参数返回时,有可能还并没有生成GIF图片,所以就需要监听转换进度。方法如下,测试通过。
Process videoProcess = builder.start();
new PrintStream(videoProcess.getInputStream()).start();
videoProcess.waitFor();
我创建的是java web项目,文件上传和转换如下
package main.controller;
import main.ConverVideo;
import main.entity.Media;
import main.util.FileUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.io.*;
import java.util.Arrays;
import java.util.List;
/**
* Created by Administrator on 2017-06-19.
*/
@WebServlet("/controller/MediaService")
public class MediaService extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/videos/upload");
File file = new File(savePath);
//判断上传文件的保存目录是否存在
if (!file.exists() && !file.isDirectory()) {
System.out.println(savePath+"目录不存在,需要创建");
//创建目录
file.mkdir();
}
String filename="";
//消息提示
String message = "";
try{
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
}else{//如果fileitem中封装的是上传文件
//得到上传的文件名称,
filename = item.getName();
//允许上传的文件类型asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv
String fileType = "mp4,wmv,rmvb,mov,avi,flv,mpg,asx,asf";
//允许上传的文件最大大小(100M,单位为byte)
int maxSize = 1024*1024*100;
//判断文件大小是否超限
if (item.getSize() > maxSize)
{
item.delete();
JOptionPane.showMessageDialog(null, "文件大小超过限制!应小于" + maxSize
/ 1024 / 1024 + "M");
return;
}
//获取文件后缀名
String extName = filename.substring(filename.indexOf(".") + 1).toLowerCase().trim();
//判断是否为允许上传的文件类型
if ( !Arrays.<String> asList(fileType.split(",")).contains(extName))
{
item.delete();
JOptionPane.showMessageDialog(null, "文件类型不正确,必须为" + fileType
+ "的文件!");
return ;
}
System.out.println(filename);
if(filename==null || filename.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(filename.lastIndexOf("\\")+1);
//获取item中的上传文件的输入流
InputStream in = item.getInputStream();
//创建一个文件输出流
FileOutputStream out = new FileOutputStream(savePath + System.getProperty("file.separator") + filename);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=in.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功!";
}
}
}catch (Exception e) {
message= "文件上传失败!";
e.printStackTrace();
}
boolean flag = false; //转码成功与否的标记
// 获取配置的转换工具(ffmpeg.exe)的存放路径
String ffmpegPath = getServletContext().getRealPath("/tools/ffmpeg.exe");
String uploadFile = getServletContext().getRealPath("/videos/upload/"+filename);
String codcFilePath = getServletContext().getRealPath("/videos/temp/"+filename.substring(0,filename.lastIndexOf("."))+".gif");
String mediaPicPath = getServletContext().getRealPath("/videos/images/"+filename.substring(0,filename.lastIndexOf("."))+".jpg");
//转码
System.out.println(ffmpegPath+"\n-----------------------------------");
try {
flag = ConverVideo.executeCodecs(ffmpegPath, uploadFile, codcFilePath, mediaPicPath);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
if(flag){
//转码成功,向数据表中添加该视频信息
message = "<li>上传成功!</li>";
}else{
message = "上传失败";
}
System.out.print(message);
FileUtil.clearFile("/tools/server/videos");
request.setAttribute("gifpath","/videos/temp/"+filename.substring(0,filename.lastIndexOf("."))+".gif");
request.setAttribute("message",message);
request.setAttribute("filename",filename.substring(0,filename.lastIndexOf("."))+".gif");
request.setAttribute("downurl","/controller/DownLoadServlet");
request.getRequestDispatcher("/showgif.jsp").forward(request, response);
// if("/play".equals(path)){
// String idstr = request.getParameter("id");
// int mediaId = -1;
// Media media = null;
// if(null!=idstr){
// mediaId = Integer.parseInt(idstr);
// }
// request.setAttribute("media", media);
// request.getRequestDispatcher("media_player.jsp").forward(request, response);
// }
}
}
转换成功后,界面展示,下载
package main.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/controller/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到要下载的文件名
String fileName = request.getParameter("filename"); //
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
String fileSaveRootPath=this.getServletContext().getRealPath("/videos/temp");
// //通过文件名找出文件的所在目录
// String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
//得到要下载的文件
File file = new File(fileSaveRootPath + System.getProperty("file.separator") + fileName);
//如果文件不存在
if(!file.exists()){
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/index.jsp").forward(request, response);
return;
}
//处理文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//设置响应头,控制浏览器下载该文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//读取要下载的文件,保存到文件输入流
FileInputStream in = new FileInputStream(file.getPath());
//创建输出流
OutputStream out = response.getOutputStream();
//创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
//循环将输入流中的内容读取到缓冲区当中
while((len=in.read(buffer))>0){
//输出缓冲区的内容到浏览器,实现文件下载
out.write(buffer, 0, len);
}
//关闭文件输入流
in.close();
//关闭输出流
out.close();
}
/**
* @Method: findFileSavePathByFileName
* @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
* @Anthor:孤傲苍狼
* @param filename 要下载的文件名
* @param saveRootPath 上传文件保存的根目录,也就是/WEB-INF/upload目录
* @return 要下载的文件的存储目录
*/
public String findFileSavePathByFileName(String filename,String saveRootPath){
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
String dir = saveRootPath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5
File file = new File(dir);
if(!file.exists()){
//创建目录
file.mkdirs();
}
return dir;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}