Site icon Vinsguru

Spring WebFlux Video Streaming

spring webflux video streaming

Overview:

In this tutorial, Let’s build a simple application to stream video files with Spring WebFlux Video Streaming. It is going to be a lot simpler than you think as Spring does all the heavy lifting for us. (You do not have to serve the static content as shown in this post. It is a simple fun project to demonstrate how Spring WebFlux works here.)

Video Streaming:

When you watch a movie via Netflix or a video tutorial via YouTube, the browser client does NOT download the whole video content. It gets some content first. While it is playing the content, it also gets next few chunks in a streaming fashion. So that we keep the user engaged with the video as soon as he clicks on some video, instead of having the user to wait for whole content to download.

Often times, the users will also try to watch the video somewhere in the middle by clicking/dragging the seek bar as shown above. In this case, there is no need in getting the video chunks from the beginning. Instead, the client will request the server to serve the video content from a specific byte index. The server will accept the byte range requests and serve the content accordingly.

This is what we are going to build 🙂

Sample Application:

Our application will serve video content. We will have a simple HTML UI. When the user clicks on the play button, the server will receive the request and play the content.

The user can adjust the seek bar to watch the video from any moment.

Project Setup:

<video src="video/tom-jerry" width="720px" height="480px" controls preload="none">

</video>

Spring WebFlux Video Steaming:

@Service
public class StreamingService {

    private static final String FORMAT = "classpath:videos/%s.mp4";

    @Autowired
    private ResourceLoader resourceLoader;

    public Mono<Resource> getVideo(String title) {
        return Mono.fromSupplier(() -> this.resourceLoader.getResource(String.format(FORMAT, title)));
    }

}
@RestController
public class StreamingController {

    @Autowired
    private StreamingService service;

    @GetMapping(value = "video/{title}", produces = "video/mp4")
    public Mono<Resource> getVideo(@PathVariable String title, @RequestHeader("Range") String range) {
        System.out.println(range);
        return service.getVideo(title);
    }

}

Thats it. It is very simple. Run the application.

Spring WebFlux Video Steaming – Demo:

Let’s first see how it works behind the scenes.

curl http://localhost:8080/video/tom-jerry -i -H "Range: bytes=0-500"
2021-08-22 16:02:08.845  INFO 25964 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080
2021-08-22 16:02:08.864  INFO 25964 --- [           main] c.v.w.WebfluxVideoStreamingApplication   : Started WebfluxVideoStreamingApplication in 2.006 seconds (JVM running for 2.455)
bytes=0-500
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Type: video/mp4
Content-Range: bytes 0-500/21589849
Content-Length: 501

 ftypisomisomiso2avc1mp4freeG%�mdatQ�e��7�U5ŀ��h�S0Pjʃj-h<��*s����Rll����J��$�;ŗ*)��uw���9_� 5R180qu�+N@+{Ir�*��8?���́�€��9��˳��2��n��{�ּ5��(�VQ
�
�R�=��l�C�
 ��{Zϸ����d>T~pPj�P
�3�Y��p:�])`�xL�b}A92o�����c}Ǵ��j
                                   ���l�,�2�څ����!<~��G��$aPx:P������%����(8w����V�_��'0�V�q�����,v��(�X��E�Џ��v9$@?�
7��ww

�h�
    {
2����"�2IɌ�x�LJ��"����V"���r�5�=��������+}�z�������⼸#
                   ���^������!;����"�����p�%

Functional Endpoint:

Spring WebFlux also supports functional endpoint.  Instead of RestController, we can also serve the content with functional endpoints as shown below.

@Configuration
public class FunctionalEndPointConfig {

    @Autowired
    private StreamingService service;

    @Bean
    public RouterFunction<ServerResponse> router(){
        return RouterFunctions.route()
                .GET("fun-ep/video/{title}", this::videoHandler)
                .build();
    }

    private Mono<ServerResponse> videoHandler(ServerRequest serverRequest){
        String title = serverRequest.pathVariable("title");
        return ServerResponse.ok()
                .contentType(MediaType.valueOf("video/mp4"))
                .body(this.service.getVideo(title), Resource.class);
    }

}
<video src="fun-ep/video/tom-jerry" width="720px" height="480px" controls preload="none">

</video>

Summary:

We were able to successfully demonstrate Spring WebFlux Video Streaming. We also learnt that we do not have do anything special to handle the HTTP Range requests as Spring takes care of that.

The source code is available here.

Learn more about Spring WebFlux.

 

Share This:

Exit mobile version