Java后端利用ffmpeg做视频转码(通过视频访问链接直接进行)

一、下载ffmpeg

下载地址:http://www.ffmpeg.org/download.html。下载完成后,解压到自己喜欢的目录。

二、命令行转码(参考https://blog.csdn.net/guojianwei2011/article/details/83242789)

进入上一步解软件目录的bin目录下,输入以下命令即可,

ffmpeg -i “https://xxx/xxx/xxx.m3u8” -vcodec copy -acodec copy -absf aac_adtstoasc /xxx/xxx/xxx.mp4

其中 http://xxx/xxx/xxx.m3u8 视频的m3u8地址, /xxx/xxx/xxx.mp4 为输出mp4的文件目录及文件名

三、Java程序解码(代码仅供参考)

/**
 * hilbert.xu 2019-03-01
 */
public class ConvertVideo {
    private static final String projectDir = new ApplicationHome(ConvertVideo.class).getDir().toString();

    /**
     * 视频转化
     *
     * @param url        视频源地址
     * @param ffmpegPath ffmpeg 软件安装目录
     * @return
     */
    public static Map<String, Object> convertVideo(String url, String ffmpegPath) {
        Map<String, Object> map = new HashMap<>();
        String toolPath = ffmpegPath;
        if (StringUtils.isBlank(toolPath)) {
            toolPath = getFfmpegPath();
        }
        String outputPath = getOutputPath();
        map.put("path", outputPath);
        map.put("flag", false);
        try {
            Boolean ffmpeg = FfmpegUtil.ffmpeg(toolPath, url, outputPath);
            map.put("flag", ffmpeg);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 获取ffmpeg执行文件的路径
     *
     * @return
     */
    private static String getFfmpegPath() {
        return projectDir + File.separator + "ffmpeg";
    }

    /**
     * 获取输出文件名
     *
     * @return
     */
    private static String getOutputPath() {
        String tempPath = projectDir + File.separator + "video" + File.separator;
        File tempFolder = new File(tempPath);
        if (!tempFolder.exists()) {
            boolean mkdirs = tempFolder.mkdirs();
            if (mkdirs) {
                return tempPath + UUID.randomUUID().toString().replaceAll("-", "") + ".mp4";
            }
        }
        return tempPath + UUID.randomUUID().toString().replaceAll("-", "") + ".mp4";
    }
}
/**
 * 根据视频地址转换m3u8格式为mp4
 * <p>
 * hilbert.xu 2019-03-01
 */
public class FfmpegUtil {

    /**
     * 将视频转换为ts流
     *
     * @param ffmpegPath ffmpegPath bin路径
     * @param url        源文件路径
     * @param outputPath 输出文件路径
     * @return
     */
    public static Boolean ffmpeg(String ffmpegPath, String url, String outputPath) throws Exception {
        List<String> command = getFfmpegCommand(ffmpegPath, url, outputPath);
        if (null != command && command.size() > 0) {
            return process(command);
        }
        return false;
    }

    /**
     * @param command
     * @throws Exception
     */
    private static boolean process(List<String> command) {
        try {
            if (null == command || command.size() == 0) {
                return false;
            }
            Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
            new PrintStream(videoProcess.getErrorStream()).start();
            new PrintStream(videoProcess.getInputStream()).start();
            int exitcode = videoProcess.waitFor();
            if (exitcode == 1) {
                return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 根据文件类型设置ffmpeg命令
     *
     * @param url
     * @param outputPath
     * @return
     */
    private static List<String> getFfmpegCommand(String ffmpegPath, String url, String outputPath) {
        List<String> command = new ArrayList<>();
        command.add(ffmpegPath + File.separator + "ffmpeg");
        command.add("-i");
        command.add(url);
        command.add("-vcodec");
        command.add("copy");
        command.add("-acodec");
        command.add("copy");
        command.add("-absf");
        command.add("aac_adtstoasc");
        command.add(outputPath);
        return command;
    }
}

class PrintStream extends Thread {
    java.io.InputStream __is = null;

    public PrintStream(java.io.InputStream is) {
        __is = is;
    }

    public void run() {
        try {
            while (this != null) {
                int _ch = __is.read();
                if (_ch == -1) {
                    break;
                } else {
                    System.out.print((char) _ch);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、总结

本位只提供一种转码形式,如有其他需要可以参看ffmpeg文档进行功能扩充。具体执行命令可以参考getFfmpegCommand方法进行封装。

希望大家可以参考本文,根据自己的业务需求进行扩充。有何疑问欢迎大家一起讨论。

把技术死磕到底。

发布了23 篇原创文章 · 获赞 24 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_35971547/article/details/88116422