-
前端用H5的Video标签做了播放器,部分mp4文件上传成功后只有声音而没有画面,经过了解之后才知道此标签只支持编码为H264的MP4文件,不支持编码为MPEG4的MP4文件,想成功播放必须要转码。于是就去网上找啊找,刚开始全是格式化工厂转,但是我要的是可以用代码实现的。。。但最后找到一种折中的方法,就是拿ffmpeg工具结合代码来完成转码。
- 当然了,首先得检测该MP4的编码是哪种类型,如果是H264,那就不用转了直接上传就好了,否则就需要转码。这是检测的代码。(ps:因为用的是maven项目,而中央仓库找不到这个依赖,还得手动打包到本地仓库。。。这是jar包地址,下1.0.2版本的。)
http://www.sauronsoftware.it/projects/jave/download.php
Encoder encoder = new Encoder();
File target1 = new File(path);
MultimediaInfo info3 = encoder.getInfo(target1);
System.out.println(info3);
**输出结果如下:**
it.sauronsoftware.jave.MultimediaInfo (format=mov, duration=115200, video=it.sauronsoftware.jave.VideoInfo (decoder=h264, size=it.sauronsoftware.jave.VideoSize (width=1280, height=720), bitRate=-1, frameRate=25.0), audio=it.sauronsoftware.jave.AudioInfo (decoder=mpeg4aac, samplingRate=44100, channels=2, bitRate=-1))
- 其中video是视频信息,audio则是音频信息,duration是视频长度。。。其他参数不一一说明了。。。最重要的是decoder这个参数,如果是h264那么恭喜你不用转码,但如果是mpeg4那么就只能转码了!
- 要转码就必须要有ffmpeg工具,也算是千辛万苦最后在csdn花了金币下载了一个,直接贴代码:
public static boolean changeVCodec(String inputFile, String outputFile) {
List<String> command= new ArrayList<String>();
command.add("ffmpeg工具的本地路径");
command.add("-i");
command.add(inputFile);// 要转的文件路径
command.add("-vcodec");
command.add("h264"); // 设置自己想要的视频编码信息
command.add("-acodec");
command.add("copy");// 因为对音频没改变需求,所以直接copy
command.add("-f");
command.add("mov");
command.add("-y");
command.add(outputFile); // 转码之后的文件路径
StringBuffer test = new StringBuffer();
for (int i = 0; i < command.size(); i++) {
test.append(command.get(i) + " ");
}
log.info("转换编码和接收文件的信息:" + test);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(command);
builder.start();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
changeVCodec(source,target);
}
- 这样在windows上就转码成功了,是通过 "ProcessBuilder "这个类来操作系统进程;当然在linux上还没试验,不出意外是没有问题的!
最后原MPEG4的MP4文件通过转码之后也能成功播放了! - 如果哪位老哥老姐有更好的方法,还请指导!
今天再次测试时碰到个问题,就是用项目实现转码如果不做流的处理,那么需要等的时间非常长,一个2分钟的视频足足等了25分钟。25分钟够好多男士来好几发了。。。后来想到把输入和错误流给读出来,结果同一个2分钟的视频虽然也要等,但只等了35秒,还能接收
InputStream inputStream = null;
InputStream errorStream = null;
try {
Process p = Runtime.getRuntime().exec(command.toArray(new String[command.size()]));
inputStream = p.getInputStream();
errorStream = p.getErrorStream();
BufferedReader inputBr = new BufferedReader(new InputStreamReader(inputStream));
BufferedReader errorBr = new BufferedReader(new InputStreamReader(errorStream));
new Thread(){
public void run(){
String inputLine = null;
StringBuffer inputBuffer = new StringBuffer();
try {
while ((inputLine = inputBr.readLine()) != null){
inputBuffer.append(inputLine);
}
log.info("转码文件的输入流" + inputBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != inputBr){
try {
inputBr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}.start();
//
new Thread(){
public void run(){
String errorLine = null;
StringBuffer errorBuffer = new StringBuffer();
try {
while ((errorLine = errorBr.readLine()) != null){
errorBuffer.append(errorLine);
}
log.info("转码文件的错误流:" + errorBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null != errorBr){
try {
errorBr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}.start();
flag = true;
} catch (Exception e) {
throw new CommunityException("转换MP4编码失败");
}finally {
if(null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != errorStream){
try {
errorStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return flag;