- 浏览: 135013 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
zheng_zhimeng:
这个版本在linux的版本下有问题,亲们用的没有问题么
文档展示:IcePDF 将PDF转换为图片 -
yuming.xiao:
转换的某些图片,有些模糊。不知道楼主遇到这个问题没有
文档展示:IcePDF 将PDF转换为图片 -
zenghongqing:
您好,请教您一个问题://cell内容字符串总宽度 doub ...
Java POI Excel 行高自适应 -
xiang37:
http://xiva.iteye.com/blog/2066 ...
视频分割项目预研 -
I白I:
怎么还配置数据库了?
视频分割项目预研
接 视频分割项目预研
http://zhuyufufu.iteye.com/blog/2078404
对于没法用ffmpeg处理的rm等格式,使用了mplayer的mencoder来处理。
我的项目重点在视频分割。在此只写rmvb切分的代码。对于别的ffmpeg无法处理的格式,mencoder应该都能处理。
下面贴出暂时使用的视频处理工具类,有获取视频信息、截取视频、获取截图、加水印、视频转换等功能。
其原理都很简单:使用java调用外部组件对视频进行处理。
后面要添加的功能:解析组件输出流,生成视频处理进度及结果。
下面贴上代码,方便以后查阅
properties配置文件
http://zhuyufufu.iteye.com/blog/2078404
对于没法用ffmpeg处理的rm等格式,使用了mplayer的mencoder来处理。
我的项目重点在视频分割。在此只写rmvb切分的代码。对于别的ffmpeg无法处理的格式,mencoder应该都能处理。
下面贴出暂时使用的视频处理工具类,有获取视频信息、截取视频、获取截图、加水印、视频转换等功能。
其原理都很简单:使用java调用外部组件对视频进行处理。
后面要添加的功能:解析组件输出流,生成视频处理进度及结果。
下面贴上代码,方便以后查阅
properties配置文件
#视频切割配置参数 ffmpeg_home=D:/ffmpeg/ffmpeg-20140611-git-b2fb65c-win64-static/ ffmpeg=D:/ffmpeg/ffmpeg-20140611-git-b2fb65c-win64-static/bin/ffmpeg.exe mplayer=D:/ffmpeg/MPlayer-generic-r37220+gd4be3a8/mplayer.exe mencoder=D:/ffmpeg/MPlayer-generic-r37220+gd4be3a8/mencoder.exe
package com.zas.util; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; /** * 视频操作类 * @author zas * */ public class VideoUtil { static Logger logger = Logger.getLogger(VideoUtil.class); final static String FFMPEG = PropertyToolkits.getProperty("ffmpeg"); final static String MENCODER = PropertyToolkits.getProperty("mencoder"); final static String MPLAYER = PropertyToolkits.getProperty("mplayer"); /** * 获取一个指定视频的基本信息 * @param inputVideoFile * @return 视频信息 */ public static String getVideoInfo(String inputVideoFile){ //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("文件有误"); } List<String> commandList = new ArrayList<String>(); commandList.add(FFMPEG); commandList.add("-i"); commandList.add(inputVideoFile); // mplayer -identify $inputFileName -nosound -vc dummy -vo null // List<String> commandList = new ArrayList<String>(); // commandList.add(MPLAYER); // commandList.add("-identify"); // commandList.add(inputVideoFile); // commandList.add("-nosound"); // commandList.add("-vc"); // commandList.add("dummy"); // commandList.add("-vo"); // commandList.add("null"); //获取视频信息 String videoInfo = process(commandList); return videoInfo; } /** * 获取视频截图 * @param inputVideoFile 要处理的视频 * @param imgPath 要截取的截图 * @param parameterMap 参数 * @return */ public static String getVideoSnapshots(String inputVideoFile, String imgPath, Map<String, String> parameterMap){ //ffmpeg -i 1111.wma -y -ss 00:00:09 -t 00:00:10 -s 320*240 -f mjpeg -vframes 10 1111_1.jpg //获取图片的第一帧 ffmpeg commandLine: ffmpeg -y -i 1111.wma -vframes 1 -r 1 -ac 1 -ab 2 -s 320x240 -f image2 1111_1.jpg //把视频的前30帧转换成一个Animated Gif : //ffmpeg -i 1111.wma -vframes 30 -y -f gif 1111.gif //图片时间截取也很重要,很有可能是无效图片或者是黑屏 //建议 增加关键帧,通常第一帧为关键帧,可以使用:vframes:帧参数,舍弃微秒参数,只保留时间参数 //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("视频文件有误"); } /* -i filename 输入文件 -y 覆盖输出文件 -t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持 -ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持 */ List<String> commandList = new ArrayList<String>(); commandList.add(FFMPEG); commandList.add("-i"); commandList.add(inputVideoFile); commandList.add("-y"); //位置参数太靠后,会影响抓图效率 commandList.add("-ss"); commandList.add("00:00:09"); // commandList.add("-t"); // commandList.add("00:00:01"); commandList.add("-vframes"); commandList.add("1"); // commandList.add("-r"); // commandList.add("1"); // commandList.add("-ac"); // commandList.add("1"); // commandList.add("-ab"); // commandList.add("2"); // commandList.add("-s"); // commandList.add("320*240"); commandList.add("-f"); commandList.add("mjpeg"); commandList.add(imgPath); String processInfo = process(commandList); return processInfo; } /** * 使用ffmpeg 从指定时间开始截取特定时长视频 * @param fromTime 开始时间 00:5:28 * @param inputVideoFile 要截取的视频 * @param duration 要截取的视频时长 00:03:25 * @param outputFile 截取的视频的输出位置 * @param parameterMap 参数 * @return 处理信息 */ public static String cutting(String fromTime, String inputVideoFile, String duration, String outputFile, Map<String, String> parameterMap){ //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("视频文件有误"); } File file = new File(outputFile); if(file.exists()){ System.out.println("outputFile exists !"); return "outputFile exists!"; } String filetype = inputVideoFile.substring(inputVideoFile.lastIndexOf(".") + 1); if("rm".equalsIgnoreCase(filetype) || "rmvb".equalsIgnoreCase(filetype)){ return cuttingRmvb(fromTime, inputVideoFile, duration, outputFile, parameterMap); } //ffmpeg -ss 00:5:28 -i "1111.wmv" -acodec copy -vcodec copy -t 00:03:25 output.wmv //这行命令解释为:从文件 1111.wmv 第 5:28 分秒开始,截取 03: 25 的时间,其中视频和音频解码不变,输出文件名为 output.wmv 。 List<String> commandList = new ArrayList<String>(); commandList.add(FFMPEG); commandList.add("-ss"); commandList.add(fromTime); commandList.add("-i"); commandList.add(inputVideoFile); commandList.add("-acodec"); commandList.add("copy"); commandList.add("-vcodec"); commandList.add("copy"); commandList.add("-t"); commandList.add(duration); commandList.add(outputFile); String processInfo = process(commandList); return processInfo; } /** * 使用ffmpeg 从指定时间开始截取特定时长视频 * @param fromTime 开始时间 00:5:28 * @param inputVideoFile 要截取的视频 * @param duration 要截取的视频时长 00:03:25 * @param outputFile 截取的视频的输出位置 * @param parameterMap 参数 * @return 处理信息 */ public static String cuttingRmvb(String fromTime, String inputVideoFile, String duration, String outputFile, Map<String, String> parameterMap){ //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("视频文件有误"); } // mencoder basket.rm -ovc lavc -oac mp3lame -o basket.avi -ss 5:00 -endpos 8:00 List<String> commandList = new ArrayList<String>(); commandList.add(MENCODER); commandList.add(inputVideoFile); commandList.add("-ovc"); commandList.add("lavc"); commandList.add("-oac"); commandList.add("mp3lame"); commandList.add("-ss"); commandList.add(fromTime); commandList.add("-endpos"); commandList.add(duration); commandList.add("-o"); commandList.add(outputFile); String processInfo = process(commandList); return processInfo; } /** * 视频转换 * @param inputVideoFile 视频文件 * @param outputFile 转换后的视频文件 * @param parameterMap 其余参数 * @return */ public static String videoConverter(String inputVideoFile, String outputFile, Map<String, String> parameterMap){ //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("视频文件有误"); } //视频的格式有很多,以mp4和flv为例子 // ffmpeg -i test.mp4 -ab 56 -ar 22050 -qmin 2 -qmax 16 -b 320k -r 15 -s 320x240 outputfile.flv //mp4 转 flv // ffmpeg -i outputfile.flv -copyts -strict -2 test.mp4 //flv 转 mp4 List<String> commandList = new ArrayList<String>(); commandList.add(FFMPEG); commandList.add("-y"); commandList.add("-i"); commandList.add(inputVideoFile); commandList.add("-ab"); commandList.add("5600000"); commandList.add("-ar"); commandList.add("22050"); commandList.add("-b"); commandList.add("500"); commandList.add("-s"); commandList.add("320*240"); commandList.add(outputFile); String processInfo = process(commandList); return processInfo; } /** * 视频加水印 * @param inputVideoFile 要处理的视频文件 * @param outputFile 输出的视频文件 * @param parameterMap 参数 * @return */ public static String addWatermark(String inputVideoFile, String outputFile, Map<String, String> parameterMap){ //检查是否能够处理 if(!checkVideoFile(inputVideoFile)){ throw new RuntimeException("视频文件有误"); } //http://blog.51yip.com/linux/1584.html //#ffmpeg -y -i test.mp4 -acodec copy -vf "movie=logo.jpg [logo]; [in][logo] overlay=10:10:1 [out]" test2.mp4 //overlay=10:10:1,后三个数据表示是距离左边的距离,距离上边的距离,是否透明,1表示透明。上例我用的是jpg,当然不可能透明。 //# ffmpeg -y -i test.mp4 -acodec copy -vf "movie=uwsgi.jpg [logo]; [in][logo] overlay=enable='lte(t,1)' [out]" test2.mp4 //overlay=enable='lte(t,1)' ,这个参数表示,水印在前一秒显示。 //ffmpeg -y -i D:/ffmpeg/video/w.mkv -acodec copy -t 00:01:10 -vf "movie=logo.png [logo]; [in][logo] overlay=10:10:1 [out]" D:/ffmpeg/video/w_logo.mkv List<String> commandList = new ArrayList<String>(); commandList.add(FFMPEG); commandList.add("-i"); commandList.add(inputVideoFile); commandList.add("-y"); commandList.add("-acodec"); commandList.add("copy"); commandList.add("-vf"); commandList.add("\"movie=logo.png [logo]; [in][logo] overlay=10:10:1 [out]\""); commandList.add(outputFile); // // String command = FFMPEG + " -y -i \"D:/ffmpeg/video/a b/w.mkv\" -acodec copy -t 00:01:10 -vf \"movie=logo.png [logo]; [in][logo] overlay=10:10:1 [out]\" D:/ffmpeg/video/w_logo.mkv"; // String processInfo = exec(command); String processInfo = process(commandList); return processInfo; } /** * 命令执行 * @param command * @return */ public static String exec(String command) { long beginTime = System.nanoTime(); Runtime rt = Runtime.getRuntime(); try { Process process = rt.exec(command); /* StringTokenizer st = new StringTokenizer(command); String[] cmd = new String[st.countTokens()]; for (int i = 0; st.hasMoreTokens(); i++){ cmd[i] = st.nextToken(); System.out.println(cmd[i]); } cmd[0] = new File(cmd[0]).getPath(); StringBuilder cmdbuf = new StringBuilder(80); for (int i = 0; i < cmd.length; i++) { if (i > 0) { cmdbuf.append(' '); } String s = cmd[i]; if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) { if (s.charAt(0) != '"') { cmdbuf.append('"'); cmdbuf.append(s); if (s.endsWith("\\")) { cmdbuf.append("\\"); } cmdbuf.append('"'); } else if (s.endsWith("\"")) { The argument has already been quoted. cmdbuf.append(s); } else { Unmatched quote for the argument. throw new IllegalArgumentException(); } } else { cmdbuf.append(s); } } String cmdstr = cmdbuf.toString(); System.out.println("cmdstr : " + cmdstr);*/ final InputStream isNormal = process.getInputStream(); new Thread(new Runnable() { public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(isNormal)); StringBuilder buf = new StringBuilder(); String line = null; try { while((line = br.readLine()) != null){ buf.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } System.out.println("输出结果为:" + buf); } }).start(); // 启动单独的线程来清空process.getInputStream()的缓冲区 InputStream isError = process.getErrorStream(); BufferedReader br2 = new BufferedReader(new InputStreamReader(isError)); StringBuilder buf = new StringBuilder(); String line = null; while((line = br2.readLine()) != null){ buf.append(line + "\n"); } System.out.println("错误输出结果为:" + buf); try { process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } long endTime = System.nanoTime(); System.out.println("视频处理耗时: " + (endTime - beginTime) / 1000000 + " 毫秒 "); return null; } /** * 根据命令处理视频 * @param commandList * @param processInfo * @return 处理信息 */ private static String process(List<String> commandList) { StringBuffer processInfo = new StringBuffer(); ProcessBuilder builder = new ProcessBuilder(); builder.command(commandList); builder.redirectErrorStream(true); long beginTime = System.nanoTime(); try { Process p = builder.start(); //保存ffmpeg的输出结果流 BufferedReader buf = null; buf = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = null; while ((line = buf.readLine()) != null) { System.out.println(line); processInfo.append(line + "\n"); } p.waitFor();// 这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行 } catch (IOException e) { e.printStackTrace(); logger.error(e); throw new RuntimeException("视频处理出错"); } catch (InterruptedException e) { e.printStackTrace(); logger.error(e); throw new RuntimeException("视频处理出错"); } long endTime = System.nanoTime(); System.out.println("处理耗时: " + (endTime - beginTime) / 1000000 + " 毫秒。 "); System.out.println("视频处理结果信息: \n" + processInfo); return processInfo.toString(); } /** * 检测视频是否能够被处理 * @param videoPath * @return */ private static boolean checkVideoFile(String videoPath) { if(null == videoPath){ return false; } //根据后缀做类型检测 //检查是否文件以及文件是否存在 File videoFile = new File(videoPath); if(!videoFile.isFile() || !videoFile.exists()){ return false; } return true; } public static void main(String[] args) { // String inputVideoFile = "D:/ffmpeg/video/【天下足球网www.txzqw.com】下半场.rmvb"; String outputFile = "D:/ffmpeg/video/【天下足球网www.txzqw.com】下半场_1.rmvb"; String inputVideoFile = "D:/ffmpeg/video/a b/w.mkv"; // String outputFile = "D:/ffmpeg/video/w_1.mkv"; // String inputVideoFile = "D:/ffmpeg/video/Wildlife.wmv"; // String outputFile = "D:/ffmpeg/video/Wildlife.wmv.flv"; String fromTime = "00:00:00"; String duration = "00:3:28"; VideoUtil.getVideoInfo(inputVideoFile); // VideoUtil.cuttingRmvb(fromTime, inputVideoFile, duration, outputFile, null); // String imgPath = "D:/ffmpeg/video/1111.jpg"; // VideoUtil.getVideoSnapshots(inputVideoFile, imgPath, null); // VideoUtil.addWatermark(inputVideoFile, outputFile, null); // VideoUtil.videoConverter(inputVideoFile, outputFile, null); // VideoUtil.getVideoInfo(inputVideoFile); } }
发表评论
-
Java数组删除指定元素
2014-09-18 11:30 2206package com.zas.util; impo ... -
linux 干掉所有java进程
2014-08-07 12:31 992ps -ef|grep java|grep -v grep|c ... -
Oracle自带连接池使用(转载收录)
2014-07-31 10:01 1363最近在搞数据迁移:从sql server 迁数据到oracle ... -
html dom jsoup httpclient
2014-07-10 21:45 1051xml dom 对大多数java程序员来说并不陌生,但是htm ... -
Java 对象存储到oracle Blob字段
2014-07-08 14:52 1058Java 数据对象在没有持久存储到业务表时,可能需要临时存 ... -
Java 科学计数法数字转字符串
2014-07-08 14:30 1428科学计数法数字转字符串,记录代码,留后使用 double ... -
突破tomcat jsp编译65535行的限制
2014-07-04 17:16 4675使用tomcat时有可能会遇到其对jsp编译行数的限制, ... -
视频分割项目预研
2014-06-11 16:12 2161由于工作需要,研究下视频切割。 现在的情况:视频切割是重中之 ... -
Java POI Excel 行高自适应
2014-03-28 14:08 15598在Excel处理的过程中,可能有需要用到行高自适应的时候。 ... -
Java POI Excel sheet 合并遇到的问题解决2
2014-03-25 18:03 3171上接 Java POI Excel sheet 合并 http ... -
文档展示:使用iText转换各种图片为PDF
2014-03-23 12:38 2847如题: 下面这段代码可以处理各种格式的图片,代码的出处忘记了 ... -
Java 进程执行外部程序,造成外部程序阻塞的一种原因
2014-03-23 12:06 1424前一阵子在研究文档展示时使用了java进程直接调用外部程序 ... -
Java POI Excel sheet 合并遇到的问题解决
2014-03-23 11:30 5017上接 Java POI Excel sheet http:// ... -
Java POI Excel sheet合并
2014-03-19 10:59 6562由于工作上的需要,特地研究了下Excel合并的问题,现贴出来, ... -
文档展示:IcePDF 将PDF转换为图片
2014-02-11 16:35 4874上接 文档展示:PDFRender 将PDF转换为图片 htt ... -
文档展示:PDFRender 将PDF转换为图片 多线程处理 提高效率
2014-02-10 12:04 3219上接 文档展示:PDFRender 将PDF转换为图片 htt ... -
文档展示:使用POI转换DOC为HTML
2014-02-10 10:42 1733上接 文档展示:使用OpenOffice转换文档为HTML h ... -
文档展示:使用OpenOffice转换文档为HTML
2014-02-08 17:53 2576上接 文档展示:使用OpenOffice转换文档为PDF ... -
文档展示:PDFRender 将PDF转换为图片
2014-02-08 10:13 2135上接 文档展示:PDFBox 将PDF转换为图片 http:/ ... -
文档展示:使用OpenOffice转换文档为PDF
2014-01-27 11:37 1698上接 文档展示 http://zhuyufufu.iteye. ...
相关推荐
摄像头操作的基本类。 对摄像头摄像及保存视频,压缩视频 希望对需要摄像头视频压缩的朋友有帮助。 缺点是压缩速度太慢, 不知哪位大虾有没有好的办法分享一下。
c#+库文件XML操作类时间操作类视频转换类文件操作类FTP操作类弹出信息类等库文件
FTP操作类、导出Excel、配置文件操作类、 文件操作类、弹出消息类、XML操作类、 弹出消息类、分词辅助类、时间操作类、 汉字转拼音、压缩解压缩、条形码、 正则表达式、日历、上传下载、 视频转换类、随机数类、条形...
汉字转拼音、日历、上传下载、时间操作类、视频转换类 包含上述五个类源码
AVI操作类,图片转AVI格式的视频,具体查看 http://www.cnblogs.com/qc-id-01/p/7494757.html 博客内的内容均为转载,工具类为跨网下载
计算机前端-核心编程.视频03单例的数据库操作类.avi
Excel操作类;FTP操作类;Html操作类;IP辅助类;JSON操作;JS操作;URL的操作类;XML操作类;处理多媒体的公共类;弹出消息类;二维码操作类;汉字转拼音;加密解密;科学计数,数学;类型转换;配置文件操作类;上传下载;时间操作...
winform第三章封装数据库操作类(无视频). sql 2005 c#
该代码中含有C# 视频转换所使用的的基础操作类,可直接使用
封装数据库操作类(有视频)自己用的希望对初学者有帮助 ,我自己也是在学习,这是很常用的封装。
Jquery相关、jQuery.cookie帮助类、访问系统相关、C#基础类库(Chart图形、CSV文件转换、FTP操作类、加密/解密帮助类、FTP操作类、JS操作类、...操作类、视频转换类、条形码、文件操作类、验证码)等等还有好多就没写了
1.FME常用转换器之字符串操作类视频讲解,讲解如何使用FME对字符串文件进行操作处理。 2.本视频讲解中使用的FME版本为2020.2中文版。 3.本资源仅为视频讲解,用户需自行安装相应版本的FME。
java视频教程 Java文件操作 JavaFile
10. Excel操作类 11. FTP操作类 12. H5-微信 13. Html操作类 14. INI文件读写类 15. IP辅助类 16. Javascript 17. Json 18. JSON操作 19. JS操作 20. Lib 21. Mime 22. Net 23. NPOI 24. obj 25. ...
视频的裁剪,合并2个操作, 支持MP4,mov,等手机格式
Cache、CSV文件转换、DEncrypt、FTP操作类、JS、Json、Mime、PDF、Properties、ResourceManager、XML操作类、弹出消息类、导出Excel、分词辅助类、汉字转拼音、配置文件操作类、日历、上传下载、时间操作类、视频...
准确,高效的业务流识别与分类是保障多媒体通信端到端QoS(Quality of Service),执行相关网络操作的前提。如今数据规模的剧烈增加为业务流的分类提出了挑战,而特征选择能够尽可能地减少特征维数,去除冗余特征,...
Chart图形、Cookie&Session&Cache、CSV文件转换、DEncrypt、FTP操作类、JS...操作类、视频转换类、随机数类、条形码、图片、网络、文件操作类、序列化、压缩解压缩、验证码、页面辅助类、邮件、邮件2、正则表达式、字符...
今天整理电脑资料的之后,发现了平时开发写的小例子,现在整理出来大家分享给大家,大致包含如下资源压缩解压缩、正则表达式、序列化、文件操作类、条形码帮助类、视频转换帮助类、二维码操作类、RDLC打印帮助类、AD...
、CSV文件转换、DEncrypt、FTP操作类、JS、Json、Mime、PDF、Properties、ResourceManager、XML操作类、弹出消息类、导出Excel、分词辅助类、汉字转拼音、配置文件操作类、日历、上传下载、时间操作类、视频转换类、...