Linux下搭建基于ffmpeg的jave并且提取视频中的音频


1.安装yasm-1.3.0

解压 

        tar zxvf yasm-1.3.0.tar.gz

cd到解压目录下对进行:

        ./configure 

        make

        make install

如果提示说缺少"automake-1.15",则在其源码目录执行

        autoreconf -ivf



2.安装fdk-acc-0.1.6

过程同1.



3.安装配置ffmpeg-4.0(这里一定要使用jave2.0的jar 不然后续使用jave会一直出错)

tar cd之后

执行

        ./configure --enable-shared --prefix=/usr/local/ffmpeg

        make 

        make install

make时间较长需要耐心等待

检验是否安装成功:

        ./configure --enable-shared --prefix=/usr/local/ffmpeg

会出现报错:

/usr/local/ffmpeg/bin/ffmpeg: error while loading shared libraries: libavdevice.so.56: cannot open shared object file: No such file or directory

就是库文件检索不到,因此需要手动修改连接库文件/etc/ld.so.conf ,具体为:

        vim /etc/ld.so.conf

        include ld.so.conf.d/*.conf

        /usr/local/ffmpeg/lib/

在vim好如上命令之后,接下来使得命令需生效,使用的命令为:

        ldconfig

配置环境变量Path,以使得其在所有目录下都可以使用ffmpeg:

        export PATH=/usr/local/ffmpeg/bin/:$PATH

检测是否可以再任意目录下进行:

        ffmpeg --version



4.使用jave

调用:

    private boolean convertAmr2MP3(File src, File target) {
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        Encoder encoder = new Encoder();
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp3");
        attrs.setAudioAttributes(audio);
        try {
            encoder.encode(src, target, attrs);
            return true;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InputFormatException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        return false;
    }

报错:

it.sauronsoftware.jave.InputFormatException
	at it.sauronsoftware.jave.Encoder.parseMultimediaInfo(Encoder.java:659)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:840)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:713)
	at com.music.read.MusicFileParser.convertAmr2MP3(MusicFileParser.java:256)
	at com.music.read.MusicFileParser.loadFile(MusicFileParser.java:75)
	at com.music.read.MusicFileParser.access$000(MusicFileParser.java:24)
	at com.music.read.MusicFileParser$1.run(MusicFileParser.java:43)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

继续到官网找原因:

Using an alternative ffmpeg executable
JAVE is not pure Java: it acts as a wrapper around an ffmpeg (http://ffmpeg.mplayerhq.hu/) executable. ffmpeg is an open source and free software project entirely written in C, so its executables cannot be easily ported from a machine to another. You need a pre-compiled version of ffmpeg in order to run JAVE on your target machine. The JAVE distribution includes two pre-compiled executables of ffmpeg: a Windows one and a Linux one, both compiled for i386/32 bit hardware achitectures. This should be enough in most cases. If it is not enough for your specific situation, you can still run JAVE, but you need to obtain a platform specific ffmpeg executable. Check the Internet for it. You can even build it by yourself getting the code (and the documentation to build it) on the official ffmpeg site. Once you have obtained a ffmpeg executable suitable for your needs, you have to hook it in the JAVE library. That's a plain operation. JAVE gives you an abstract class called it.sauronsoftware.jave.FFMPEGLocator. Extend it. All you have to do is to define the following method:

public java.lang.String getFFMPEGExecutablePath()
This method should return a file system based path to your custom ffmpeg executable.

Once your class is ready, suppose you have called it MyFFMPEGExecutableLocator, you have to create an alternate encoder that uses it instead of the default locator:

Encoder encoder = new Encoder(new MyFFMPEGExecutableLocator())
You can use the same procedure also to switch to other versions of ffmpeg, even if you are on a platform covered by the executables bundled in the JAVE distribution.

Anyway be careful and test ever your application: JAVE it's not guaranteed to work properly with custom ffmpeg executables different from the bundled ones.

在官方文档上看了这一段,大意就是说要去ffmpeg的官网下载对应版本的ffmpeg。然后需要自己创建一个类去继承FFMPEGLocator,实现抽象方法,将ffmpeg的路径传JAVE



使用类加载器,获取ffmpeg的真实路经:

public class MyFFMPEGExecute extends FFMPEGLocator {
    protected String getFFMPEGExecutablePath() {

        String path = MyFFMPEGExecute.class.getResource("/res/ffmpeg").getPath();

        return path;
    }
}

调用方法改为:

    private boolean convertAmr2MP3(File src, File target) {
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        Encoder encoder = new Encoder(new MyFFMPEGExecute());
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp3");
        attrs.setAudioAttributes(audio);
        try {
            encoder.encode(src, target, attrs);
            return true;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InputFormatException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        return false;
    }

运行之后仍然报错:

it.sauronsoftware.jave.EncoderException: Stream mapping:
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:863)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:713)
	at com.music.read.MusicFileParser.convertAmr2MP3(MusicFileParser.java:256)
	at com.music.read.MusicFileParser.loadFile(MusicFileParser.java:75)
	at com.music.read.MusicFileParser.access$000(MusicFileParser.java:24)
	at com.music.read.MusicFileParser$1.run(MusicFileParser.java:43)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

这下就尴尬了,都是都是按照要求来实现的啊?怎么就不行呢?


看来还是得,后来找到一个更新版本的jave的jar包。JAVE官网最新的版本发布日期是2009年!所以可能是这个原因


加入新的jar包后重新编译运行,仍然报错。但这此报的异常又变了,感觉有希望

Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 8 more

从异常来看,最新的jave依赖了commons-logging,加上这个:

   
            commons-logging
            commons-logging
            1.2
        

但是这方案不建议使用,使用maven添加依赖在非maven项目下比较麻烦,因此建议使用commons-logging-1.2.jar

此中间还出现了一个插曲,如果提示ClassDefNotFound,很有可能是你的路径包含有中文名字


最后根据实际项目需求写了一个获取目录下所有的视频文件,在上一层目录建立一个新的文件夹下,把原来要转换的视频转换到这里。

import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncodingAttributes;
import it.sauronsoftware.jave.FFMPEGLocator;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import banger.video.EncryptUtil;
public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String filePath="/Users/hackjeremy/Desktop/env/1/";
		String videoType=".avi";
		System.out.println(
				Main.work(Main.getFileList(filePath,videoType), videoType));	
	}
	
	public static String work(Listfilelist,String fileType){
		long startTime = System.currentTimeMillis(); // 获取开始时间
		String newFloderPath="";
		if(filelist.size()>0){
			String []temp=(filelist.get(0)+"").split("/");
			for(int i=0;i0){
					newFloderPath+=("/"+temp[i]);
				}
			}
		}else{
			return "";
		}
		newFloderPath+="_finish/";
		
		Listfilename=new ArrayList();//目录下所有要处理的文件名字 不含后缀名
		for(int i=0;ifilename_cast=new ArrayList();
		if(createDir(newFloderPath)){
			for(int i=0;i getFileList(String strPath,String fileType) {
        File dir = new File(strPath);
        Listfilelist=new ArrayList();
        File[] files = dir.listFiles(); 
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                String fileName = files[i].getName();
                if (files[i].isDirectory()) { 
                    getFileList(files[i].getAbsolutePath(),fileType); 
                } else if (fileName.endsWith(fileType)) { 
                    String strFileName = files[i].getAbsolutePath();
                    filelist.add(files[i]);
                } else {
                    continue;
                }
            }
        }
        return filelist;
    }
}
初试文件为:

Linux下搭建基于ffmpeg的jave并且提取视频中的音频_第1张图片

控制台输出为:

Linux下搭建基于ffmpeg的jave并且提取视频中的音频_第2张图片

运行之后的视频转换如下:

Linux下搭建基于ffmpeg的jave并且提取视频中的音频_第3张图片

看某个视频简略图:

Linux下搭建基于ffmpeg的jave并且提取视频中的音频_第4张图片

完全没有任何问题

你可能感兴趣的:(linux,ffmpeg,jave,提取视频中的音频)