java-FFmpeg(一) 实现视频的转码和截图功能

时间:2022-04-25
本文章向大家介绍java-FFmpeg(一) 实现视频的转码和截图功能,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行。

  在java开发中,FFmpeg也常被调用用来进行视频的转码,录播和直播,总的来说,FFmpeg是一款非常强大的,而且做与视频相关的业务平台开发人员必须要学会的工具,那具体怎么实习呢,第一章我们先从分别windows和linux下调用FFmpeg进行视频的转码,和对视频的截图做出说明解释。

ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等),而对于ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),我们在下面采用了mencoder工具,先将视频转换成AVI格式再用ffmpeg进行转码;

windows下:

        1.首先需要FFmpeg和mencoder的工具。一共五个文件,点此下载,将他解压放在你的D盘FFmpeg文件夹下。

 linux下:

依次执行下面的指令

yasm是一个完全重写的NASM汇编。目前,它支持x86和AMD64指令集,接受NASM和气体汇编语法,产出二进制, ELF32 , ELF64 , COFF , Mach - O的( 32和64 ) , RDOFF2 ,的Win32和Win64对象的格式,并生成STABS 调试信息的来源,DWARF 2 ,CodeView 8格式。之所以在FFmpeg中用这个,主要是支持编译ffmpeg-x264.
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar xzvf yasm-1.3.0.tar.gz
cd yasm-1.3.0
./configure
make
make install

2.下载3.1.3 release ffmpeg
wget http://ffmpeg.org/releases/ffmpeg-3.1.3.tar.gz
tar -zxvf ffmpeg-3.1.3.tar.gz
cd ffmpeg-3.1.3
./configure
make
make install

第二步的时间可能会有点长,耐心等待~!安装完成之后输入  ffmpeg -version 可以看到版本说明安装成功

package wordtopdf;

import java.io.File;  
import java.util.ArrayList;  
import java.util.Calendar;  
import java.util.List;  
  
下面直接上代码,都写好注释的,很清楚。

public class ConvertVideo {
     private final static String PATH = "【需要转码的视频路径】";  
      
        public static void main(String[] args) {  
            if (!checkfile(PATH)) {   //判断路径是不是一个文件
                System.out.println(PATH + " is not file");  
                return;  
            }  
            if (process()) {        //执行转码任务
                System.out.println("ok");  
            }  
        }  
      
        private static boolean checkfile(String path) {  
            File file = new File(path);  
            if (!file.isFile()) {  
                return false;  
            }  
            return true;  
        }  
        
        private static boolean process() { 
            // 判断视频的类型
            int type = checkContentType();  
            boolean status = false;  
            //如果是ffmpeg可以转换的类型直接转码,否则先用mencoder转码成AVI
            if (type == 0) {  
                System.out.println("直接将文件转为flv文件");  
                status = processFLV(PATH);// 直接将文件转为flv文件  
            } else if (type == 1) {  
                String avifilepath = processAVI(type);  
                if (avifilepath == null)  
                    return false;// avi文件没有得到  
                status = processFLV(avifilepath);// 将avi转为flv  
            }  
            return status;  
        }  
      
        private static int checkContentType() {  
            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 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;  
        }  
           
      
        // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.  
        private static String processAVI(int type) {  
            List<String> commend = new ArrayList<String>();  
            commend.add("D:\ffmpeg\mencoder");  
            commend.add(PATH);  
            commend.add("-oac");  
            commend.add("lavc");  
            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("【存放转码后视频的路径,记住一定是.avi后缀的文件名】");  
            try {  
                //调用线程命令启动转码
                ProcessBuilder builder = new ProcessBuilder();  
                builder.command(commend);  
                builder.start();  
                return "【存放转码后视频的路径,记住一定是.avi后缀的文件名】";  
            } catch (Exception e) {  
                e.printStackTrace();  
                return null;  
            }  
        }  
      
        // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
        private static boolean processFLV(String oldfilepath) {  
      
            if (!checkfile(PATH)) {  
                System.out.println(oldfilepath + " is not file");  
                return false;  
            }  
              
            // 文件命名  
            Calendar c = Calendar.getInstance();  
            String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);  
            List<String> commend = new ArrayList<String>();  
            commend.add("D:\ffmpeg\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("-s");  
            commend.add("600x500");  
            commend.add("【存放转码后视频的路径,记住一定是.flv后缀的文件名】");  
      
            try {  
                Runtime runtime = Runtime.getRuntime();  
                Process proce = null; 
                //视频截图命令,封面图。  8是代表第8秒的时候截图
                String cmd = "";  
                String cut = "     c:\ffmpeg\ffmpeg.exe   -i   "  
                        + oldfilepath  
                        + "   -y   -f   image2   -ss   8   -t   0.001   -s   600x500   c:\ffmpeg\output\"  
                        + "a.jpg";  
                String cutCmd = cmd + cut;  
                proce = runtime.exec(cutCmd);  
                //调用线程命令进行转码
                ProcessBuilder builder = new ProcessBuilder(commend);                 
                 builder.command(commend);  
                builder.start();  
      
                return true;  
            } catch (Exception e) {  
                e.printStackTrace();  
                return false;  
            }  
        }  
}

 注:ffmpeg的功能十分强大,但是命令也非常多,转换每种格式的命令都不相同!需要转换其他格式的,请写对命令。

       命令格式:

    普通转码:     ffmpeg -i [输入文件名] [参数选项] -f [格式] [输出文件]     比如:MP4转avi c:ffmpegffmpeg -i c:ffmpeginputc.mp4 -f avi c:ffmpegoutputa.avi

    参数:-an 去掉音频     -b 1000K 压缩码率为1000K     -s 800*500 压缩尺寸为800*500     -aspect 宽高比,格式 16:9 或 1.778     (当源尺寸是16:9,要压缩成非16:9的,一方面要设定 -s,另一方面要给出 -aspect)     -ss 开始时间​     -t 持续时长