第一次写博客,望支持,


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>


望大家多多鼓励!!!
要支持我哦!!!