Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java multimedia streaming via HTML5 video element

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?

like image 633
IAmYourFaja Avatar asked Feb 13 '23 00:02

IAmYourFaja


1 Answers

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);
}
}
like image 146
saganas Avatar answered Feb 15 '23 12:02

saganas