Java无需安装使用FFmpeg

网上很多教程都是需要先在服务器上安装ffmpeg,这样做首先是后期维护非常麻烦,每到一个新环境都得先安装文件,windows还好,linux是非常麻烦的,还可能有权限不足的各种坑。

这里介绍一个包,核心就是将各个环境的ffmpeg打成jar包,只要引入就可以无视环境使用

        但需要注意一点,最好将没用的环境的包排除出去,避免最终的jar包过大

Maven依赖

        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-all-deps</artifactId>
            <version>3.3.1</version>
            <exclusions>
                <!--  排除windows 32位系统      -->
                <exclusion>
                    <groupId>ws.schild</groupId>
                    <artifactId>jave-nativebin-win32</artifactId>
                </exclusion>
                <!--  排除linux 32位系统      -->
                <exclusion>
                    <groupId>ws.schild</groupId>
                    <artifactId>jave-nativebin-linux32</artifactId>
                </exclusion>
                <!-- 排除Mac系统-->
                <exclusion>
                    <groupId>ws.schild</groupId>
                    <artifactId>jave-nativebin-osx64</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ws.schild</groupId>
                    <artifactId>jave-nativebin-osxm1</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ws.schild</groupId>
                    <artifactId>jave-nativebin-linux-arm32</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 测试代码(mp4格式转m3u8)

实现方式就是构造出需要执行的指令,和正常操作ffmpeg一样

    public static void main(String[] args) {
        String filePathName = System.getProperty("user.dir")+"/file/xxx.mp4";
        String m3u8FileName = System.getProperty("user.dir") + "/file/xxx.m3u8";
        String cmdString = "-y -v error -i {filePathName} -strict strict -f hls -preset ultrafast -acodec aac -ac 1 -vsync 2 -c:v copy -c:a copy -tune fastdecode -hls_time 10 -hls_list_size 0 -threads 12 {outputPath}";
        cmdString = cmdString.replace("{filePathName}", filePathName);
        cmdString = cmdString.replace("{outputPath}",m3u8FileName);
        Integer code = cmdExecut(cmdString);
        System.out.println(String.format("获取最终执行结果:%s", code == 0 ? "成功!" : "失败!"));

    }

    /**
     *
     * @Description: (执行ffmpeg自定义命令)
     * @param: @param cmdStr
     * @param: @return
     * @return: Integer
     * @throws
     */
    public static Integer cmdExecut(String cmdStr) {
        //code=0表示正常
        Integer code  = null;
        FfmpegCmd ffmpegCmd = new FfmpegCmd();
        /**
         * 错误流
         */
        InputStream errorStream = null;
        try {
            //destroyOnRuntimeShutdown表示是否立即关闭Runtime
            //如果ffmpeg命令需要长时间执行,destroyOnRuntimeShutdown = false
            ffmpegCmd.execute(false, true, cmdStr);
            errorStream = ffmpegCmd.getErrorStream();

            //打印过程
            int len = 0;
            while ((len=errorStream.read())!=-1){
                log.info(String.valueOf(len));
            }
            //code=0表示正常
            code = ffmpegCmd.getProcessExitCode();
        } catch (Exception e) {
            log.error("转码失败",e);
        } finally {
            //关闭资源
            ffmpegCmd.close();
        }
        //返回
        return code;
    }

相关的类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ws.schild.jave.process.ProcessKiller;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FfmpegCmd {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /** The process representing the ffmpeg execution. */
    private Process ffmpeg = null;

    /**
     * A process killer to kill the ffmpeg process with a shutdown hook, useful if the jvm execution
     * is shutted down during an ongoing encoding process.
     */
    private ProcessKiller ffmpegKiller = null;

    /** A stream reading from the ffmpeg process standard output channel. */
    private InputStream inputStream = null;

    /** A stream writing in the ffmpeg process standard input channel. */
    private OutputStream outputStream = null;

    /** A stream reading from the ffmpeg process standard error channel. */
    private InputStream errorStream = null;

    /**
     * Executes the ffmpeg process with the previous given arguments.
     *
     * @param destroyOnRuntimeShutdown destroy process if the runtime VM is shutdown
     * @param openIOStreams Open IO streams for input/output and errorout, should be false when
     *     destroyOnRuntimeShutdown is false too
     * @param ffmpegCmd  windows such as (mp4 transform to mov):
     *     " -i C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer.mp4 -c copy C:\\Users\\hsj\\AppData\\Local\\Temp\\jave\\honer_test.mov "
     * @throws IOException If the process call fails.
     */
    public void execute(boolean destroyOnRuntimeShutdown, boolean openIOStreams, String ffmpegCmd) throws IOException {
        DefaultFFMPEGLocator defaultFFMPEGLocator = new DefaultFFMPEGLocator();

        StringBuffer cmd = new StringBuffer(defaultFFMPEGLocator.getExecutablePath());
        //insert blank for delimiter
        cmd.append(" ");
        cmd.append(ffmpegCmd);
        String cmdStr = String.format("ffmpegCmd final is :%s", cmd.toString());
        System.out.println(cmdStr);
        logger.info(cmdStr);

        Runtime runtime = Runtime.getRuntime();
        try {
            ffmpeg = runtime.exec(cmd.toString());

            if (destroyOnRuntimeShutdown) {
                ffmpegKiller = new ProcessKiller(ffmpeg);
                runtime.addShutdownHook(ffmpegKiller);
            }

            if (openIOStreams) {
                inputStream = ffmpeg.getInputStream();
                outputStream = ffmpeg.getOutputStream();
                errorStream = ffmpeg.getErrorStream();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns a stream reading from the ffmpeg process standard output channel.
     *
     * @return A stream reading from the ffmpeg process standard output channel.
     */
    public InputStream getInputStream() {
        return inputStream;
    }

    /**
     * Returns a stream writing in the ffmpeg process standard input channel.
     *
     * @return A stream writing in the ffmpeg process standard input channel.
     */
    public OutputStream getOutputStream() {
        return outputStream;
    }

    /**
     * Returns a stream reading from the ffmpeg process standard error channel.
     *
     * @return A stream reading from the ffmpeg process standard error channel.
     */
    public InputStream getErrorStream() {
        return errorStream;
    }

    /** If there's a ffmpeg execution in progress, it kills it. */
    public void destroy() {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (Throwable t) {
                logger.warn("Error closing input stream", t);
            }
            inputStream = null;
        }

        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (Throwable t) {
                logger.warn("Error closing output stream", t);
            }
            outputStream = null;
        }

        if (errorStream != null) {
            try {
                errorStream.close();
            } catch (Throwable t) {
                logger.warn("Error closing error stream", t);
            }
            errorStream = null;
        }

        if (ffmpeg != null) {
            ffmpeg.destroy();
            ffmpeg = null;
        }

        if (ffmpegKiller != null) {
            Runtime runtime = Runtime.getRuntime();
            runtime.removeShutdownHook(ffmpegKiller);
            ffmpegKiller = null;
        }
    }

    /**
     * Return the exit code of the ffmpeg process If the process is not yet terminated, it waits for
     * the termination of the process
     *
     * @return process exit code
     */
    public int getProcessExitCode() {
        // Make sure it's terminated
        try {
            ffmpeg.waitFor();
        } catch (InterruptedException ex) {
            logger.warn("Interrupted during waiting on process, forced shutdown?", ex);
        }
        return ffmpeg.exitValue();
    }

    /**close**/
    public void close() {
        destroy();
    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值