First of all, do not let the title deceive you — it will not be simple println(“Hello world”) but with Actor System. Today, we will implement your first (sorry if I assumed wrongly) video streaming service. Namely, I will use Akka HTTP and Streams to create a REST API capable of streaming a video file, in mp4 format, in a way that matches the expectations of HTML5 <video> tag. Besides, I will also add a few words about Akka and some components like Akka Streams to give you some theoretical background before you start coding. But first, one question.

Why Video Streaming?

There are three main reasons behind choosing video streaming as the topic for today’s article. The first one is that it is an absorbing and complex subject for me, especially on a large scale (like Netflix) and I have always wanted to learn more about it. The next reason is that it is a niche topic, so a project based around video streaming can be a great addition to anyone’s portfolio - this one is especially important for people who want to start their journey with Scala and Akka. Last but not least it is very interesting way to get familiar with Akka Streams, which in fact makes this whole operation much easier.

After this brief introduction, we can move to the first of the main topics for today.

What Is Akka And Is It Tasty?

In general, it is an open-source toolkit whose aim is to make the creation of multi-threaded and distributed applications easy and also provide runtime for such applications. Akka-based systems tend to scale very, very well. Akka is based around Actor Model and actor-based concurrency and draws lots of inspiration from Erlang. It is written in Scala but provides DSLs for both Scala and Java.

When it comes to the tastiness of Akka, if you prefer eating your source code then for sure it is very tasty. If you want to learn more about Akka I recommend starting from reading this.

Here most of the source code will be based around HTTP and Streams features and there will be almost no features from the standard Akka Actors package.

When we cover the absolute basics of Akka we can dive deeper into today’s text.

What Is Akka Streams?

Akka Streams are simply a package built on top of normal Akka Actors to help us with the processing of infinite (or finite but very, very large) sequences of data. The main motivation behind the creation of Akka Streams was problems with the correct configuration of actors in the actor system to achieve a stable flow of streamed data.

An important fact is that Akka Streams have a built-in back-pressure mechanism. Thanks to that one of the most complex problems in the streaming world, configuring the producer to react correctly when the consumer cannot keep up with load, is taken care of by a tool you use and you do not have to care about it too much.

Additionally, Akka Streams provides an API that is compliant with interfaces required by Reactive Streams SPI. As a side note, it is worth noting that Akka itself is one of the founding members of the Reactive Stream initiative.

Akka Streams checked so now we can jump to the next part of the theory.

What Is Akka HTTP?

Similarly to Akka Streams, it is a package provided by Akka creators. It is built on top of Akka Streams and Akka Actors and it helps you to interact with outside worlds via HTTP. It provides both sides of HTTP stack, so you can build a REST API and you can use it as HTTP client for sending requests to some external service.

So now, when you have some basic understating of tools which we will use to implement our backend, the last thing left to describe is the most important part of our application’s frontend.

Details Of HTML5

It is a new tag introduced in HTML 5 to replace adobe video player. As you may guess, its main responsibility is to embed media player, capable of playing videos, into an HTML document. The idea is very similar to plain old <img> tag.

Inside <video> tag you place <source> tag with two important attributes. The first one is **src **attribute used to point out video which we want to display. The second important field is type, responsible for keeping our video format

You can also write some text inside <video> </video> tags and it will be used as fallback in browsers that do not support the element. As for now, even Internet Explorer supports it so this scenario is almost impossible.

How Streaming With HTML

Although it sounds complex at the first glance, after some reading it becomes quite easy. Almost everything is ready and we only have to integrate different components.

On the backend side, most of the heavy lifting will be done by FileIO object, which will emit events chunked part of our file. Of course, the size of chunked elements is configurable. Moreover, the starting position is also configurable which will allow us to start playing our video from a certain point, not exactly from the beginning. All these, features are perfectly suited for <video> tag performing HTTP GET request with Range header to play video without downloading it first.

Examples of requests made by HTML video:

For anyone interested, request header – Range:bytes=x- is responsible for picking the starting position of our video. The first request will be send at the beginning of processing video while the second one can be sent when you decide to move to a certain point on the video timeline.

With this lengthy introduction, it is finally time for some coding. Are you happy?

Let’s Write Streaming Service

In the next few paragraphs, I will implement the backend of our streaming service and then I will create a simple web page in HTML to verify if it works correctly.

Because I like doing assumptions, I assumed that anyone interested knows some basics of Scala and SBT.

1. We will add all necessary dependencies to our **build.sbt **file, for this project we will need only 3 packages: akka-httpakka-actor-typed (in theory, package akka-actor is enough but remember to always type safe), akka-stream.

Scala

2. Now we can create the main class responsible for starting our application. I choose to extend App — for me, it is more convenient than creating main method. In the next step, we will put there Actor System and HTTP server starters.

Scala

3. After creating the main class we can add the code mentioned in previous step.

Scala

As for now, such configuration is enough. In the last step, we will add the call of bind method at the end to expose our REST API. The current configuration will run Actor System with name akka-video-stream and HTTP server on port 8090 of your local machine. Remember not to omit implicit keyword near Actor System definition, as such implicit parameter is required by signature of Http method.

4. Here we will finally implement REST API endpoint used to process requests from <video> tag.

Scala

As you can see, I have created an endpoint with URL “api/files/default”. It checks if **Range **header is present in request. If our server is able to find it, the client will get a response with code 200 (OK), otherwise, we return a response with code 416 (Range Not Satisfiable).

5. The fifth step is perfect for implementing the method which is the main course of the whole article.

Scala

Here I have done a few things:

  • I have loaded the file I want to stream to the application, then based on the header from quest and file info I have calculated starting point of streaming and Content Range response header.
  • With help of FileIO I have created a stream from the previously loaded file. Then I used this stream as data in HttpEntity.
  • I have created HttpResposne with code 206 (Partial content), headers and responseEntity as body.

I also want to describe FileIO in more details as it is the most magical thing in this article. So, what exactly happened in this line: FileIO.fromPath(file.toPath, 1024, start) ?

It created Source (Akka Streams counterpart of Producer from Reactive Streams) from the content of file under the provided path. Each element emitted by the source will have exactly 1 MB of size. The first emitted element will be in the position marked by the start parameter, so if you set 0 as the start parameter value, the first emitted element will be the first MB of file under the provided path.

6. As we have implemented the main magic of today, we have to refactor our app to be able to use it.

We will start from changes in REST API definition:

complete(HttpResponse(StatusCodes.Ok)) => complete(stream(range))

So now instead, of simply returning OK, we call our stream method with range as a parameter and start streaming.

We have to remember that our API is still not exposed so we have to do the following modification to the fragment responsible for starting HTTP server.

Http().newServerAt(host, port) =>Http().newServerAt(host, port).bind(Streamer.route)

Et voila, now we have working backend and our REST API is accessible for anyone interested. Now we just have to test it.

#java #tutorial #scala #html #akka #streaming #streams

Video Streaming With Akka Streams
1.70 GEEK