文档章节

java使用ffmpeg和mencoder做视频格式转换

祁达方
 祁达方
发布于 2015/08/20 16:19
字数 1113
阅读 1957
收藏 4
点赞 0
评论 0

首发:个人博客,持续更新和纠错

主要使用技术:
1)FFmpeg,用于主流格式之间的转换,例如AVI,MP4,FLV等。
2)MEncoder,用于奇葩格式转主流格式,例如RMVB转AVI。这样我们可以把奇葩格式先转AVI,再由FFmpeg把AVI转成想要的格式。
3)java的执行命令行操作的技术,这样安装在服务器上的↑这两个转换器就可以被java调用了。
包括ProcessBuilder和Runtime这两种调法。
可以参考这篇


FFmpeg的官网在这里,其文档在这里
MEncoder的官网在这里,其中文文档在这里

主要参考:这篇文章,使用的FFmpeg和MEncoder也直接用的这篇文章后面提供的压缩包。
但正如有的网友指出的,这篇文章中代码的硬伤在于,当rmvb->avi->flv这样两步转换的时候,需要等待前一步完成,再进行后一步。
所以改了改代码,如下:

package test;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;

public class Test {
    
    public static final String BASEPATH = "d:\\ftest\\";

    public static void main(String[] args) {
        String fromFilePath1 = BASEPATH + "from\\test.mp4";
        doConvert(fromFilePath1, "flv");
        
        String fromFilePath2 = BASEPATH + "from\\test.rmvb";
        doConvert(fromFilePath2, "flv");
    }

    /**
     * 尝试进行转换
     */
    public static void doConvert(String fromFilePath, String goalType){
        if (!checkInput(fromFilePath)) {
            System.out.println("文件" + fromFilePath + "不存在");
        }else{
            if (process(fromFilePath, goalType)) {
                System.out.println("转换成功");
            }else{
                System.out.println("转换失败");
            }
        }
    }

    /**
     * 进行转换
     * @return
     */
    private static boolean process(String fromFilePath, String goalType) {
        int type = checkContentType(fromFilePath);
        boolean status = false;
        if (type == 0) {
            status = getResult(fromFilePath, goalType);
        } else if (type == 1) {
            String avifilepath = getPreResult(type, fromFilePath);
            if (avifilepath == null){
                return false;
            }
            status = getResult(avifilepath, goalType);
        }
        return status;
    }

