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 = "【需要转码的视频路径】";

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:\ffmpeg\ffmpeg -i c:\ffmpeg\input\c.mp4 -f avi c:\ffmpeg\output\a.avi

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




posted @ 2019-05-17 11:48  星朝  阅读(1834)  评论(1)    收藏  举报