通过HTML5video元素的Java多媒体流

我试图让我的Java后端将video文件(MP4等)“流”到浏览器。 我担心我必须编写非常复杂的,低级实用的NIO类型代码,例如:

public class VideoController extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) { File f = new File("/opt/videos/video19394.mp4"); PrintStream ps = resp.getWriter(); while(still reading f) { writeTheVideoBytesToStream(f, ps); } } } 

似乎这一切都是用HTML5 元素处理的( 是的?? )。 这样,从客户端,我可以指定:

  

然后,在服务器端,即使是像web.xml这样简单的东西,我也可以指定URL请求之间的映射,如http://myapp.example.com/videos/19394和位于服务器上的MP4文件在/opt/videos/video19394.mp4 。 而元素只是自动处理事情。

我在这里是否正确,或者即使我使用 ,我还需要在服务器上实现低级别的字节/套接字流式传输吗?

您可以使用Spring Boot框架,只需从REST端点提供InputStream。 这样也可以使用HTML5中的video标签进行滚动。

代码看起来像这样:

 @RequestMapping(value = "videos/file-name", method = GET) @ResponseBody public final ResponseEntity retrieveResource(@PathVariable(value = "file-name") final String fileName, @RequestHeader(value = "Range", required = false) String range) throws Exception { long rangeStart = Longs.tryParse(range.replace("bytes=","").split("-")[0]);//parse range header, which is bytes=0-10000 or something like that long rangeEnd = Longs.tryParse(range.replace("bytes=","").split("-")[0]);//parse range header, which is bytes=0-10000 or something like that long contentLenght = ;//you must have it somewhere stored or read the full file size InputStream inputStream = Resources.getResource(fileName).openStream();//or read from wherever your data is into stream HttpHeaders headers = new HttpHeaders(); headers.setContentType("video/mp4"); headers.set("Accept-Ranges", "bytes"); headers.set("Expires", "0"); headers.set("Cache-Control", "no-cache, no-store"); headers.set("Connection", "keep-alive"); headers.set("Content-Transfer-Encoding", "binary"); headers.set("Content-Length", String.valueOf(rangeEnd - rangeStart)); //if start range assume that all content if (rangeStart == 0) { return new ResponseEntity<>(new InputStreamResource(inputStream), headers, OK); } else { headers.set("Content-Range", format("bytes %s-%s/%s", rangeStart, rangeEnd, contentLenght)); return new ResponseEntity<>(new InputStreamResource(inputStream), headers, PARTIAL_CONTENT); } } 

正如@saganas所建议的那样,您需要实现一个支持字节范围请求的控制器。 但是, Spring Content支持开箱即用的video流(即字节范围支持),并提供非常简单的编程接口。 例如,将Spring Content用于文件系统,您可以通过在代码中定义单个界面来创建video流服务。 而已。

这是如何做。 通过start.spring.io或通过IDE spring项目向导(编写本文时的Spring Boot 1.5.10)创建一个新的Spring Boot项目。 添加以下Spring Boot / Content依赖项,以便最终得到以下内容: –

    org.springframework.boot spring-boot-starter   org.springframework.boot spring-boot-starter-web   javax.servlet servlet-api 2.3    com.github.paulcwarren spring-content-fs-boot-starter 0.0.9   com.github.paulcwarren spring-content-rest-boot-starter 0.0.9   org.springframework.boot spring-boot-starter-test test   

在Spring Boot Application类中,创建VideoStore接口。 这会导致Spring Content注入一个java实现(此接口)以及REST端点,这意味着您不必担心自己编写这些:

  @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @StoreRestResource(path="videos") public interface VideoStore extends Store {} } 

注意: – 默认情况下,Spring Content将在java.io.tmpdir下创建一个商店,因此您还需要将SPRING_CONTENT_FS_FILESYSTEM_ROOT环境变量设置为指向“商店”的根目录。

将您的video放入此“根”位置。 启动应用程序,您的video将可以从以下链接流式传输: –

/videos/ExampleVideo.mp4

Spring Content也支持其他“存储”。 比如S3。 所以你不必使用文件系统。 但它非常适合快速启动和运行。 如果您确实想要使用其他存储,则只需切换正确的Spring Content依赖项即可。