Building a Streaming Service

August 11, 2024

Can one person build a movie and TV streaming platform from scratch? Probably not, but I’m giving it a try—one step at a time.

Note: This post covers Phase 1 of the project (the CMS), which is already live here.

Index

Motivation

The technology behind video streaming has always fascinated me. Terms like “encoding” and “transcoding” pop up frequently if you explore this space, and once you start digging into how everything works, it’s easy to get hooked. I certainly did.

In the early days, video streaming was pretty basic—a single video file embedded in a player. But as the demand for streaming grew, so did the complexity. The introduction of the <video> tag in HTML5, the rise of Apple’s HLS protocol, and major innovations from companies like Netflix reshaped the industry. The world was suddenly consuming vast amounts of media, not just porn.

But what if you want to build your own platform from scratch? That’s what I set out to do—one person, one project, and a whole lot of code.

Core Components of a Streaming Service

A streaming service requires several core components. Some of these are essential, while others can be optional depending on what kind of platform you’re building. Here’s a breakdown of what you’ll need:

CMS

At the heart of any streaming platform is the CMS (Content Management System). This is what lets you manage the media content—adding, removing, and organizing movies and TV shows.

Big platforms like Netflix and Amazon Prime Video build their own CMS systems in-house, but for this project, I went with something more accessible and manageable. I used Flask (a Python web framework), paired with Tailwind CSS for styling and Jinja2 for templating. It’s a lightweight, flexible setup that gets the job done without a lot of overhead. For storing media information, I decided on a flat-file JSON database. The content doesn’t change often, so updating it during builds works perfectly fine.

Content Library

And then, of course, there’s the actual content. While companies like Netflix produce their own original series and films, smaller platforms tend to license content from studios. For my demo app, I used dummy data from IMDb. You could swap this for real licensed content, or even user-generated material depending on the type of service you’re creating.

Core Infrastructure

The backend infrastructure that powers video streaming is just as critical as the content itself. While I’m particularly interested in the technical details of this area, this blog won’t dive too deep into it. However, here are some key components that play a crucial role in delivering a seamless video experience:

graph TD;
    User -->|Interacts With| Web-Player;
    Web-Player -->|Requests Video| CDN;
    CDN -->|Serves Cached Video| Web-Player;
    CDN -->|If Not Cached, Sends Request| Backend-Server;
    Backend-Server -->|Fetches| Storage;
    Storage -->|Provides Raw Video| Backend-Server;
    Backend-Server -->|Sends Raw Video| Transcoder;
    Transcoder -->|Encodes & Transcodes Video| Backend-Server;
    Backend-Server -->|Sends Encoded Video| CDN;
    CDN -->|Serves Encoded Video| Web-Player;
    Web-Player -->|Plays Video| User;

    subgraph "Video Streaming Workflow"
        Web-Player
        CDN
        Backend-Server
        Storage
        Transcoder
    end
  

This diagram shows how a user interacts with the player and how video is fetched, encoded, and delivered across the infrastructure.

Service providers like Akamai, Cloudflare, and Mux offer infrastructure solutions that handle all these components for you. If you don’t have experience with infrastructure, that’s perfectly fine—these services can manage it for you. I’ll dive deeper into infrastructure changes in a follow-up post (Phase 2).

Building the CMS

Navigation is critical for any streaming app, so I focused on building a system that’s intuitive but powerful. Users can filter movies by genre, language, and other parameters, allowing them to quickly narrow down what they’re looking for. Whether your content library has 50 titles or 5,000, this kind of navigation helps users find their way.

Homepage

Slideshow

I started with a homepage slideshow that highlights the newest movies and TV shows. It automatically cycles through the featured titles, and I added a progress bar at the top to give users a sense of when the slide will change. This makes the browsing experience feel dynamic without being overwhelming.

Content Display

On the homepage, I added support for displaying content in rows. Right now, the categories include ‘Latest Movies’ and ‘Latest TV Episodes,’ but these are totally customizable. Each row is horizontally scrollable, so users can easily browse through a selection. I’ve made it flexible enough to adjust the number of items shown per row, depending on how much content you want to display at a time.

Themes

Early on, I was clear about wanting to support multiple themes, so I wired up Tailwind to work with configurations and Flask to allow somewhat dynamic CSS. By “somewhat dynamic,” I mean that you can’t alter the theme while the app is running (yet!). Currently, you have to choose a theme at build time, and all users see the same one, since we only run Tailwind during the build process and don’t generate CSS for multiple themes. However, you can use any colors that Tailwind CSS supports.

