zoukankan      html  css  js  c++  java
  • 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下:

    复制代码
    依次执行下面的指令

    1.下载yasm-1.3.0.tar.gz这个版本:
    1
    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 = "【需要转码的视频路径】";

        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {  
            </span><span style="color: #0000ff;">if</span> (!checkfile(PATH)) {   <span style="color: #008000;">//</span><span style="color: #008000;">判断路径是不是一个文件</span>
                System.out.println(PATH + " is not file"<span style="color: #000000;">);  
                </span><span style="color: #0000ff;">return</span><span style="color: #000000;">;  
            }  
            </span><span style="color: #0000ff;">if</span> (process()) {        <span style="color: #008000;">//</span><span style="color: #008000;">执行转码任务</span>
                System.out.println("ok"<span style="color: #000000;">);  
            }  
        }  
      
        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> checkfile(String path) {  
            File file </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> File(path);  
            </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">file.isFile()) {  
                </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;  
            }  
            </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;  
        }  
        
        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> process() { 
            </span><span style="color: #008000;">//</span><span style="color: #008000;"> 判断视频的类型</span>
            <span style="color: #0000ff;">int</span> type =<span style="color: #000000;"> checkContentType();  
            </span><span style="color: #0000ff;">boolean</span> status = <span style="color: #0000ff;">false</span><span style="color: #000000;">;  
            </span><span style="color: #008000;">//</span><span style="color: #008000;">如果是ffmpeg可以转换的类型直接转码,否则先用mencoder转码成AVI</span>
            <span style="color: #0000ff;">if</span> (type == 0<span style="color: #000000;">) {  
                System.out.println(</span>"直接将文件转为flv文件"<span style="color: #000000;">);  
                status </span>= processFLV(PATH);<span style="color: #008000;">//</span><span style="color: #008000;"> 直接将文件转为flv文件  </span>
            } <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type == 1<span style="color: #000000;">) {  
                String avifilepath </span>=<span style="color: #000000;"> processAVI(type);  
                </span><span style="color: #0000ff;">if</span> (avifilepath == <span style="color: #0000ff;">null</span><span style="color: #000000;">)  
                    </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span>;<span style="color: #008000;">//</span><span style="color: #008000;"> avi文件没有得到  </span>
                status = processFLV(avifilepath);<span style="color: #008000;">//</span><span style="color: #008000;"> 将avi转为flv  </span>
    

    }
    return status;
    }

        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> checkContentType() {  
            String type </span>= PATH.substring(PATH.lastIndexOf(".") + 1<span style="color: #000000;">, PATH.length())  
                    .toLowerCase();  
            </span><span style="color: #008000;">//</span><span style="color: #008000;"> ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  </span>
            <span style="color: #0000ff;">if</span> (type.equals("avi"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mpg"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("wmv"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("3gp"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mov"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mp4"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("asf"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("asx"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("flv"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">;  
            }  
            </span><span style="color: #008000;">//</span><span style="color: #008000;"> 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),  
            </span><span style="color: #008000;">//</span><span style="color: #008000;"> 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.  </span>
            <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("wmv9"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("rm"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("rmvb"<span style="color: #000000;">)) {  
                </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">;  
            }  
            </span><span style="color: #0000ff;">return</span> 9<span style="color: #000000;">;  
        }  
           
      
        </span><span style="color: #008000;">//</span><span style="color: #008000;"> 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.  </span>
        <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> String processAVI(<span style="color: #0000ff;">int</span><span style="color: #000000;"> type) {  
            List</span>&lt;String&gt; commend = <span style="color: #0000ff;">new</span> ArrayList&lt;String&gt;<span style="color: #000000;">();  
            commend.add(</span>"D:\ffmpeg\mencoder"<span style="color: #000000;">);  
            commend.add(PATH);  
            commend.add(</span>"-oac"<span style="color: #000000;">);  
            commend.add(</span>"lavc"<span style="color: #000000;">);  
            commend.add(</span>"-lavcopts"<span style="color: #000000;">);  
            commend.add(</span>"acodec=mp3:abitrate=64"<span style="color: #000000;">);  
            commend.add(</span>"-ovc"<span style="color: #000000;">);  
            commend.add(</span>"xvid"<span style="color: #000000;">);  
            commend.add(</span>"-xvidencopts"<span style="color: #000000;">);  
            commend.add(</span>"bitrate=600"<span style="color: #000000;">);  
            commend.add(</span>"-of"<span style="color: #000000;">);  
            commend.add(</span>"avi"<span style="color: #000000;">);  
            commend.add(</span>"-o"<span style="color: #000000;">);  
            commend.add(</span>"【存放转码后视频的路径,记住一定是.avi后缀的文件名】"<span style="color: #000000;">);  
            </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {  
                </span><span style="color: #008000;">//</span><span style="color: #008000;">调用线程命令启动转码</span>
                ProcessBuilder builder = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ProcessBuilder();  
                builder.command(commend);  
                builder.start();  
                </span><span style="color: #0000ff;">return</span> "【存放转码后视频的路径,记住一定是.avi后缀的文件名】"<span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) {  
                e.printStackTrace();  
                </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;  
            }  
        }  
      
        </span><span style="color: #008000;">//</span><span style="color: #008000;"> ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  </span>
        <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> processFLV(String oldfilepath) {  
      
            </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">checkfile(PATH)) {  
                System.out.println(oldfilepath </span>+ " is not file"<span style="color: #000000;">);  
                </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;  
            }  
              
            </span><span style="color: #008000;">//</span><span style="color: #008000;"> 文件命名  </span>
            Calendar c =<span style="color: #000000;"> Calendar.getInstance();  
            String savename </span>= String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000<span style="color: #000000;">);  
            List</span>&lt;String&gt; commend = <span style="color: #0000ff;">new</span> ArrayList&lt;String&gt;<span style="color: #000000;">();  
            commend.add(</span>"D:\ffmpeg\ffmpeg"<span style="color: #000000;">);  
            commend.add(</span>"-i"<span style="color: #000000;">);  
            commend.add(oldfilepath);  
            commend.add(</span>"-ab"<span style="color: #000000;">);  
            commend.add(</span>"56"<span style="color: #000000;">);  
            commend.add(</span>"-ar"<span style="color: #000000;">);  
            commend.add(</span>"22050"<span style="color: #000000;">);  
            commend.add(</span>"-qscale"<span style="color: #000000;">);  
            commend.add(</span>"8"<span style="color: #000000;">);  
            commend.add(</span>"-r"<span style="color: #000000;">);  
            commend.add(</span>"15"<span style="color: #000000;">);  
            commend.add(</span>"-s"<span style="color: #000000;">);  
            commend.add(</span>"600x500"<span style="color: #000000;">);  
            commend.add(</span>"【存放转码后视频的路径,记住一定是.flv后缀的文件名】"<span style="color: #000000;">);  
      
            </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {  
                Runtime runtime </span>=<span style="color: #000000;"> Runtime.getRuntime();  
                Process proce </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; 
                </span><span style="color: #008000;">//</span><span style="color: #008000;">视频截图命令,封面图。  8是代表第8秒的时候截图</span>
                String cmd = ""<span style="color: #000000;">;  
                String cut </span>= "     c:\ffmpeg\ffmpeg.exe   -i   "  
                        +<span style="color: #000000;"> oldfilepath  
                        </span>+ "   -y   -f   image2   -ss   8   -t   0.001   -s   600x500   c:\ffmpeg\output\"  
                        + "a.jpg"<span style="color: #000000;">;  
                String cutCmd </span>= cmd +<span style="color: #000000;"> cut;  
                proce </span>=<span style="color: #000000;"> runtime.exec(cutCmd);  
                </span><span style="color: #008000;">//</span><span style="color: #008000;">调用线程命令进行转码</span>
                ProcessBuilder builder = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ProcessBuilder(commend);                 
                 builder.command(commend);  
                builder.start();  
      
                </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;  
            } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) {  
                e.printStackTrace();  
                </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;  
            }  
        }  
    

    }

    复制代码
     注: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 持续时长




  • 相关阅读:
    面向对象程序设计寒假作业2
    面向对象程序设计寒假作业1
    自我介绍
    3组-Alpha冲刺-1/6
    3组 需求分析报告
    3组 团队展示
    第一次个人编程作业
    第一次博客作业
    我罗斯方块最终篇
    我罗斯方块设计
  • 原文地址:https://www.cnblogs.com/jpfss/p/10880553.html
Copyright © 2011-2022 走看看