第一次写博客,望支持,
MP4、 AVI、RMVB、MKV、ASF、WMV、3GP、FLV等文件其实只能算是一种封装标准。
2 部分组成的。H264、Xvid等就是视频编码格式,MP3、AAC等就是音频编码格式。
例如:将一个Xvid视频编码文件和一个MP3视频编码文件按AVI封装标准封装以后,就得到一个AVI后缀的视频文件,这个就是我们常见的AVI视频文件了。
由于很多种视频编码文件、音频编码文件都符合AVI封装要求,则意味着即使是AVI后缀,也可能里面的具体编码格式不同。因此出现在一些设备上,同是AVI后缀文件,一些能正常播放,还有一些就无法播放。
同样的情况也存在于其他容器格式。即使RMVB、WMV等也不例外。部分技术先进的容器还可以同时封装多个视频、音频编码文件,甚至同时封装进字幕,如MKV封装格式。MKV文件可以做到一个文件包括多语种发音、多语种字幕,适合不同人的需要。
例如:MKV文件只要制作的时候同时加入国语和粤语发音的音轨和对应的简体、繁体字幕,播放的时候,你可以独立选择国语或粤语发音,并根据自己需要选择简体或繁体字幕,也可以选择不显示字幕。相当方便。
因此,视频转换需要设置的本质就是:A设置需要的视频编码、B设置需要的音频编码、C选择需要的容器封装。一个完整的视频转换设置都至少包括了上面3个步骤。
常用的有 Xvid,H264,MPEG1,MPEG2。
其中,!!!(重点)
FLV格式是一种新的视频格式,全称为FlashVideo。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等缺点。
所以要做视屏在线播放,需要传FLV格式的视频文件,思路就是:
上传视屏(下一篇文章说关于大附件上传的文章)——>
将视屏转码成FLV并截取视频指定秒数的截图,获取视频时长(用插件ffmpeg)——>
在本地存储,数据库存入路径——>
在线播放时,将FLV文件用Response发送给前端——>
前端用 vcastr3.swf(嵌入浏览器中的轻量级播放器)将其播放-------
上代码:这是写好的测试转码的代码,ffmpeg 文件官网上下载,下哪个静态版的
package com.webapp.test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class testExecuteCodecs {
public static void main(String[] args) throws Exception {
String ffmpegPath = "src/main/webapp/tools/ffmpeg/ffmpeg.exe";
String upFilePath = "C:/Users/mk/Desktop/床下有人dvdscr.rmvb";
String codcFilePath = "C:/Users/mk/Desktop/床下有人dvdscr.flv";
String mediaPicPath = "C:/Users/mk/Desktop/2018.jpg";
boolean a = executeCodecs(ffmpegPath, upFilePath, codcFilePath, mediaPicPath);
System.out.println("转码结果: "+(a==true?"成功":"失败"));
}
public static boolean executeCodecs(String ffmpegPath, String upFilePath, String codcFilePath,String mediaPicPath) throws Exception {
System.out.println("ffmpegPath--转码工具的存放路径: "+ffmpegPath);
System.out.println("upFilePath--转换格式的源文件: "+upFilePath);
System.out.println("codcFilePath--转换后的的文件: "+codcFilePath);
System.out.println("mediaPicPath--截图保存路径: "+mediaPicPath);
// 创建一个List集合来保存转换视频文件为flv格式的命令
List<String> convert = new ArrayList<String>();
convert.add(ffmpegPath); // 添加转换工具路径
convert.add("-i"); // 添加参数"-i",该参数指定要转换的文件
convert.add(upFilePath); // 添加要转换格式的视频文件的路径
convert.add("-qscale"); // 指定转换的质量
convert.add("6");
convert.add("-ab"); // 设置音频码率
convert.add("64");
convert.add("-ac"); // 设置声道数
convert.add("2");
convert.add("-ar"); //设置声音的采样频率
convert.add("22050");
convert.add("-r"); //设置帧频
convert.add("24");
convert.add("-y"); // 添加参数"-y",该参数指定将覆盖已存在的文件
convert.add(codcFilePath);
// 创建一个List集合来保存从视频中截取图片的命令
List<String> cutpic = new ArrayList<String>();
cutpic.add(ffmpegPath);
cutpic.add("-i");
cutpic.add(upFilePath); // 同上(指定的文件即可以是转换为flv格式之前的文件,也可以是转换的flv文件)
cutpic.add("-y");
cutpic.add("-f");
cutpic.add("image2");
cutpic.add("-ss"); // 添加参数"-ss",该参数指定截取的起始时间
cutpic.add("1"); // 添加起始时间为第1秒
cutpic.add("-t"); // 添加参数"-t",该参数指定持续时间
cutpic.add("0.001");// 添加持续时间为1毫秒
cutpic.add("-s"); // 添加参数"-s",该参数指定截取的图片大小
cutpic.add("800*600"); // 添加截取的图片大小为350*240
cutpic.add(mediaPicPath); // 添加截取的图片的保存路径
boolean mark = true;
//java的进程管理类
ProcessBuilder builder = new ProcessBuilder();
try {
builder.command(cutpic);
builder.redirectErrorStream(true);
// 如果此属性为 true,则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并,
// 因此两者均可使用 Process.getInputStream() 方法读取。这使得关联错误消息和相应的输出变得更容易
Process p = builder.start();
String info = read(p.getInputStream());
System.out.println("进程返回的信息:"+info);
String regexDuration = "Duration: (.*?),";
Pattern pattern = Pattern.compile(regexDuration);
Matcher m = pattern.matcher(info);
if (m.find()) {
//截取时间字符串
String time = m.group().substring(m.group().indexOf(" ")+1,m.group().indexOf(","));
System.out.println(time);
System.out.println(getTime(time));
}
//设置此进程生成器的操作系统程序和参数。
builder.command(convert);
//设置此进程生成器的 redirectErrorStream 属性。
builder.redirectErrorStream(true);
//使用此进程生成器的属性启动一个新进程。
builder.start();
} catch (Exception e) {
mark = false;
System.out.println(e);
e.printStackTrace();
}
return mark;
}
// 负责从返回信息中读取内容
private static String read(InputStream is) {
BufferedReader br = null;
StringBuffer sb = new StringBuffer();
try {
br = new BufferedReader(new InputStreamReader(is), 500);
String line = "";
while ((line = br.readLine()) != null) {
// System.out.println(line);
sb.append(line);
}
br.close();
} catch (Exception e) {
} finally {
try {
if (br != null)
br.close();
} catch (Exception e) {
}
}
return sb.toString();
}
//转换时间
public static int getTime(String t) {
String strs[] = t.split(":");
int min=0;
if (strs[0].compareTo("0") > 0) {
min+=Integer.valueOf(strs[0])*60*60;//秒
}
if(strs[1].compareTo("0")>0){
min+=Integer.valueOf(strs[1])*60;
}
if(strs[2].compareTo("0")>0){
min+=Math.round(Float.valueOf(strs[2]));
}
return min ;
}
}
播放时用Response将flv文件输出,参数Path 是flv文件存放的路径:
package cn.tedu.ttms.mk.controller.update;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.tedu.ttms.mk.service.UpdateFileService;
@Controller
public class LoadVideo {
@Resource
private UpdateFileService updateFileService;
@RequestMapping("/loadVideo.do")
@ResponseBody
public void execute1 (String Path, HttpServletResponse res)throws Exception{
File file = new File(Path);
OutputStream os = res.getOutputStream();
InputStream in = null;
ServletOutputStream out1 = null;
try {
in = new FileInputStream(file);
byte[] buffer = new byte[10 * 1024];
int length;
while ((length = in.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
System.out.println("文件读取失败,文件不存在");
e.printStackTrace();
} catch (IOException e) {
System.out.println("文件流输出异常");
e.printStackTrace();
} finally {
try {
in.close();
os.close();
} catch (IOException e) {
System.out.println("文件流关闭异常");
e.printStackTrace();
}
}
}
}
前端用
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>播放</title>
</head>
<body>
<object type="application/x-shockwave-flash" data="tools/vcastr3.swf"
width="650" height="500" id="vcastr3">
<param name="movie" value="tools/vcastr3.swf" />
<param name="allowFullScreen" value="true" />
<param name="FlashVars"
value="xml=
<vcastr>
<channel>
<item>
<source>192.168.0.1:8080/.....路径.....</source>
</item>
</channel>
</vcastr>" />
</object>
</body>
</html>
望大家多多鼓励!!!
要支持我哦!!!