I am trying to allow my Java backend to "stream" video files (MP4, etc.) to browsers. I was worried that I would have to write really complicated, low-level-practically-NIO type code like:
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);
}
}
}
But it seems like this is all taken care of with the HTML5 <video/>
element (yes??). This way, from the client-side, I can just specify:
<video width="500" height="500" url="http://myapp.example.com/videos/19394" />
And then, on the server-side, even in something as simple as web.xml
, I can just specify the mapping between URL requests like http://myapp.example.com/videos/19394
and the MP4 file located on the server at /opt/videos/video19394.mp4
. And the <video/>
element just takes care of things automagically.
Am I correct here, or even if I used <video/>
, would I still need to implement low-level byte/socket streaming stuff on the server?
You can use Spring Boot framework and just serve an InputStream from your REST endpoint. This will allow to scroll using video tag in HTML5 as well.
The code would look like something like this:
@RequestMapping(value = "videos/file-name", method = GET)
@ResponseBody
public final ResponseEntity<InputStreamResource>
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With