Serve html page for video streaming in embedded Jetty

233 Views Asked by At

I have an embedded jetty application that has various endpoints, one of them is /stream/fileId and another one is /streamWithHTML/fileId.

The first one gets a file with the specified id from filesystem and starts writing its contents to the response, making use of the range headers to skip to different parts of the video.

The second endpoint is intended to do the same thing, except instead of the default browser player, i want my own custom player built with html.
This is the code i attempted to put together until now. This returns a web page but i dont know how to handle the video stream:

        response.setContentType("text/html");
        try {
            PrintWriter writer = response.getWriter();
            String filePath1 = "path/to/file";
            String encodedFilename = URLEncoder.encode(filePath1, StandardCharsets.UTF_8);
            
            // Get an html file and then print its contents after replacing a couple of parameters
            InputStream stream = getClass().getClassLoader().getResourceAsStream("HTML/VideoPlayer/index_template.html");
            String htmlPage = IOUtils.toString(stream, StandardCharsets.UTF_8);
            htmlPage = htmlPage.replace("$title", fileEntity1.fileName);
            htmlPage = htmlPage.replace("$video_source", encodedFilename);
            writer.println(htmlPage);
            writer.flush();
            writer.close();
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
        }

And this is the contents of the html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>$title</title>
</head>
<body style="background-color: #303030">

<video style="max-width: 100%; max-height: 100%;" src="$video_source"></video>

</body>
</html>

Note that $title and $video_source are just strings i use to correctly place some values when i serve the page.

Every solution i have tried or have seen up until now, is to serve a static video, but it is not possible for me, since the video is saved on a database.

Additional note: the video must be accessible from outside through only one endpoint, which will be the one with the html page, so putting the video on one endpoint and then serving i in the html of another request is not an option for me.

1

There are 1 best solutions below

2
Joakim Erdfelt On

The $video_source is just an HTTP request to a specific resource on your webserver. (it could be /videos/67328148734529)

It will be up to you to implement that specific resource endpoint on your webserver. Typically as an HttpServlet. (in the above example, your endpoint would be on url-pattern /videos/*, and you would use the request.getPathInfo() on your servlet to obtain the video id that is being requested by the browser)

Some things you'll be on the hook to handle.

  1. Honor the limitations put on your response by the various Accept headers on the request.
  2. Provide the correct Content-Type response.
  3. Honor the various HTTP range request headers to know where in the video content you should serve.
  4. Produce the correct HTTP range response headers to indicate to the browser where the content being responded to is coming from.
  5. Stream this video content from your database to your response to the request.

You should consider not using a general database for the video content itself, it makes for a terribly inefficient experience, as most database blob requests don't support range requests efficiently (especially with the nuances of HTTP range requests and multipart/byteranges responses).

A common technique is to put the video in it's raw form on a storage device (hdd, ssd, cdn, etc) with a UUID style name, and have the database reference the UUID name, and other metadata. That way you serve from storage to network efficiently.