`
josico
  • 浏览: 43116 次
社区版块
存档分类
最新评论

java实现视频文件转换为flv(带文件缩略图)

    博客分类:
  • java
阅读更多

通过java代码,调用底层工具,实现视频格式转换

 

原理是这样的:

ffmpeg可以转换大多数视频文件,如:avi|wmv|mkv|asx|swf|asf|vob|mpg|mp4|mov|flv等

但有些视频格式,ffmpeg无法转,比如:rm,rmvb等

所以遇到ffmpeg不能转的视频格式时,需要调用另一个工具mencoder,利用mencoder将那些文件转成ffmpeg能够转换的格式。基本通过这2个工具可以转换大多数视频文件

 

必备组件有

  • ffmpeg.exe
  • mencoder.exe
  • pthreadGC2.dll

pthreadGC2.dll需要放到system32目录下

 

全部文件下载地址

http://115.com/file/anrac8ke

 

下载下来的压缩包除了有上述组件外,还有5个文件夹

  • ConvertVideo
  • img
  • input
  • system
  • output

具体解释

  1. ConvertVideo是工程文件,在myeclipse9.0下编写完成,可直接导入
  2. img文件夹是装生成的视频文件缩略图的
  3. input文件夹里面放你需要转的视频源文件
  4. system文件是一个中转站,对于ffmpeg不能转的文件,mencoder会将其转成ffmpeg所认识的avi文件,并放置在system文件夹中。当ffmpeg将system文件夹中的avi文件转成flv后,system文件夹自动清空
  5. output文件夹则是存放转好了的flv视频文件

这里有一片CSDN的文章 ,写得很好,推荐给大件看看。具体就是看一些ffmpeg和mencoder的参数详解,这样让你之后的修改,也有的放失

http://blog.csdn.net/hemingwang0902/article/details/4382342

 

 

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

class ConvertVideo {

	private List<String> pathRight = new ArrayList<String>();// 经处理后,得到的有效地址
	private List<String> path1 = new ArrayList<String>();// ffmpeg能处理的文件的地址集
	private List<String> path2 = new ArrayList<String>();// ffmpeg不能处理的文件的地址集
	public static int fileNum = 0;// 所有经过验证合法,并需要转换的视频数量

	public static void main(String[] args) {
		Date start = new Date();
		ConvertVideo conver = new ConvertVideo();
		String fileFolder = "e:\\input";
		List<String> listFile = conver.getFilesInPath(fileFolder);
		List<String> listVideo = conver.filter(listFile);
		int fileNumMax = listVideo.size(); // 所有视频数量
		conver.checkfile(listVideo);
		conver.process();

		if (fileNum == fileNumMax) {
			Date end = new Date();
			System.out.println("耗时:" + (end.getTime() - start.getTime()) / 1000
					+ "秒");
		}
	}

	/**
	 * 过滤avi|wmv|rmvb|rm|asx|asf|mpg|3gp|mp4|mov|flv)$格式的视频
	 */
	private List<String> filter(List<String> list) {
		List<String> fileList = new ArrayList<String>();
		for (String str : list) {
			if (str.matches(".+\\.(avi|wmv|rmvb|rm|asx|mkv|asf|mpg|swf|3gp|mp4|mov|vob|flv)$")) {
				fileList.add(str);
			}
		}
		return fileList;
	}

	/**
	 * 
	 * 获取e:\\input下所有文件路径
	 */
	public List<String> getFilesInPath(String path) {
		List<String> fileList = new ArrayList<String>();

		if (path == null || "".equals(path))
			return fileList;

		File file = new File(path);

		if (!file.exists()) {
			return fileList;
		}

		File[] childFiles = file.listFiles();

		try {
			for (int i = 0; i < childFiles.length; i++) {
				String filePath = childFiles[i].getAbsolutePath();
				if (childFiles[i].isDirectory()) {
					fileList.addAll(getFilesInPath(filePath));
				} else {
					fileList.add(filePath);
				}
			}
		} catch (Exception e) {
			return fileList;
		}

		return fileList;
	}

	/**
	 * 
	 * 避免文件重名,在文件尾部加唯一标识,主要是以获取当前时间,以字符串格式hhmmssSSSSSS
	 */
	public String transform(Date date) {
		SimpleDateFormat sdFormat = new SimpleDateFormat("hhmmssSSSSSS");
		String myTime = sdFormat.format(date);
		return myTime;
	}

	/**
	 * 核心处理函数
	 */
	public void process() {
		checkContentType(pathRight);
		pathRight.clear();
		if (path1.size() > 0) { // 地址集中的文件全部是ffmpeg所能解析的文件
			processFLV(path1); // 直接将文件转为flv文件
		}
		if (path2.size() > 0) {
			processAVI(path2); // 得到ffmpeg不能解析的文件所转换成avi文件的地址集
		}
	}

	/**
	 * 将传过来的地址集分类,ffmpeg能解析的分到path1中,ffmpeg不能解析的分到path2中
	 */
	public void checkContentType(List<String> list) {
		for (String str : list) {
			if (str.matches(".+\\.(avi|wmv|mkv|asx|swf|asf|vob|mpg|mp4|mov|flv)$")) {
				path1.add(str);
			} else {
				path2.add(str);
			}
		}
	}

	/**
	 * . 处理用户传递过来的地址集 有效的放到pathRight中 无效的放到pathWrong中
	 */
	public void checkfile(List<String> path) {
		for (int i = 0; i < path.size(); i++) {
			File file = new File((String) path.get(i));
			if (file.isFile()) {
				pathRight.add(path.get(i));
			}
		}
	}

	/**
	 * 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
	 */
	public void processAVI(List<String> list) {
		List<String> finish = new ArrayList<String>();
		for (String str : list) {
			List<String> commend = new java.util.ArrayList<String>();
			commend.add("\"e:\\mencoder\"");
			commend.add("\"" + str + "\"");
			commend.add("-oac");
			commend.add("mp3lame");
			commend.add("-lameopts");
			commend.add("preset=64");
			commend.add("-ovc");
			commend.add("xvid");
			commend.add("-xvidencopts");
			commend.add("bitrate=600");
			commend.add("-of");
			commend.add("avi");
			commend.add("-o");
			String file = str.substring(str.lastIndexOf("\\") + 1,
					str.lastIndexOf("."));
			file = (file + transform(new Date())).trim();
			commend.add("\"e:\\System\\" + file + ".avi\""); // 最后输出出来的avi,尽量不要出现二义性,否则会覆盖掉原有的视频
			try {
				ProcessBuilder builder = new ProcessBuilder();
				builder.command(commend);
				Process p = builder.start();
				int exitValue = doWaitFor(p);
				if (exitValue != -1) {
					processFLV1("e:\\System\\" + file + ".avi");
				}
			} catch (Exception e) {
				// e.printStackTrace();
				System.out.println("********avi转换出错********");
			}
			finish.add(str);
		}
		path2.removeAll(finish);
	}

	/**
	 * ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
	 */
	public boolean processFLV1(String str) {

		List<String> commend = new java.util.ArrayList<String>();
		commend.add("\"e:\\ffmpeg\"");
		commend.add("-i");
		commend.add("\"" + str + "\"");
		commend.add("-ab");
		commend.add("64");
		commend.add("-ac");
		commend.add("2");
		commend.add("-ar");
		commend.add("22050");
		commend.add("-b");
		commend.add("230");
		commend.add("-r");
		commend.add("29.97");
		commend.add("-y");
		String file = str.substring(str.lastIndexOf("\\") + 1,
				str.lastIndexOf("."));
		String fileName = "e:\\output\\" + file + ".flv";
		commend.add("\"" + fileName + "\"");
		try {
			ProcessBuilder builder = new ProcessBuilder();
			builder.command(commend);
			Process p = builder.start();
			int exitValue = doWaitFor(p);
			if (exitValue != -1) {
				fileNum++;
			}
			processImg(fileName);
		} catch (Exception e) {
			System.out.println("*********转换为FLV格式出错*********");
			// e.printStackTrace();
			return false;
		}
		deleteFile(str);
		return true;
	}

	public void processFLV(List<String> list) {
		List<String> finish = new ArrayList<String>();
		for (String str : list) {
			List<String> commend = new java.util.ArrayList<String>();
			commend.add("\"e:\\ffmpeg\"");
			commend.add("-i");
			commend.add("\"" + str + "\"");
			commend.add("-ab");
			commend.add("64");
			commend.add("-ac");
			commend.add("2");
			commend.add("-ar");
			commend.add("22050");
			commend.add("-b");
			commend.add("230");
			commend.add("-r");
			commend.add("29.97");
			commend.add("-y");
			String file = str.substring(str.lastIndexOf("\\") + 1,
					str.lastIndexOf("."));
			String fileName = "e:\\output\\" + file + transform(new Date())
					+ ".flv";
			commend.add("\"" + fileName + "\"");
			try {
				ProcessBuilder builder = new ProcessBuilder();
				builder.command(commend);
				Process p = builder.start();
				int exitValue = doWaitFor(p);
				if (exitValue != -1) {
					fileNum++;
					processImg(fileName);
				}
			} catch (Exception e) {
				// System.out.println("*********转换为FLV格式出错*********");
				e.printStackTrace();
			}
			finish.add(str);
		}
		path1.removeAll(finish);
	}

	/**
	 * 生成图片 参数String newfilename, String newimg
	 */
	public boolean processImg(String str) {
		List<String> commend = new java.util.ArrayList<String>();
		commend.add("\"e:\\ffmpeg\"");
		commend.add("-i");
		commend.add("\"" + str + "\"");
		commend.add("-y");
		commend.add("-f");
		commend.add("image2");
		commend.add("-ss");
		commend.add("5");
		commend.add("-t");
		commend.add("0.001");
		commend.add("-s");
		commend.add("320x240");
		commend.add("\"e:\\img\\"
				+ str.substring(10, str.lastIndexOf(".")) + ".jpg\"");
		try {
			ProcessBuilder builder = new ProcessBuilder();
			builder.command(commend);
			builder.start();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public void deleteFile(String str) {
		File file = new File(str);
		file.delete();
	}

	/**
	 * ffmpeg不能转换的格式要先转换成avi的格式,才转化为flv格式,doWaitFor方法保证,原视频完全转化为avi后,
	 * 才转化成flv,避免avi,flv同时转换出错
	 */
	public int doWaitFor(Process p)

	{
		InputStream in = null;
		InputStream err = null;
		int exitValue = -1; // returned to caller when p is finished
		try {
			System.out.println("comeing");
			in = p.getInputStream();
			err = p.getErrorStream();
			boolean finished = false; // Set to true when p is finished

			while (!finished) {
				try {
					while (in.available() > 0) {
						// Print the output of our system call
						Character c = new Character((char) in.read());
						System.out.print(c);
					}
					while (err.available() > 0) {
						// Print the output of our system call
						Character c = new Character((char) err.read());
						System.out.print(c);
					}

					// Ask the process for its exitValue. If the process
					// is not finished, an IllegalThreadStateException
					// is thrown. If it is finished, we fall through and
					// the variable finished is set to true.
					exitValue = p.exitValue();
					finished = true;

				} catch (IllegalThreadStateException e) {
					// Process is not finished yet;
					// Sleep a little to save on CPU cycles
					Thread.currentThread().sleep(500);
				}
			}
		} catch (Exception e) {
			// unexpected exception! print it out for debugging...
			System.err.println("doWaitFor();: unexpected exception - "
					+ e.getMessage());
		} finally {
			try {
				if (in != null) {
					in.close();
				}

			} catch (IOException e) {
				System.out.println(e.getMessage());
			}
			if (err != null) {
				try {
					err.close();
				} catch (IOException e) {
					System.out.println(e.getMessage());
				}
			}
		}
		// return completion status to caller
		return exitValue;
	}

}

 

分享到:
评论
5 楼 ren2881971 2012-12-27  
josico 写道
ren2881971 写道
josico 写道
ren2881971 写道
MARK. 工作刚好用到! 代码很漂亮!

八客气

但是哥们,为什么我不能在转换格式完之后同时转换缩略图呢。
好像是cmd命令不能连续执行的原因? 具体我不太清楚。 后来我放弃用缩略图了。。就是列表页。 点击播放。。

缩略图 我也只是把思路做出来了  因为后面放弃了 也就没有深究
我是根据时间来取缩略图的  必须5:00截个图 13:00截个图什么的 
但有的视频不到5分钟 这样就截不出来
如果 只截10秒钟之内的随机图 那也不好 因为 很多视频 特别是游戏视频 刚开始一段时间都是一样的 
后来准备该方案 那就没后文了  因为我辞职了

哈哈 。 才看到您的回复。
好像不能在转换完之后在执行截图的操作。 只能单独转换或者单独截图~
4 楼 josico 2012-12-24  
ren2881971 写道
josico 写道
ren2881971 写道
MARK. 工作刚好用到! 代码很漂亮!

八客气

但是哥们,为什么我不能在转换格式完之后同时转换缩略图呢。
好像是cmd命令不能连续执行的原因? 具体我不太清楚。 后来我放弃用缩略图了。。就是列表页。 点击播放。。

缩略图 我也只是把思路做出来了  因为后面放弃了 也就没有深究
我是根据时间来取缩略图的  必须5:00截个图 13:00截个图什么的 
但有的视频不到5分钟 这样就截不出来
如果 只截10秒钟之内的随机图 那也不好 因为 很多视频 特别是游戏视频 刚开始一段时间都是一样的 
后来准备该方案 那就没后文了  因为我辞职了
3 楼 ren2881971 2012-12-21  
josico 写道
ren2881971 写道
MARK. 工作刚好用到! 代码很漂亮!

八客气

但是哥们,为什么我不能在转换格式完之后同时转换缩略图呢。
好像是cmd命令不能连续执行的原因? 具体我不太清楚。 后来我放弃用缩略图了。。就是列表页。 点击播放。。
2 楼 josico 2012-12-21  
ren2881971 写道
MARK. 工作刚好用到! 代码很漂亮!

八客气
1 楼 ren2881971 2012-12-19  
MARK. 工作刚好用到! 代码很漂亮!

相关推荐

Global site tag (gtag.js) - Google Analytics