    /**
     * 判断源视频的种类(主流格式 or 奇葩格式)
     */
    private static int checkContentType(String fromFilePath) {
        String type = fromFilePath.substring(fromFilePath.lastIndexOf(".") + 1, fromFilePath.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 0;
        } 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等),
        // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
        else if (type.equals("wmv9")) {
            return 1;
        } else if (type.equals("rm")) {
            return 1;
        } else if (type.equals("rmvb")) {
            return 1;
        }
        return 9;
    }

    /**
     * 检查指定的输入文件是否存在
     */
    private static boolean checkInput(String path) {
        File file = new File(path);
        if (!file.isFile()) {
            return false;
        }
        return true;
    }

    /**
     * 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
     */
    private static String getPreResult(int type, String fromFilePath) {
        String fileName = UUID.randomUUID().toString() + ".avi";
        
        //预处理指令
        List<String> commend = new ArrayList<String>();
        commend.add(BASEPATH + "util\\mencoder");
        commend.add(fromFilePath);
        //commend.add("-oac lavc");
        commend.add("-oac");
        commend.add("mp3lame");
        commend.add("-lameopts");
        commend.add("preset=64");
        commend.add("-lavcopts");
        commend.add("acodec=mp3:abitrate=64");
        commend.add("-ovc");
        commend.add("xvid");
        commend.add("-xvidencopts");
        commend.add("bitrate=600");
        commend.add("-of");
        commend.add("avi");
        commend.add("-o");
        commend.add(BASEPATH + "pre\\" + fileName);
        
        try {
            //预处理进程
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            builder.redirectErrorStream(true);

            //进程信息输出到控制台
            Process p = builder.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            while((line = br.readLine()) != null){
                System.out.println(line);
            }
            p.waitFor();//直到上面的命令执行完,才向下执行
            
            return BASEPATH + "pre\\" + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
     * @param oldfilepath
     * @param goalType
     * @return
     */
    private static boolean getResult(String oldfilepath, String goalType) {
        String fileName = UUID.randomUUID() + "." + goalType;
        
        if (!checkInput(oldfilepath)) {
            System.out.println(oldfilepath + "不存在");
            return false;
        }
        
        // 文件命名
        Calendar c = Calendar.getInstance();
        
        //转换格式命令
        List<String> commend = new ArrayList<String>();
        commend.add(BASEPATH + "util\\ffmpeg");
        commend.add("-i");
        commend.add(oldfilepath);
        commend.add("-ab");
        commend.add("56");
        commend.add("-ar");
        commend.add("22050");
        commend.add("-qscale");
        commend.add("8");
        commend.add("-r");
        commend.add("15");
        commend.add("-y");
        commend.add("-s");
        commend.add("600x500");
        commend.add(BASEPATH + "to\\" + fileName);

        try {
            Runtime runtime = Runtime.getRuntime();
            //截图命令
            String cut = BASEPATH + "util\\ffmpeg.exe   -i   "
                    + oldfilepath
                    + "   -y   -f   image2   -ss   8   -t   0.001   -s   600x500   " + BASEPATH + "\\to\\" + fileName + ".jpg";
            
            //截图进程
            Process proce = runtime.exec(cut);
            proce.waitFor();//直到上面的命令执行完,才向下执行
            
            //转换格式进程
            ProcessBuilder builder = new ProcessBuilder(commend);
            builder.command(commend);
            builder.redirectErrorStream(true);
            
            //进程信息输出到控制台
            Process p = builder.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            while((line = br.readLine()) != null){
                System.out.println(line);
            }
            p.waitFor();//直到上面的命令执行完,才向下执行
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

长期欢迎项目合作机会介绍,项目收入10%用于酬谢介绍人。新浪微博:@冷镜,QQ:908789432。


© 著作权归作者所有

共有 人打赏支持
祁达方
粉丝 11
博文 41
码字总数 51226
作品 0
大兴
程序员
java使用ffmpeg和mencoder做视频格式转换 这个博客mencoder和ffmpeg需要安装吗

@祁达方 你好,想跟你请教个问题:java使用ffmpeg和mencoder做视频格式转换 这个博客mencoder和ffmpeg需要安装吗,这两个软件放到指定的位置就行吗?

wjh89325
05/30
0
0
java调用ffmpeg,mencoder进行视频转换,读取时长等

以前做的一个基于ffmpeg的视频格式转换的程序,现在抽空整理一下,很多地方都是从别的大神那借鉴的,只是把自己的觉得有用的,对别人有帮助的拿出来分享分享,下面是代码 package video; imp...

四月李
2014/04/11
0
0
在Centos6.4安装ffmpeg 并在网站中集成视频转换服务

安装 安装有三个办法 自己编译安装 利用yum安装 下载已经编译好的 1 自己编译安装 编译安装得办法可以参考这里 还有一个自动安装得脚本 实验结果。。成功了一个小问题是 这个源码地址可能被封...

cobola
2014/09/20
0
0
android端采用FFmpeg进行音频混合与拼接剪切

接触FFmpeg有一段时间了,它是音视频开发的开源库,几乎其他所有播放器、直播平台都基于FFmpeg进行二次开发。本篇文章来总结下采用FFmpeg进行音频处理:音频混合、音频剪切、音频拼接与音频转...

mp624183768
05/13
0
0
Linux 下完整安装ffmpeg(包括各种解码器)

FFmpeg 是什么? FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常...

霖_柒
2015/04/27
0
0
通过FFmpeg解码和OpenGL的YUV转RGB实现Android视频播放

前言 在我的博文 https://blog.csdn.net/ericbar/article/details/80506390 中,我们在Android平台上,实现了通过FFmpeg在native(C/C++)层进行视频解码,并通过OpenGL实现了硬件渲染工作,...

ericbar
05/30
0
0
GitHub上最火的74个Android开源项目(三)

GitHub上最火的40个Android开源项目(一) GitHub上最火的40个Android开源项目(二) GitHub上最火的74个Android开源项目(三) GitHub上最火的40个iOS开源项目(一) GitHub上最火的40个iOS...

LiSteven
2014/05/11
0
1
開源網路視訊會議軟件-openmeetings 的安裝

開源網路視訊會議軟件-openmeetings的安裝 2011年7月4日 前言 openmeetings是用Java開發,B/S架構.透過internet可以達到,視訊,音頻,文件,聊天室...等功能.會議中也可以由主持人決定誰可以發言...

pawnjazz
2011/07/04
0
0
Adler-32算法及其在FFMPEG中的实现

Adler-32是Mark Adler提出的一种校验和算法,与同等长度的CRC校验算法相比,它具有更好的执行效率。与此同时,它比Fletcher-16可靠,但稍逊于Fletcher-32。 Adler-32通过求解两个16位的数值A...

pqiankui
2013/10/28
0
0
LInux下安装ffmpeg视频转换工具

首先要安装各种解码器 1、lame lame-3.97.tar.gz Url:http://sourceforge.net/project/showfiles.php?groupid=290&packageid=309 安装方法如下: Java代码 tar -zxvf lame-3.97.tar.gz cd ......

慎思
2012/08/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java集合元素的默认大小

当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使...

竹叶青出于蓝
10分钟前
1
0
Java快速开发平台,JEECG 3.7.7闪电版本发布,增加多套主流UI代码生成器模板

JEECG 3.7.7 闪电版本发布,提供5套主流UI代码生成器模板 导读 ⊙平台性能优化,速度闪电般提升 ⊙提供5套新的主流UI代码生成器模板(Bootstrap表单+BootstrapTable列表\ ElementUI列表表单)...

Jeecg
13分钟前
0
0
export 和 module.export 的区别

在浏览器端 js 里面,为了解决各模块变量冲突等问题,往往借助于 js 的闭包把左右模块相关的代码都包装在一个匿名函数里。而 Nodejs 编写模块相当的自由,开发者只需要关注 require,exports,...

孟飞阳
15分钟前
1
0
技术教育的兴起

技术教育的兴起 作者: 阮一峰 1、 有一年,我在台湾环岛旅行。 花莲的海边,我遇到一对台湾青年夫妻,带着女儿在海滩上玩。我们聊了起来。 当时,我还在高校当老师。他们问我,是否觉得台湾...

吕伯文
15分钟前
0
0
Linux服务器下的HTTP抓包分析

说到抓包分析,最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了,但是有时候由于客户端开发人员(可能是第三方)知识欠缺或者其它一些原因,无法顺利的在客户端进行抓包分析,...

mylxsw
20分钟前
0
0
mybatis3-javaapi

sqlSessionFactoryBuilder->sqlSessionFactory->sqlSession<-rowbound<-resultHandler myBatis uses a Java enumeration wrapper for transaction isolation levels, called TransactionIsol......

writeademo
23分钟前
0
0
Java NIO:浅析I/O模型

也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念...

yzbty23
24分钟前
0
0
了解iOS消息推送一文就够:史上最全iOS Push技术详解

本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表。 1、引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ、微信等IM界面处于前台时,聊天消息和指令都会...

JackJiang-
25分钟前
0
0
Mysql汉子转拼音

update t_app_city SET CITY_NAME_BEGIN = ELT(INTERVAL(CONV(HEX(LEFT(CONVERT(CITY_NAME USING gbk),1)),16,10), 0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7, 0xBFA......

尘叙缘
27分钟前
0
0
大数据构建智慧城市“新引擎”,加速推进新旧动能转换

——“大数据与智慧城市”技术交流分享会——济南站召开 7月13日,“大数据携手智慧城市,助力山东新旧动能转换”技术交流分享会——济南站在山东信息通信技术研究院会议室成功举办,此次会议...

左手的倒影
29分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部