一、下载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方法进行封装。
希望大家可以参考本文,根据自己的业务需求进行扩充。有何疑问欢迎大家一起讨论。
把技术死磕到底。