转换程序:
package com.wamei.tool;
import com.wamei.common.ResourceUtils;
import com.wamei.util.JsonResponseHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* Created by chen on 2016/8/23.
*/
public class VideoConvertUtil implements Runnable{
private final static Logger logger = Logger.getLogger(VideoConvertUtil.class);
public static final String FFMPEG_PATH = "D:/ffmpeg/bin/ffmpeg.exe";
private static Process process;
private String video_path;
private String videoFileName;
public VideoConvertUtil(String video_path,String videoFileName){
this.video_path = video_path;
this.videoFileName = videoFileName;
}
@Override
public void run() {
convertCommand(video_path,videoFileName);
}
/**
* 视频转换
* @param video_path
* @return
*/
public static String convertCommand(String video_path,String videoFileName) {
//D:/ffmpeg.exe -i D:\360Downloads\7049a5246a2d44fe897c2ea1c917eeee.wmv -vcodec libx264 -preset ultrafast -profile:v baseline -acodec aac -strict experimental -s 640*480 -b 568k -ab 128k iCulture.mp4
if(StringUtils.isEmpty(video_path)){
return null;
}
File file = new File(video_path);
if (!file.exists()) {
System.err.println("路径[" + video_path + "]对应的视频文件不存在!");
return null;
}
String videoUrl = "";
String format = ".mp4";
try {
// String videoName = videoFileName.substring(0,videoFileName.lastIndexOf("."))+format;
// String newVideoPath = video_path.substring(0,video_path.lastIndexOf("/")+1)+videoName;
String newVideoPath = video_path.substring(0,video_path.lastIndexOf("."))+format;
String videoName = videoFileName.substring(0,videoFileName.lastIndexOf("."))+format;
Integer type = checkVideoType(video_path);
logger.info("old vodeo path:"+video_path);
logger.info("new video path"+newVideoPath);
if(0==type){
List<String> commands = new java.util.ArrayList<String>();
commands.add(FFMPEG_PATH);
commands.add("-i");
commands.add(video_path);
commands.add("-vcodec");
commands.add("libx264");
commands.add("-preset");
commands.add("ultrafast");
commands.add("-profile:v");
commands.add("baseline");
commands.add("-acodec");
commands.add("aac");
commands.add("-strict");
commands.add("experimental");
// commands.add("-s");
// commands.add("640*480");
// commands.add("-b");//视频品质设置(有模糊,要视频清晰使用-qscale)
// commands.add("568k");
commands.add("-qscale");//视频品质
commands.add("6");//视频品质参数
commands.add("-ab");
commands.add("128k");
commands.add("-y");//文件存在选择重写
commands.add(newVideoPath);
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
process = builder.start();
//process.waitFor();//等待进程执行完毕
//防止ffmpeg进程塞满缓存造成死锁
InputStream error = process.getErrorStream();
InputStream is = process.getInputStream();
byte[] b = new byte[1024];
int readbytes = -1;
try {
while((readbytes = error.read(b)) != -1){
logger.info("FFMPEG视频转换进程错误信息:"+new String(b,0,readbytes));
}
while((readbytes = is.read(b)) != -1){
logger.info("FFMPEG视频转换进程输出内容为:"+new String(b,0,readbytes));
}
}catch (IOException e2){
}finally {
error.close();
is.close();
}
}
videoUrl = "http://"+JsonResponseHelper.serverAddress+"/wamei/upload/video/"+videoName;
logger.info("视频格式转换:"+videoUrl);
} catch (Exception e) {
e.printStackTrace();
}
return videoUrl;
}
private static Integer checkVideoType(String PATH) {
String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length())
.toLowerCase();
// 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 9;//本身是MP4格式不用转换
} else if (type.equals("asf")) {
return 0;
} else if (type.equals("asx")) {
return 0;
} else if (type.equals("flv")) {
return 0;
}
// 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
else if (type.equals("wmv9")) {
return 1;
} else if (type.equals("rm")) {
return 1;
} else if (type.equals("rmvb")) {
return 1;
}
return 9;
}
public static void main(String[] args) {
//String videoPath = "E:\\wamei_app\\04编码\\java\\idea\\wamei\\out\\artifacts\\wamei_war_exploded\\upload\\video\\20160819\\1471575811202054258.mp4";
String videoPath = "D:/360Downloads/7049a5246a2d44fe897c2ea1c917eeee.mp4";
//String filename = "test001.wmv";
//String url = convertCommand(videoPath,filename);
//System.out.println("视频链接:"+url);
for(int i=0;i<10;i++){
logger.info("线程"+i);
String fileName = "test00"+i+".wmv";
VideoConvertUtil v1= new VideoConvertUtil(videoPath,fileName);
Thread t1 = new Thread(v1);
t1.start();
}
}
}
截取视频封面程序
package com.wamei.util;
import com.wamei.common.ResourceUtils;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* Created by on 2016/8/23.
*/
public class VideoPreviewImageUtil {
private final static Logger logger = Logger.getLogger(VideoPreviewImageUtil.class);
public static final String FFMPEG_PATH = "D:/ffmpeg.exe";
public static final String serverPath = ResourceUtils.getValue("wamei.server.path");
private static Process process;
public static String processImg(String veido_path) {
String imageUrl = "";
File file = new File(veido_path);
if (!file.exists()) {
System.err.println("路径[" + veido_path + "]对应的视频文件不存在!");
return null;
}
List<String> commands = new java.util.ArrayList<String>();
commands.add(FFMPEG_PATH);
commands.add("-i");
commands.add(veido_path);
commands.add("-y");
commands.add("-f");
commands.add("image2");
commands.add("-ss");
commands.add("8");//这个参数是设置截取视频多少秒时的画面
//commands.add("-t");
//commands.add("0.001");
commands.add("-s");
commands.add("700x525");
Long date = new Date().getTime();
String filePath = "/wamei/upload/image/video_"+date+".jpg";
imageUrl = serverPath+"/wamei/upload/image/video_"+date+".jpg";
//imageUrl = serverPath+"/wamei_war_exploded/upload/image/video_"+date+".jpg";//本地测试路径
System.out.println("图片截取原路径:"+imageUrl);
commands.add(imageUrl);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
process = builder.start();
process.waitFor();//等待进程执行完毕
//防止ffmpeg进程塞满缓存造成死锁
InputStream error = process.getErrorStream();
InputStream is = process.getInputStream();
byte[] b = new byte[1024];
int readbytes = -1;
try {
while((readbytes = error.read(b)) != -1){
logger.info("FFMPEG截图进程错误信息:"+new String(b,0,readbytes));
}
while((readbytes = is.read(b)) != -1){
logger.info("FFMPEG截图进程输出内容为:"+new String(b,0,readbytes));
}
}catch (IOException e2){
}finally {
error.close();
is.close();
}
imageUrl = "http://"+JsonResponseHelper.serverAddress+filePath;
logger.info("视频封面截取:"+imageUrl);
} catch (Exception e) {
e.printStackTrace();
}
return imageUrl;
}
public static boolean processImg(String veido_path, String ffmpeg_path) {
File file = new File(veido_path);
if (!file.exists()) {
System.err.println("路径[" + veido_path + "]对应的视频文件不存在!");
return false;
}
List<String> commands = new java.util.ArrayList<String>();
commands.add(ffmpeg_path);
commands.add("-i");
commands.add(veido_path);
commands.add("-y");
commands.add("-f");
commands.add("image2");
commands.add("-ss");
commands.add("8");//这个参数是设置截取视频多少秒时的画面
//commands.add("-t");
//commands.add("0.001");
commands.add("-s");
commands.add("700x525");
String imageUrl = veido_path.substring(0, veido_path.lastIndexOf(".")).replaceFirst("vedio", "file") + ".jpg";
Long date = new Date().getTime();
String filePath = "/wamei/upload/image/video_"+date+".jpg";
imageUrl = serverPath+filePath;
commands.add(imageUrl);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
builder.start();
System.out.println("截取成功");
System.out.println("===="+imageUrl);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
String videoPath = "E:\\wamei_app\\04编码\\java\\idea\\wamei\\out\\artifacts\\wamei_war_exploded\\upload\\video\\20160819\\1471575811202054258.mp4";
processImg(videoPath, VideoPreviewImageUtil.FFMPEG_PATH);
}
}
处理上传视频处理:
/**
* 上传视频
* @param response
*/
@RequestMapping(value = "/upload/video",method = RequestMethod.POST)
@ResponseBody
public void saveUploadVideo(HttpServletRequest request,HttpServletResponse response) {
StringBuffer sb = new StringBuffer();
String savePath="upload/video/";
String videoName = "",videoType="mp4";
String picSrc = "",videoLink = "";//视频封面//视频链接
boolean mark = false,status = false;
try {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("videoFile");
if (file != null) {
videoName=file.getOriginalFilename();
videoType = videoName.substring(videoName.lastIndexOf(".")+1);// 截取视频文件格式
videoType = StringUtils.isNotEmpty(videoType)?videoType:"mp4";
String fileName = UUID.randomUUID().toString().replace("-", "")+"."+videoType;
String path = request.getSession().getServletContext().getRealPath(savePath+fileName);
videoLink = "http://"+JsonResponseHelper.serverAddress+"/wamei/"+savePath+fileName;
videoLink = videoLink.substring(0,videoLink.lastIndexOf("."))+".mp4";
//视频文件大小限制在30M
if (file.getSize() > 0 && file.getSize() <= 31457280) {
logger.info("file size:=================== "+file.getSize());
mark = FileHelper.saveUploadedVideo(request,videoName, file, path);
if(mark){
picSrc = VideoPreviewImageUtil.processImg(path);//截取视频封面
if(null!=picSrc){
status = true;
}
//视频格式转换
VideoConvertUtil v1= new VideoConvertUtil(path,fileName);
Thread t1 = new Thread(v1);
t1.start();
}
}
}
if(status){
sb.append("{\"statusCode\":\"1\", \"msg\":\"上传成功!\", \"errorCode\":\"\",\"videoLink\":\""+videoLink+"\", \"videoConver\":\""+picSrc+"\"}");
}else{
sb.append("{\"statusCode\":\"0\", \"msg\":\"上传失败\", \"errorCode\":\"\", \"result\":{}}");
}
} catch (Exception e) {
e.printStackTrace();
sb.append("{\"statusCode\":\"0\", \"msg\":\"上传失败\", \"errorCode\":\"\", \"result\":{}}");
}
JsonResponseHelper.renderText(sb.toString(), response);
}
页面:利用uploadify 插件上传视频
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<head>
<title>挖媒管理后台 - 快讯添加/编辑</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- bootstrap -->
<link href="/wamei/pages/css/bootstrap/bootstrap.css" rel="stylesheet" />
<link href="/wamei/pages/css/bootstrap/bootstrap-datetimepicker.min.css" rel="stylesheet" />
<link href="/wamei/pages/css/bootstrap/bootstrap-responsive.css" rel="stylesheet" />
<link href="/wamei/pages/css/bootstrap/bootstrap-overrides.css" type="text/css"
rel="stylesheet" />
<!-- global styles -->
<link rel="stylesheet" type="text/css" href="/wamei/pages/css/elements.css" />
<link rel="stylesheet" type="text/css" href="/wamei/pages/css/icons.css" />
<!-- libraries -->
<link rel="stylesheet" type="text/css"
href="/wamei/pages/css/lib/font-awesome.css" />
<!-- this page specific styles -->
<link rel="stylesheet" href="/wamei/pages/css/compiled/personal-info.css"
type="text/css" media="screen" />
<!-- this page specific styles -->
<!-- open sans font -->
<link href='/wamei/pages/css/open-sans-font.css' rel='stylesheet' type='text/css' />
<link rel="stylesheet" type="text/css" href="/wamei/pages/js/uploadify/uploadify.css" />
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
#previewDiv{
margin-left: 134px;
}
#previewDiv img{
margin-right: 6px;
margin-top:6px;
}
#videoFileDiv{
margin-left: 134px;
}
#videoFileDiv a{
margin-top: 15px;
}
#videoDiv{
margin-left: 134px;
}
#videoDiv img{
margin-right: 6px;
margin-top:6px;
}
.image-remove-icon{
position: relative;
top: -36px;
left: -22px;
background-color: #3e4ada;
}
.image-remove-icon i{
color:#fff;
}
.uploadify{
height: 50px !important;
}
.uploadify-button{
height: 25px !important;
line-height: 25px !important;
width: 70px !important;
margin-top: 10px;
}
.swfupload{
top: 7px;
height: 45px;
}
.uploadify-queue{
margin-top: 27px;
}
</style>
</head>
<!-- main container .wide-content is used for this layout without sidebar :) -->
<div class="content wide-content">
<div class="container-fluid">
<div class="settings-wrapper" id="pad-wrapper">
<div class="span7 personal-info">
<div id="roleEditDiv">
<h5 class="personal-title">快讯添加/编辑</h5>
</div>
<form action="/wamei/newsFlashController/save.htm" method="post" enctype="multipart/form-data" id="editForm">
<input type="hidden" name="id" value="${mo.id}"/>
<input type="hidden" name="newsFlashStatus" value="${mo.status}"/>
<input type="hidden" name="createTime" value="${mo.createTimeStr}"/>
<div class="field-box">
<label class="Validform_label">快讯类型:</label>
<div class="ui-select">
<select id="newsFlashType" name="newsFlashType.id">
<option value="">请选择</option>
<c:forEach items="${typeList}" var="item" varStatus="status">
<option value="${item.id}">${item.name}</option>
</c:forEach>
</select>
</div>
</div>
<div class="field-box">
<label class="Validform_label">快讯内容:</label>
<textarea id="content" name="content" value="${mo.content}" datatype="/^\s*$/|*1-500" errormsg="快讯内容至少1个字符,最多500个字符!" style="width: 300px;height: 100px;max-width: 300px;max-height: 100px;">${mo.content}</textarea>
</div>
<div class="field-box">
<label class="Validform_label">快讯图片:</label>
<div id="previewDiv">
<img src="/wamei/pages/img/new-gallery-img.png" id="imghead" style='width:100px;height:100px;'/>
</div>
<div id="imageFile" style="display:none;">
<input type="file" name="imagefile" id="hiddenFile" οnchange='previewManyImage(this,"imgFile");'/>
</div>
</div>
<div class="field-box">
<label class="Validform_label">快讯视频:</label>
<div id="videoDiv">
</div>
<div id="videoFileDiv">
<input type="file" name="videoFile" id="videoFile" />
</div>
</div>
<div class="field-box">
<label class="Validform_label">全文链接:</label>
<div class="ui-select">
<select id="linkType" name="linkType" datatype="*" errormsg="请选择全文链接类型!">
<option value="1">文章ID</option>
<option value="2" selected>H5链接</option>
</select>
</div>
</div>
<div class="field-box">
<label class="Validform_label"></label>
<input class="span5 inline-input" type="text" value="${mo.link}" id="link" name="link" style="height: 25px"/>
</div>
<div class="field-box">
<label>定时发布:</label>
<div class="input-append date form_datetime">
<input class="span5 inline-input" type="text" id="publishTime" readonly name="publishTime" value="${mo.publishTimeStr}" style="height: 25px;width: 135%;" />
<span class="add-on"><i class="icon-remove"></i></span>
<span class="add-on"><i class="icon-calendar"></i></span>
</div>
</div>
<div class="span6 field-box actions">
<input type="button" class="btn-glow primary" value="提交" id="checkButton"/> <span></span>
<input type="button" class="btn-glow primary" value="取消" οnclick="cancle();" />
</div>
</form>
</div>
</div>
</div>
</div>
<!-- end main container -->
<!-- scripts -->
<script src="/wamei/pages/js/jquery.min.js"></script>
<script src="/wamei/pages/js/jquery.form.js"></script>
<script src="/wamei/pages/js/bootstrap.min.js"></script>
<script src="/wamei/pages/js/bootstrap-datetimepicker.js"></script>
<script src="/wamei/pages/js/Validform_v5.3.2.js"></script>
<script type="text/javascript" src="/wamei/pages/js/uploadify/jquery.uploadify.min.js"></script>
<script src="/wamei/pages/js/theme.js"></script>
<script type="text/javascript">
$(function() {
$('#videoFile').uploadify({
'swf' : '/wamei/pages/js/uploadify/uploadify.swf',
'uploader' : '/wamei/newsFlashController/upload/video.htm',
// Your options here
'formData': {},
'fileObjName' : 'videoFile',
'fileSizeLimit' : 0,
'auto':true,
'buttonText': '添加视频',
'fileTypeExts' : '*.mp4;*.avi;*.3gp;*.wmv;*.flv;*.mov;*.mpeg',
'removeCompleted' : true,
'removeTimeout' : 1,
'multi' : false,
'onUploadStart' : function(file) {
var num = $(".videoCover").length;
if(file.size>=31457280){
alert("超过视频上传限制大小(30M)!");
this.cancelUpload(file.id);
}
if(null!=num && num>4){
alert("最多只能上传5个视频!");
this.cancelUpload(file.id);
//$('#' + file.id).remove();
}
},
'onUploadSuccess':function(file,json,response){
//console.log(file);console.log(json);
var videoId = "video"+Math.floor(Math.random()*100000+1);
var data = eval("(" + json + ")");
if (data && data.statusCode == 1) {
$("#videoDiv").append("<img src='"+data.videoConver+"' link='"+data.videoLink+"' class='videoCover "+videoId+"' οnclick='previewVideo(this);' style='width:100px;height:100px;'/>" +
"<span class='image-remove-icon icon trash' videoId='"+videoId+"' title='删除' οnclick='videoRemove(this);'><i class='icon-remove'></i></span>");
var videosData =data.videoConver +"@"+ data.videoLink;
$("#videoFileDiv").append("<input type='hidden' class='"+videoId+"' name='videos' value='"+videosData+"' />");
} else {
alert(data.msg);
}
},
'onQueueComplete' : function(json) {
$('.uploadify-queue').html('');
//return false;
}
});
//快讯图片
var images = '${mo.images}';
if(images){
var data = images.split(",");
console.log(data);
for(var i=0;i<data.length;i++){
var imgId = "img"+i;
$("#imghead").before("<img src='"+data[i]+"' class='imgFile "+imgId+"' style='width:100px;height:100px;'/>" +
"<span class='image-remove-icon icon trash' imgId='"+imgId+"' title='删除' οnclick='imageRemove(this);'><i class='icon-remove'></i></span>");
$("#imageFile").append("<input type='hidden' class='"+imgId+"' name='imageUrl' value='"+data[i]+"' />");
}
}
//快讯视频
var videoCover = '${mo.videoCover}';
var videos = '${mo.videos}';
if(videoCover){
var data = videoCover.split(",");
var videoData = videos.split(",");
console.log(data);console.log(videoData);
for(var i=0;i<data.length;i++){
var videoId = "video"+i;
$("#videoDiv").append("<img src='"+data[i]+"' link='"+videoData[i]+"' class='videoCover "+videoId+"' οnclick='previewVideo(this);' style='width:100px;height:100px;'/>" +
"<span class='image-remove-icon icon trash' videoId='"+videoId+"' title='删除' οnclick='videoRemove(this);'><i class='icon-remove'></i></span>");
var videosStr = data[i] + "@" +videoData[i];
$("#videoFileDiv").append("<input type='hidden' class='"+videoId+"' name='videos' value='"+videosStr+"' />");
}
}
$(".form_datetime").datetimepicker({
format:"yyyy-mm-dd hh:ii:ss",
autoclose: true,
todayBtn: true,
minuteStep: 10,
pickerPosition: "bottom-left",
minView:0
});
//类型选中
var typeId = "${mo.newsFlashType.id}";
if(typeId){
$("#newsFlashType").val(typeId);
}
//全文链接类型
var linkType = '${mo.linkType}';
if(linkType) {
$("#linkType").val(linkType);
}
//上传图片
$("#imghead").on("click", function() {
$("#hiddenFile").click();
});
$("#editForm").Validform({
btnSubmit:"#checkButton",
tiptype:function(msg){
if(msg != '' && msg!='通过信息验证!'){
alert(msg);
}
},
tipSweep:true,
beforeSubmit:function(){
saveForm();
return false;
}
});
});
function saveForm(){
var content = $("#content").val();
var imgageUrl = $("input[name='imageUrl']").val();
var videoUrl = $("input[name='videos']").val();
console.log(link+"======m====="+imgageUrl+"====v====="+videoUrl);
if((!content) && (!videoUrl) && (!imgageUrl)){
alert("快讯内容,视频,图片三项不能全为空!");
return ;
}
$("#editForm").ajaxSubmit({
type: 'post',
async: false,
success: function($data) {
var data = eval("("+$data+")");
if(data && data.statusCode==1){
alert("保存信息成功!");
window.location.href = "/wamei/pages/articles/newsflash_list.jsp";
}else{
alert(data.msg);
}
}
});
}
function cancle(){
window.history.back(-1);
}
//移除图片
function imageRemove(obj){
var id = $(obj).attr("imgId");
$("."+id).remove();
$(obj).remove();
}
//移除视频
function videoRemove(obj){
var id = $(obj).attr("videoId");
$("."+id).remove();
$(obj).remove();
}
//视频播放
function previewVideo(obj){
var videoUrl = $(obj).attr("link");
var videoCover = $(obj).attr("src");
window.open("/wamei/pages/articles/previewVideo.jsp?videoUrl="+videoUrl+"&videoCover="+videoCover+"");
}
</script>