VIdeo streaming service in Django, Node.js or Phoenix?

I am developing a service which builds around video streaming. The streaming happens behind a paywalled Login-Layer, so the usage patterns are pretty predictable. I am currently evaluating which technology stack I want to use.

I already developed applications in PHP (long ago) and Python Django (not so long ago). I know that I am very productive with Django. Nevertheless I love learning new things and Elixir looks like a lot of fun to me, especially since I enjoy functional programming but was never able to use it for a real-world project. Therefore I would really like to use it. A third option is to use node.js (with the NestJS framework) since I can then integrate frameworks like Next/Nuxt if I want to do a SPA that is partially Server side rendered.

My main question is the following:

  1. I never did video streaming. Naively I would think that all you need to do is to put your videos on a CDN and then embed them with an html5 video tag. Where am I wrong here and specifically are there any obvious upsides/downsides of Django/Node.js/Phoenix when doing video streaming?

I also have some more questions:
2. Why do people here use Liveview instead of making React/Vue SPA as everyone else is right now? What are the benefits of each of these paradigms against the plain “oldschool” Server-Side-Rendered approach?
3. Is Phoenix still a good choice if I do not need Liveview but just want to make a backend-API for a frontend SPA?
4. How easy is deployment to AWS with elixir? With Django and Node AWS has official guides, for Phoenix it does not.

Hello! :wave:

Let’s jump into your main question! Video streaming could be live or not, in a live scenario, you would have many clients (the viewers) subscribing to a socket and a sender (the streamer). In this you would have to capture the frames from the sender transcode it, inevitably using C/C++ no matter the language, and send to all subscribers of the socket. Elixir is really good at managing sockets and connections in a clean way. See the membrane framework
Now if you want to have users uploading videos and others watching, like an youtube, you could start with any language since it is a CRUD application with upload of files, the hard part comes into splitting the video to better buffer and have multiple resolutions, again probably done with C/C++.

The other questions:

We tend to use LiveView because it does not require specialized knowledge at yet another stack, from starting, developing, testing, deploying, for just some dynamic parts in the application. Other point for liveview is that the server keeps the truth about the state of all clients, and all changes from one client can be seen by the others, there is no need for synchronization in the client side.

Yes Phoenix is still a great choice for APIs, it has great response times, easy to use and integrates well with the ecosystem, you are not bound by the framework. By the nature of Elixir/BEAM you can write synchronous code that runs asynchrony. Get Django for example, at each route you write straightforward code, there is no need for callbacks are special keywords, same for Elixir, but there no GIL, all requests run concurrently with each other, providing a fair response time for all independent of load, you are not going to see simple requests getting stomped because someone decided to upload a gigantic video.

I’m no expert in releases with Elixir, but you can generate an artifact easy with mix release, install erlang on your virtual machine on AWS and dump the artifact there. Going to run on Docker? easier! There are lot of guides and tutorials covering deploying in various providers, including docker.

Hope this helps shed some light.

3 Likes

Thank you for the detailed answer!

I meant video watching a la YouTube, not a streaming service. That was badly worded from my side. Ok, then basically I would have the users upload the videos, then run some script that I’d have to write in a lower level language maybe (although Python probably has ready-made libraries for converting videos between resolutions?) to create the videos of different resolutions. But that could be done as an AWS Lambda task I guess anyway, so I am not bound by a language for that task. Then I deploy the videos to Amazon S3 or a CDN and just paste the links into html5 video tags, right? Or is this still very simplified?

About Liveview: Having interactive user interfaces without another stack of course sounds great, thank you. But do I understand it right, that this means that I will probably have way more server load than if using a JS-Framework for interactivity? The JS Framework would let the client computer do all the lifting and degrade my server to a pure data-fetching/sending API whereas with something as Liveview I would have server load for every time something on the client side changes and keep a connection to every client alive all the time? That sounds expensive (processing-wise and also money-wise if I am hosting on AWS).
I see the advantage of having the full client side on the server for some applications. But in my case I don’t need that for now. Do I understand it right that then I would probably not choose Liveview but just do a pure API?

The flow of my application is basically this: Person A uploads video. Other Peoples B, C, … watch videos, make annotation (comments etc) for Person A. A few days later Person A reviews the annotations and I maybe give some nice tools to make the reviewing process more pleasant.

I’ll throw my 2 cents on the deploying to aws question.
From my experience with it (only deployed 3 apps to ec2 so far), it’s simple enough if you know your way around AWS. Basically make a release and rsync it with aws.

I’m not using docker as my dev box is similar to the hosts, but I feel that the docker part is well covered (there’s a few docker file examples here on the forum).

1 Like

While you see many examples of LiveView being used for pure interactivity with the user, you shouldn’t use it for that propose. I mean anything in the client side that is only DOM manipulation and doesn’t require data from the backend must be left to be handled purely in the client side with JS framework of your choice, including VanillaJS as I like to use. If you do it with LiveView and the user is commuting by train, car or just have a slow internet connection, then things like animating a menu or a modal will look sluggish.

So, in my opinion you should use only LiveView to interact with the user when you need to fetch or send data to the backend. This is where LiveView excels, because it avoids duplication of business logic in the backend and in the client side.

LiveView uses an Elixir process per client connected to the backend, and they have a very small footprint on the server. You can run thousands of them or even millions, depending on the memory capacity on your server. Also, live view only sends the html when the connection is established and afterwards it only sends the data that has changed, thus the bytes transferred between client and server have a very small footprint and allow for very fast network round trips between client and server.

I would recommend you to take this LiveView free course:

It does an excellent job in explaining the mechanics being used and how it compares to SPAs. This was the course that made LiveView to click for me :slight_smile:

This course is provided by @mikeclark and you have a dedicated forum post for it:

The Programming Phoenix 1.4 book walks you through building a web app that allows you to watch youtube videos and discuss them with others in realtime, thus having some similarities with what you want to do.

Maybe you want to give it a read?

1 Like

It isn’t as simple as just dumping video content on a CDN for many use cases - different player devices have different needs and different bandwidth capabilities. Preparing the video assets for uploading to a CDN is a pretty complex workflow. After spending quite a while looking at it I ended up using mux.com - you upload the highest quality asset you have and they generate all the required derived assets. You can “unlock” particular assets for a time period using access tokens generated in your Elixir code based on user authentication etc. They have an Elixir library for connecting to their API. I used video.js to play the videos with video location and access token calculated by my Elixir code and encoded in the video URL given to the player.

Quite a lot of the mux.com platform is written in Elixir, I believe - one or two of their developers pop up on the slack channel.

And +1 to @Exadra37 response - the Programming Phoenix book has a great worked example covering a fair bit of what you need that would translate to either LiveView or a SPA without too much difficulty. In this case, I’d probably go the standard Phoenix view/controller + javascript as per the book (depending on your overall workflow) - there can be a bit of funkiness with stability of video players when liveview is busy manipulating the DOM. I haven’t fully investigated it - our project got parked up when the pandemic broke out and we’re only just getting back to it now.

5 Likes