ffmpeg 下载以及安装步骤
进入官方地址
http://ffmpeg.org/
进入下一步
window 下载
linux 下载
看到上面这个图,下载那个版本看你自己选择
完成之后
window安装
配置环境变量
在cmd 输入ffmpeg 显示下图 就完成了
springboot整合使用
举个例子:
200M的视频,因为太大,网络加载很慢,要等很久。
那么像要播放流畅,那就需要流媒体。
因为视频点播 是流媒体,所以要把视频切成流媒体。
使用ffmpeg 把视频切成m3u8和ts
/*import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;*/
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/*import ws.schild.jave.DefaultFFMPEGLocator;
import ws.schild.jave.EncoderException;
import ws.schild.jave.FFMPEGLocator;
import ws.schild.jave.MultimediaObject;*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
/**
* mp4转换m3u8工具类
*/
@Component
public class ConvertM3U8Util {
@Value("${m3u8.ffmpegpath}")
private String ffmpegpath; // ffmpeg.exe的目录
public boolean convertOss(String folderUrl, String fileName) {
if (!checkfile(folderUrl + fileName)) {
System.out.println("文件不存在!");
return false;
}
//验证文件后缀
String suffix = StringUtils.substringAfter(fileName, ".");
String fileFullName = StringUtils.substringBefore(fileName, ".");
if (!validFileType(suffix)) {
return false;
}
//return processM3U8(folderUrl,fileName,fileFullName);
return processM3U8(folderUrl, fileName, fileFullName, "1280x720", "10");
}
/**
* 验证上传文件后缀
*
* @param type
* @return
*/
private boolean validFileType(String type) {
if ("mp4".equals(type)) {
return true;
}
return false;
}
/**
* 验证是否是文件格式
*
* @param path
* @return
*/
private boolean checkfile(String path) {
File file = new File(path);
if (!file.isFile()) {
return false;
} else {
return true;
}
}
// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
/**
* ffmpeg程序转换m3u8
*
* @param folderUrl
* @param fileName
* @param fileFullName
* @return
*/
private boolean processM3U8(String folderUrl, String fileName, String fileFullName) {
//这里就写入执行语句就可以了
List commend = new java.util.ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-c:v");
commend.add("libx264");
commend.add("-hls_time");
commend.add("20");
commend.add("-hls_list_size");
commend.add("0");
commend.add("-c:a");
commend.add("aac");
commend.add("-strict");
commend.add("-2");
commend.add("-f");
commend.add("hls");
commend.add(folderUrl + fileFullName + ".m3u8");
try {
ProcessBuilder builder = new ProcessBuilder();//java
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* @param folderUrl
* @param fileName
* @param fileFullName
* @param resolution 分辨率
* @param time 每个ts时长
* @return
*/
private boolean processM3U8(String folderUrl, String fileName, String fileFullName, String resolution, String time) {
//这里就写入执行语句就可以了
List commend = new java.util.ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-profile:v");
commend.add("baseline");
commend.add("-level");
commend.add("3.0");
commend.add("-s");
commend.add(resolution);
commend.add("-start_number");
commend.add("0");
commend.add("-hls_time");
commend.add(time);
commend.add("-hls_list_size");
commend.add("0");
commend.add("-f");
commend.add("hls");
commend.add(folderUrl + fileFullName + ".m3u8");
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private boolean processM3U8(String ffmpegpath, String folderUrl, String fileName, String fileFullName, String resolution, String time) {
//这里就写入执行语句就可以了
List commend = new java.util.ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-profile:v");
commend.add("baseline");
commend.add("-level");
commend.add("3.0");
commend.add("-s");
commend.add(resolution);
commend.add("-start_number");
commend.add("0");
commend.add("-hls_time");
commend.add(time);
commend.add("-hls_list_size");
commend.add("0");
commend.add("-f");
commend.add("hls");
commend.add(folderUrl + fileFullName + ".m3u8");
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 合理压缩视频
*
* @param folderUrl 目录
* @param fileName 文件名
* @param newfileUrl 新的存放文件地址
* @param resolution
* @return
*/
private boolean reasonableCompression(String folderUrl, String fileName, String newfileUrl, String resolution) {
//这里就写入执行语句就可以了
//ffmpeg -i d:/123.mp4 -s 1280x720 -c:v libx264 -preset veryfast -crf 28 -c:a copy d:/xin8.mp4
List commend = new java.util.ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-s");
commend.add(resolution);
commend.add("-c:v");
commend.add("libx264");
commend.add("-preset");
commend.add("veryfast");
commend.add("-crf");
commend.add("28");
commend.add("-c:a");
commend.add("copy");
commend.add(newfileUrl);
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/***
* 合理转换m3u8
* @param folderUrl
* @param fileName
* @param fileFullName
* @param resolution
* @param time
* @return
*/
private boolean reasonableProcessM3U8(String folderUrl, String fileName, String fileFullName, String resolution, String time) {
//这里就写入执行语句就可以了
//ffmpeg -i d:/123.mp4 -s 1280x720 -c:v libx264 -preset veryfast -crf 28 -c:a copy d:/xin8.mp4
List commend = new ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-preset");
commend.add("veryfast");
commend.add("-crf");
commend.add("28");
commend.add("-s");
commend.add(resolution);
commend.add("-start_number");
commend.add("0");
commend.add("-hls_time");
commend.add(time);
commend.add("-hls_list_size");
commend.add("0");
commend.add("-hls_segment_filename");
commend.add(folderUrl + fileFullName + "-%d.ts");
commend.add("-f");
commend.add("hls");
commend.add(folderUrl + fileFullName + ".m3u8");
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 合理取时间某一秒画面为图片
*
* @param folderUrl 目录
* @param fileName 文件
* @param newfileUrl 新文件地址
* @param startTime 起始时间 第几秒
* @param resolution 图片分辨率尺寸
* @return
*/
private boolean reasonableImage(String folderUrl, String fileName, String newfileUrl, String startTime, String resolution) {
//这里就写入执行语句就可以了
//ffmpeg -i d:/123.mp4 -s 1280x720 -c:v libx264 -preset veryfast -crf 28 -c:a copy d:/xin8.mp4
List<String> cutpic = new ArrayList<String>();
cutpic.add(ffmpegpath);
cutpic.add("-i");
cutpic.add(folderUrl + fileName); // 同上(指定的文件即可以是转换为flv格式之前的文件,也可以是转换的flv文件)
cutpic.add("-y");
cutpic.add("-f");
cutpic.add("image2");
cutpic.add("-ss"); // 添加参数"-ss",该参数指定截取的起始时间
cutpic.add(startTime); // 添加起始时间为第2秒
cutpic.add("-t"); // 添加参数"-t",该参数指定持续时间
cutpic.add("0.001"); // 添加持续时间为1毫秒
cutpic.add("-s"); // 添加参数"-s",该参数指定截取的图片大小
cutpic.add(resolution); // 添加截取的图片大小为350*240
cutpic.add(newfileUrl); // 添加截取的图片的保存路径
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(cutpic);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private boolean reasonableProcessM3U8(String ffmpegpath,String folderUrl, String fileName, String fileFullName, String resolution, String time) {
//这里就写入执行语句就可以了
//ffmpeg -i d:/123.mp4 -s 1280x720 -c:v libx264 -preset veryfast -crf 28 -c:a copy d:/xin8.mp4
List commend = new ArrayList();
commend.add(ffmpegpath);
commend.add("-i");
commend.add(folderUrl + fileName);
commend.add("-preset");
commend.add("veryfast");
commend.add("-crf");
commend.add("28");
commend.add("-s");
commend.add(resolution);
commend.add("-start_number");
commend.add("0");
commend.add("-hls_time");
commend.add(time);
commend.add("-hls_list_size");
commend.add("0");
commend.add("-hls_segment_filename");
commend.add(folderUrl + fileFullName + "-%d.ts");
commend.add("-f");
commend.add("hls");
commend.add(folderUrl + fileFullName + ".m3u8");
try {
//java
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
Process p = builder.start();
int i = doWaitFor(p);
System.out.println("------>" + i);
p.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 监听ffmpeg运行过程
*
* @param p
* @return
*/
public int doWaitFor(Process p) {
InputStream in = null;
InputStream err = null;
int exitValue = -1; // returned to caller when p is finished
try {
System.out.println("comeing");
in = p.getInputStream();
err = p.getErrorStream();
boolean finished = false; // Set to true when p is finished
while (!finished) {
try {
while (in.available() > 0) {
Character c = new Character((char) in.read());
System.out.print(c);
}
while (err.available() > 0) {
Character c = new Character((char) err.read());
System.out.print(c);
}
exitValue = p.exitValue();
finished = true;
} catch (IllegalThreadStateException e) {
Thread.currentThread().sleep(500);
}
}
} catch (Exception e) {
System.err.println("doWaitFor();: unexpected exception - "
+ e.getMessage());
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
if (err != null) {
try {
err.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
return exitValue;
}
/**
* 获取视频文件时长
*
* @param music
* @return
*/
/*private String getVideoTime(File music) {
System.out.println("~~~~~~~~~~~~~~~~ 开始获取视频时长 ~~~~~~~~~~~~~~~~~");
Encoder encoder = new Encoder();
try {
MultimediaInfo m = encoder.getInfo(music);
long ls = m.getDuration();
int time = (int) ls / 1000;
int ss = time % 60;
int mm = time / 60 % 60;
int hh = time / 60 / 60 % 24;
String result = "";
if (ss != 0) {
String HH = hh == 0 ? "" : getTime(hh) + ":";
result = HH + getTime(mm) + ":" + getTime(ss);
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
return "00:00";
}*/
/**
* 把时间转换成字符串
*
* @param time
* @return
*/
private String getTime(int time) {
if (time == 0) {
return "00";
} else {
if (time <= 9) {
return "0" + time;
} else {
return time + "";
}
}
}
/**
* 获取视频大小
*
* @param source
* @return
*/
private Long readVideoSize(File source) {
FileChannel fc = null;
Long size = 0L;
try {
@SuppressWarnings("resource")
FileInputStream fis = new FileInputStream(source);
fc = fis.getChannel();
BigDecimal fileSize = new BigDecimal(fc.size());
size = Long.parseLong(fileSize.toString());
if (size > 0) {
size = Long.parseLong(fileSize.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fc) {
try {
fc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return size;
}
public static void main(String[] args) {
/*ConvertM3U8Util util = new ConvertM3U8Util();
boolean b = util.reasonableProcessM3U8("D:/ffmpeg/bin/ffmpeg.exe", "d:/video/", "xin7.mp4", "xin7","1280x720", "10");
System.out.println(b);*/
/*File file = new File("d:/123.mp4");
String videoTime = util.getVideoTime(file);
Long videoSize = util.readVideoSize(file);
System.out.println(videoTime);
System.out.println(videoSize);
//解析文件
MultimediaObject object = new MultimediaObject(file);
ws.schild.jave.MultimediaInfo multimediaInfo = object.getInfo();
long duration = multimediaInfo.getDuration();
System.out.println(duration / 1000);
System.out.println(multimediaInfo.getAudio().getBitRate());
System.out.println(multimediaInfo.getFormat());
Sys
*/
}
}
注意:
页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
<script src="https://unpkg.com/video.js/dist/video.js"></script>
<script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
</head>
<body>
<video id="my_video_1" class="video-js vjs-default-skin" controls preload="auto"
data-setup='{}'>
<source type="application/x-mpegURL" src="http://localhost/ud/48214823-466d-4914-a1ef-9e5a3e097303/123.m3u8">
<!-- video.js给的示例 -->
<!--<source src="http://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8" type="application/x-mpegURL">-->
</video>
<script src="//cdn.bootcss.com/video.js/7.0.0-alpha.1/video.min.js"></script>
</body>
</html>
注意:
是你使用ffmpeg 切成m3u8 ,你要指向这个地址。相等于 localhost/ud/123.mp4.
在使用ffmpeg 切片的时候,最终会切成这样子。