java支持html5视频流技术Pseudostreaming
2016-03-15 15:13
691 查看
伪流技术是一种能在常见HTTP服务器如APACHE、tomcat、IIS或lighttpd上安装提供的一种协议。它使用服务端脚本来提供客户端到服务器的视频交互。播放器在URL上携带start time的参数发送HTTP请求到服务端,服务端的脚本处理视频流并且给予回复,保证提供的视频流起始位置与START TIME参数所对应。这个start time的参数通常命名为“start”,这个技术同样被风靡全球的youtube所使用,它使用的是lighttpd WEB服务器。
对于播放器来说,使用伪流或其他流式的解决方案最大的好处是:能跳转到尚未下载到的视频部分。这种情况在很符合大文件播放需求,比如2个小时的视频,用户想立刻跳转到它的后面部分开始播放,(这样不需要下载中间用户不关心的部分了)。好处如下:
能够随机跳转到视频的任意时间
从视频的中间开始播放
提供客户方流媒体服务器和服务端脚本集成的可能
支持FLV和H.264的视频
直到现在,仍然不存在一项旨在网页上显示视频的标准。
今天,大多数视频是通过插件(比如 Flash)来显示的。然而,并非所有浏览器都拥有同样的插件。
HTML5 规定了一种通过 video 元素来包含视频的标准方法。
Ogg = 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件
MPEG4 = 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件
WebM = 带有 VP8 视频编码和 Vorbis 音频编码的 WebM 文件
由于使用了Nio请使用jdk7以上版本
注意此处配置了视频文件的保存目录,需要根据实际情况进行修改
注意根据目录下的文件修改请求文件名 示例中为美丽的风景
由于IE对html5的兼容性较差,ie9以上才支持mp4格式,其它版本可以使用flash进行播放
对于播放器来说,使用伪流或其他流式的解决方案最大的好处是:能跳转到尚未下载到的视频部分。这种情况在很符合大文件播放需求,比如2个小时的视频,用户想立刻跳转到它的后面部分开始播放,(这样不需要下载中间用户不关心的部分了)。好处如下:
能够随机跳转到视频的任意时间
从视频的中间开始播放
提供客户方流媒体服务器和服务端脚本集成的可能
支持FLV和H.264的视频
直到现在,仍然不存在一项旨在网页上显示视频的标准。
今天,大多数视频是通过插件(比如 Flash)来显示的。然而,并非所有浏览器都拥有同样的插件。
HTML5 规定了一种通过 video 元素来包含视频的标准方法。
Ogg = 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件
MPEG4 = 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件
WebM = 带有 VP8 视频编码和 Vorbis 音频编码的 WebM 文件
package com.roden.video; import java.io.IOException; import java.io.OutputStream; import java.net.URLDecoder; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import static java.nio.file.StandardOpenOption.READ; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public final class PseudostreamingServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final int BUFFER_LENGTH = 1024 * 16; private static final long EXPIRE_TIME = 1000 * 60 * 60 * 24; private static final Pattern RANGE_PATTERN = Pattern.compile("bytes=(?<start>\\d*)-(?<end>\\d*)"); private String videoPath; @Override public void init() throws ServletException { videoPath = getInitParameter("videoPath"); } @Override protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } private void processRequest(final HttpServletRequest request, final HttpServletResponse response) throws IOException { String videoFilename = URLDecoder.decode(request.getParameter("video"), "UTF-8"); Path video = Paths.get(videoPath, videoFilename); int length = (int) Files.size(video); int start = 0; int end = length - 1; String range = request.getHeader("Range"); range=range==null?"":range; Matcher matcher = RANGE_PATTERN.matcher(range); if (matcher.matches()) { String startGroup = matcher.group("start"); start = startGroup.isEmpty() ? start : Integer.valueOf(startGroup); start = start < 0 ? 0 : start; String endGroup = matcher.group("end"); end = endGroup.isEmpty() ? end : Integer.valueOf(endGroup); end = end > length - 1 ? length - 1 : end; } int contentLength = end - start + 1; response.reset(); response.setBufferSize(BUFFER_LENGTH); response.setHeader("Content-Disposition", String.format("inline;filename=\"%s\"", videoFilename)); response.setHeader("Accept-Ranges", "bytes"); response.setDateHeader("Last-Modified", Files.getLastModifiedTime(video).toMillis()); response.setDateHeader("Expires", System.currentTimeMillis() + EXPIRE_TIME); response.setContentType(Files.probeContentType(video)); response.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, length)); response.setHeader("Content-Length", String.format("%s", contentLength)); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); int bytesRead; int bytesLef 4000 t = contentLength; ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH); try (SeekableByteChannel input = Files.newByteChannel(video, READ); OutputStream output = response.getOutputStream()) { input.position(start); while ((bytesRead = input.read(buffer)) != -1 && bytesLeft > 0) { buffer.clear(); output.write(buffer.array(), 0, bytesLeft < bytesRead ? bytesLeft : bytesRead); bytesLeft -= bytesRead; } } } }
由于使用了Nio请使用jdk7以上版本
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>stream</servlet-name> <servlet-class>com.roden.video.PseudostreamingServlet</servlet-class> <init-param> <param-name>videoPath</param-name> <param-value>F:/BaiduYunDownload/</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>stream</servlet-name> <url-pattern>/stream</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> </web-app>
注意此处配置了视频文件的保存目录,需要根据实际情况进行修改
<!DOCTYPE html> <html> <head> <title>HTML5 Video Pseudostreaming</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="//code.jquery.com/jquery-1.12.0.min.js"></script> <script> $(document).ready(function(){ var video = $('#myvideo'); $("#play").click(function(){ video[0].play(); }); $("#pause").click(function(){ video[0].pause(); }); $("#go10").click(function(){ video[0].currentTime+=10; }); $("#back10").click(function(){ video[0].currentTime-=10; }); $("#rate1").click(function(){ video[0].playbackRate+=2; }); $("#rate0").click(function(){ video[0].playbackRate-=2; }); $("#volume1").click(function(){ video[0].volume+=0.1; }); $("#volume0").click(function(){ video[0].volume-=0.1; }); $("#muted1").click(function(){ video[0].muted=true; }); $("#muted0").click(function(){ video[0].muted=false; }); $("#full").click(function(){ video[0].webkitEnterFullscreen(); // webkit类型的浏览器 video[0].mozRequestFullScreen(); // FireFox浏览器 }); }); </script> </head> <body> <video id="myvideo" width="80%" height="80%" controls="controls"> <source src="stream?video=美丽的风景.mp4" /> <!--<source src="stream?video=美丽的风景.mp4" type="video/mp4" /> <source src="stream?video=美丽的风景.mp4" type="video/webM" /> <source src="stream?video=美丽的风景.mp4" type="video/ogg" />--> 你的浏览器不支持html5 </video> <hr> <button id="play">播放</button> <button id="pause">暂停</button> <button id="go10">快进10秒</button> <button id="back10">快退10秒</button> <button id="rate1">播放速度+</button> <button id="rate0">播放速度-</button> <button id="volume1">声音+</button> <button id="volume0">声音-</button> <button id="muted1">静音</button> <button id="muted0">解除静音</button> <button id="full">全屏</button> </body> </html>
注意根据目录下的文件修改请求文件名 示例中为美丽的风景
由于IE对html5的兼容性较差,ie9以上才支持mp4格式,其它版本可以使用flash进行播放
相关文章推荐
- HTML5中在客户端验证文件上传的大小
- html5 web数据存储
- Canvas 在高清屏下绘制图片变模糊的解决方法
- 视频分割 Ultra Video Splitter V4.0.4 汉化版 下载
- 原生js结合html5制作小飞龙的简易跳球
- User Scripts: Video Download by User Scripts
- HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
- 三个不常见的 HTML5 实用新特性简介
- 低版本IE正常运行HTML5+CSS3网站的3种解决方案
- js+HTML5实现canvas多种颜色渐变效果的方法
- javascript+HTML5的Canvas实现Lab单车动画效果
- javascript+html5实现绘制圆环的方法
- javascript html5实现表单验证
- HTML5实现微信拍摄上传照片功能
- JavaScript+html5 canvas制作的百花齐放效果完整实例
- jQuery+HTML5加入购物车代码分享
- jQuery mobile 移动web(6)
- 基于Jquery和html5的7款个性化地图插件
- 实现音乐播放器的代码(html5+css3+jquery)