Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to proxy a HTTP video stream to any amount of clients through a Spring Webserver

Provided that I have a video HTTP stream broadcasted on a server that is on the same network as my Spring Webserver is, for instance in some url such as:

http://localhost:9090/httpstream

How can I proxy this video stream to any amount of clients, using Spring? The following example demonstrates the wanted flow:

  1. Spring webserver can be found at http://localhost:9091/spring
  2. A client wants to access a video stream, so he connects his video-stream-player to http://localhost:9091/spring (the spring webserver)
  3. The Spring WebServer should redirect the stream found on http://localhost:9090/httpstream to the client, with the latter never knowing that he accessed the httpstream host. The connection is made by Spring, not by the client

This is needed because the HTTPStream is an unsecured and not authenticated host, and I wanted to wrap it around a Spring Webserver, so that I could use some form of Security, such as a Basic Auth.


I tried requesting some form of mapping, but I couldn't find what kind of object to return, nor how to make the connection, but the expected behaviour should be something like this:

@Controller
public class HttpStreamProxyController {

    @RequestMapping("/spring") {
    public /*Stream Object?*/ getSecuredHttpStream() {
       if (clientIsSecured) {
       //... Security information

       return   //What should be returned?
       }
   }
}
like image 744
LeoColman Avatar asked Nov 14 '17 04:11

LeoColman


1 Answers

I am not sure what kind of source you are using for generating your video stream (live camera or a video file or youtube video or ..)

You can probably use StreamingResponseBody (requires Spring 4.2+). Refer following links

http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/streaming-response-body/

http://shazsterblog.blogspot.in/2016/02/asynchronous-streaming-request.html

Try this -

    @GetMapping("/stream1")
        @ResponseBody
        public StreamingResponseBody getVidoeStream1(@RequestParam String any) throws IOException {
            /* do security check before connecting to stream hosting server */ 
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<Resource> responseEntity = restTemplate.exchange( "http://localhost:8080/stream", HttpMethod.GET, null, Resource.class );
            InputStream st = responseEntity.getBody().getInputStream();
            return (os) -> {
                readAndWrite(st, os);
            };


    }

private void readAndWrite(final InputStream is, OutputStream os)
            throws IOException {
        byte[] data = new byte[2048];
        int read = 0;
        while ((read = is.read(data)) > 0) {
            os.write(data, 0, read);
        }
        os.flush();
    }

It should work. You can write your own implementation of readAndWrite() depending on your requirements.

So, your spring proxy controller could be something like this...

@Controller
public class HttpStreamProxyController {

    @RequestMapping("/spring") 
    @ResponseBody
    public StreamingResponseBody  getSecuredHttpStream() {
       if (clientIsSecured) {
       //... Security information

    RestTemplate restTemplate = new RestTemplate();
    // get video stream by connecting to stream hosting server  like this
            ResponseEntity<Resource> responseEntity = restTemplate.exchange( "https://ur-to-stream", HttpMethod.GET, null, Resource.class );
            InputStream st = responseEntity.getBody().getInputStream();
    // Or if there is any other preferred way of getting the video stream use that. The idea is to get the video input stream    

    // now return a StreamingResponseBody  object created by following lambda 
            return (os) -> {
                readAndWrite(st, os);
            };

       } else {
          return null;
       }

   }
}

The StreamingResponseBody returned by your rest endpoint will work fine with HTML5, which could be something like ..

<video width="320" height="240" controls>
  <source src="/spring" type="video/mp4">
  Your browser does not support the video tag
</video>
like image 174
vsoni Avatar answered Oct 15 '22 17:10

vsoni