如果我在Web服务器(Tomcat)中有一个文件并创建一个标签,我可以观看视频,暂停它,浏览它,并在完成后重新启动它。
但是如果我创建一个REST接口,在请求时发送视频文件,并将其URL添加到标签,我只能播放和暂停。 没有倒带,没有快进,没有导航,没有。
那么,有没有办法解决这个问题?我错过了什么地方吗?
视频文件与REST接口位于同一服务器,REST接口仅检查会话并在找到应发送的视频后发送视频。
这些是我迄今为止尝试过的方法。它们都有效,但没有一个允许导航。
/*
* This will actually load the whole video file in a byte array in memory,
* so it's not recommended.
*/
@RequestMapping(value = "/{id}/preview", method = RequestMethod.GET)
@ResponseBody public ResponseEntity<byte[]> getPreview1(@PathVariable("id") String id, HttpServletResponse response) {
ResponseEntity<byte[]> result = null;
try {
String path = repositoryService.findVideoLocationById(id);
Path path = Paths.get(pathString);
byte[] image = Files.readAllBytes(path);
response.setStatus(HttpStatus.OK.value());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(image.length);
result = new ResponseEntity<byte[]>(image, headers, HttpStatus.OK);
} catch (java.nio.file.NoSuchFileException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
return result;
}
/*
* IOUtils is available in Apache commons io
*/
@RequestMapping(value = "/{id}/preview2", method = RequestMethod.GET)
@ResponseBody public void getPreview2(@PathVariable("id") String id, HttpServletResponse response) {
try {
String path = repositoryService.findVideoLocationById(id);
File file = new File(path)
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename="+file.getName().replace(" ", "_"));
InputStream iStream = new FileInputStream(file);
IOUtils.copy(iStream, response.getOutputStream());
response.flushBuffer();
} catch (java.nio.file.NoSuchFileException e) {
response.setStatus(HttpStatus.NOT_FOUND.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
@RequestMapping(value = "/{id}/preview3", method = RequestMethod.GET)
@ResponseBody public FileSystemResource getPreview3(@PathVariable("id") String id, HttpServletResponse response) {
String path = repositoryService.findVideoLocationById(id);
return new FileSystemResource(path);
}
答案 0 :(得分:11)
处理非静态资源的简单解决方案:
@SpringBootApplication
public class DemoApplication {
private final static File MP4_FILE = new File("/home/ego/bbb_sunflower_1080p_60fps_normal.mp4");
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Controller
final static class MyController {
@Autowired
private MyResourceHttpRequestHandler handler;
// supports byte-range requests
@GetMapping("/")
public void home(
HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
request.setAttribute(MyResourceHttpRequestHandler.ATTR_FILE, MP4_FILE);
handler.handleRequest(request, response);
}
// does not support byte-range requests
@GetMapping(path = "/plain", produces = "video/mp4")
public FileSystemResource plain() {
return new FileSystemResource(MP4_FILE);
}
}
@Component
final static class MyResourceHttpRequestHandler extends ResourceHttpRequestHandler {
private final static String ATTR_FILE = MyResourceHttpRequestHandler.class.getName() + ".file";
@Override
protected Resource getResource(HttpServletRequest request) throws IOException {
final File file = (File) request.getAttribute(ATTR_FILE);
return new FileSystemResource(file);
}
}
}
(灵感来自Spring Boots LogFileMvcEndpoint,或多或少等于我后来发现的Paul-Warrens(@ paul-warren)StoreByteRangeHttpRequestHandler。
希望这是Spring在不久的将来会支持的内容,请参阅https://jira.spring.io/browse/SPR-13834(请投票赞成)。
答案 1 :(得分:5)
HTTP简历下载功能可能是您的朋友。我之前遇到过同样的问题。实施http范围后,可以在视频中导航:
http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html
答案 2 :(得分:3)
我知道这是一个老帖子,但是如果对其他人提出相同/类似的问题是有用的。
现在,像Spring Content这样的项目本身就支持视频流。最简单实现所需的所有代码都是: -
@StoreRestResource(path="videos")
public interface VideoStore extends Store<String> {}
这足以创建一个Java API和一组REST端点,允许您PUT / POST,GET和DELETE视频流。获取支持字节范围,并在HTML5视频播放器等中正常播放。
答案 3 :(得分:0)
事实上,正是前端显示&lt; video&gt;的视频控件。标签
每种特殊视频格式的浏览器都有一个默认控制面板。
您可以使用html和css通过媒体API创建自己的控件。 Media api
来自Div into HTML5 [默认情况下,&lt; video&gt; element不会暴露任何类型的玩家控件。您可以使用普通的HTML,CSS和JavaScript创建自己的控件。 &lt; video&gt; element具有play()和pause()等方法以及名为currentTime的读/写属性。还有读/写音量和静音属性。所以你真的拥有构建自己的界面所需的一切。]
答案 4 :(得分:0)
要支持Safari,您必须处理范围请求并提供正确的206返回码。 https://tools.ietf.org/html/rfc7233