Dark theme homepage for GYSO
Homepage with the dark theme selected.
Cobalt theme homepage for GYSO
Homepage with the cobalt theme selected.

The differences above are subtle, but we can get creative with other options. However, there are some limitations with shadows and transitions—building a light theme is tricky because the shadows can make it look too harsh.

Library

The Library displays all available movies and TV shows in a simple grid layout, allowing users to easily browse the entire catalog. You can filter content by release date, genre, or IMDb rating, or search for specific titles directly.

Each title is shown with a poster, IMDb rating, and key details like genre and release year. Filters and search are designed to work client-side, so once the Library loads, all interactions happen instantly without needing to query the server again. Images are also lazy-loaded to keep the app fast.

One of the main design decisions I made early on was to keep as much of the app static as possible. This means that when you open the Library, all titles are pre-loaded, with the HTML cached and served from a CDN for fast delivery. The filtering and searching are handled entirely in the browser using JavaScript, so you can use these features without sending any requests to the backend.

Here’s a look at the Library:

Screenshot of the Library section showing a grid of movies and TV shows with filtering and search options.

And here’s a video showing how the filters work in real-time:

This client-side approach makes the Library fast and responsive, letting you browse the entire catalog without adding extra load to the server.

Heading Backdrops

Some of the pages in our streaming service have custom backdrops at the top, such as the “Library” page or other static pages like “About Us” or “Privacy Policy.”

To enhance the visual appeal, I decided to build something similar to the poster grids that many streaming platforms use. Here’s an example of this concept from Netflix:

Netflix homepage showing a grid of movie posters

I ended up writing a short script using Pillow and Numpy to generate a custom backdrop image, like the one you see below:

Custom backdrop featuring a collage of movie posters for the streaming library

I think it turned out pretty well!

Custom backdrop for the library page of the streaming service

We can easily customize this for every page that requires a backdrop. For example, if you’re viewing TV Shows in the library, the backdrop can dynamically feature posters of TV shows.

Movies

When it comes to streaming a movie, you need to make the experience as seamless as possible for two main types of users:

  1. Those who already know what they want to watch and have come to the platform specifically for it.
  2. Those who are casually browsing, looking to discover something new.

For both groups, key information needs to be front and center. All the important details—movie title, description, release year, duration, genre, IMDb rating, and Metascore—are displayed right at the top, making it easy to start streaming right away.

Movie page layout in the streaming service showing title, description, release year, duration, genre, IMDb rating, and Metascore.

As you scroll down, more information is revealed in additional scrollable sections. These include clips and trailers, cast and crew information, and related movies. For clips and trailers, I’m pulling data from TMDB (The Movie Database), but you can easily use IMDb or another service for this.

Scrollable sections on the movie page for clips, trailers, cast and crew information, and related movies.

The related movies section is automatically generated by the app. I built an algorithm that looks at factors like shared cast and crew, genres, and tags to determine which movies should be recommended. As your content library grows, these recommendations will only get more accurate and relevant.

TV Shows

The TV show page is built to handle multiple seasons and episodes, making it easy for users to explore content. Unlike movies, which have a single piece of media, TV shows can span several seasons, each with multiple episodes.

For shows that haven’t aired yet, the page will display the show’s basic details—like the title, synopsis, genre, release year, and IMDb rating—but without any season or episode information until the show is released.

Screenshot of a TV show page where no seasons or episodes are available yet.

Once a show has aired, the page lists all available seasons. Each season can be expanded to show its episodes, and clicking on a different season will automatically collapse the previous one, keeping the layout tidy and easy to navigate.

Here’s a video showing how the expand and collapse feature works for the seasons:

As with the movie pages, users can watch trailers, teasers, and see the main cast and their roles.

Cast & Crew

Currently, there’s no dedicated page for people—whether cast or crew members like actors, directors, or writers. Ideally, we would have a timeline that showcases all the works an individual has been involved in, similar to how IMDb displays an actor’s page. This would allow users to explore a person’s filmography in a more detailed way.

For now, the app links cast and crew members to the library, so users can search for other movies and TV shows featuring the same individuals.

Conclusion

So this is how I’ve built out the CMS for my TBD streaming service. There’s still room for improvement, like adding sections such as “More Movies with Ryan Reynolds” or “More Movies Directed by Michael Mann” instead of just listing “Similar Movies”. As the library grows, these recommendations will become even richer and more useful.

While a CMS is just a small part of the overall system, it’s a critical one since it’s what the end user interacts with the most.

I’m excited to continue working on this project and expanding its features. If you have any suggestions or feedback, feel free to reach out using the email at the bottom of the website. I’d love to hear your thoughts!