提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
● HLS协议:HTTP Live Streaming用于播放.ts视频,它是苹果公司实现的基于HTTP的流媒体传输协议,可以实现流媒体的直播和点播。关键组成有m3u8和多个视频分片.ts
● m3u8(hls的index文件):是指UTF-8编码格式的M3U文件。M3U文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。
● .ts:视频格式:是日本高清摄像机拍摄下进行的封装格式,可使用.WinDVD 5.x、VLC Media Player、Elecard Player播放器播放;
○ mp4:一种兼容性非常好的视频格式,几乎所有的媒体设备都支持mp4格式。
○ TS比较清晰,因为TS一般封装原盘,码率比较足,mp4是压制过来的,采用先进的编码技术和合理的参数来弥补低码率编码的不足
代码如下(示例):
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.4.4</version>
</dependency>
代码如下(示例):
public class VideoUtils {
private static final Logger log = LoggerFactory.getLogger(VideoUtils.class);
//转换后的视频格式
private static final String VIDEO_FORMAT = ".mp4";
public static void main(String[] args) throws Exception {
VideoUtils.convertToMp4(new File("D:\\cs\\test\\14.ts"));
}
/**
* 转换视频文件为mp4
* @param file 目标视频文件
*/
public static void convertToMp4(File file) throws FrameRecorder.Exception, FrameGrabber.Exception {
long startTime = System.currentTimeMillis();
log.info("开始进行ts格式转MP4。。。");
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file);
//视频比率,与清晰度有关
grabber.setVideoBitrate(2000000);
//转储后mp4文件地址
String fileName = file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + VIDEO_FORMAT;;
Frame frame = null;
FFmpegFrameRecorder recorder = null;
try {
grabber.start();
log.info("FFmpegFrameGrabber start已耗时:{}ms", (System.currentTimeMillis() - startTime));
recorder = new FFmpegFrameRecorder(fileName, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.setFormat(VIDEO_FORMAT);
recorder.setFrameRate(grabber.getFrameRate());
recorder.setVideoBitrate(grabber.getVideoBitrate());
recorder.start();
log.info("FFmpegFrameRecorder start已耗时:{}ms", (System.currentTimeMillis() - startTime));
long changeSize = 0L;
while ((frame = grabber.grabFrame()) != null) {
recorder.setTimestamp(grabber.getTimestamp());
recorder.record(frame);
changeSize++;
}
log.info("视频转换总耗时:{}ms, 完成帧数:{}", (System.currentTimeMillis() - startTime), changeSize);
log.info("转换后的视频地址:{}", fileName);
} catch (Exception e) {
e.printStackTrace();
}finally{
log.info("开始关闭FFmpegFrameGrabber、FFmpegFrameRecorder流链接。。。");
recorder.stop();
recorder.release();
grabber.stop();
}
}
}
/**
*
* url转字节
* @param urlPath http://xxx.com/xxxx/xx.ts
* @return 字节
* @throws Exception
*/
public static byte[] bbb(String urlPath) throws Exception {
URL url = new URL(urlPath);
//打开链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置请求方式为"GET"
conn.setRequestMethod("GET");
//超时响应时间为5秒 q
conn.setConnectTimeout(5 * 1000);
//通过输入流获取图片数据
InputStream inStream = conn.getInputStream();
byte[] data = readInputStream(inStream);
return data;
}
/**
* 文件转字节
* @param path "D://xxx/xxx.ts"
* @return
* @throws Exception
*/
public static byte[] ccc(String path) throws Exception {
File file = new File(path);
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n = 0;
while (-1 != (n = inputStream.read(buffer))){
outputStream.write(buffer,0,n);
}
return outputStream.toByteArray();
}
/**
* 通过输入流获得二进制数据
* @param inStream
* @return data 字节
* @throws Exception
*/
private static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//创建一个Buffer字符串
byte[] buffer = new byte[1024];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用一个输入流从buffer里把数据读取出来
while( (len=inStream.read(buffer)) != -1 ){
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
outStream.write(buffer, 0, len);
}
//关闭输入流
inStream.close();
//把outStream里的数据写入内存
return outStream.toByteArray();
}
/**
* 将二进制流转换为文件
* @param bytes fileName(自定义文件)
* @return
*/
public static String bytes2File(byte[] bytes,String fileName){
File file = new File(fileName);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try (FileOutputStream outputStream = new FileOutputStream(fileName);){
outputStream.write(bytes);
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
//ts为http url
byte[] bbb = bbb("http://xxx.com/xxxx/xx.ts");
//ts为本地路径
byte[] ccc = ccc("D:\\cs\\test\\14-28_0.ts");
// "D:\\cs\\cs\\cs.mp4" 自己创建的文件
bytes2File(bbb,"D:\\cs\\cs\\cs.mp4");
}
提示:这里对文章进行总结:
此次的业务是 通过ts的path 以mp4后缀下载到本地
/**
* 下载mp4文件
* @param response
* @param videoUrlPath 文件存在的路径“D/test/xxx.ts”
*/
@Override
public void downloadMp4(HttpServletResponse response, String videoUrlPath) {
try {
File file = new File(videoUrlPath);
String filename = file.getName();
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(videoUrlPath));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename.split("\\.")[0]+".mp4", "utf-8"));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/x-download");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}