How to create a video upload platform using Ruby on Rails – Part 1

Lets create a video upload platform using the popular Ruby on Rails web framework. I have never done a multi-part series before so I thought I would take a stab at it using a small project I did in my spare time. This series might go slow since I have limited time to write these, but hopefully it will be informative.

The small project I was working on was attempting to create a video upload platform using Ruby on Rails. The app would allow you to upload videos and would play them back using Adaptive Bitrate and HLS techniques to help adjust to changing bandwidth requirements. One other thing I added for fun, was a small Node.js server that handles and transcoded videos On-The-Fly when it could, or would fallback to the normal post transcoding process. This allowed the app to receive the upload and transcode at the same time, reducing the amount of time the user had to wait. Since uploading videos has a lot of idle time, why not use that to do some more work.

This walk through will hopefully try and reattempt the work I did with that project and hopefully someone can find fun with it.

We will assume you have a basic rails environment set up and can create new Rails apps:

rails new VideoSite

Let it do its stuff and then lets go into the project.

cd VideoSite

At this point, we have a freshly baked Ruby on Rails application. We need a place where we can upload some videos. We will use the popular Carrierwave gem for handling our uploads. Lets add that to our project and bundle the project:

# Gemfile

gem 'carrierwave'
bundle install

Next we need to create the Uploader using the Carrierwave generator.

rails generate uploader Video

Great. Next lets go ahead and create our controller/model/views for our videos pages and then migrate our database.

rails generate scaffold Video title:string file:string
rake db:migrate

Before we can start uploading videos however, we need to attach the uploader to our video model. Open up app/models/video.rb and change it as follows.

class Video < ApplicationRecord
  mount_uploader :file, VideoUploader

Now we can fire up our rails application and upload some videos! Start your rails server with rails s and then navigate to http://localhost:3000/videos/new and you should see our amazing video page.

In order to actually select a video file, we need to update the view to render a file_field instead of a text_field as well as allow multipart uploads. Lets open up the app/views/videos/_form.html.erb file and change it to the following.

<%= form_with(model: video, local: true, html: { multipart: true }) do |form| %>
  <% if video.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(video.errors.count, "error") %> prohibited this video from being saved:</h2>

      <% video.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
  <% end %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title, id: :video_title %>

  <div class="field">
    <%= form.label :file %>
    <%= form.file_field :file, id: :video_file %>

  <div class="actions">
    <%= form.submit %>
<% end %>

We should now be able to choose files and upload them!

Go ahead and select a video and click the Create Video Button. You should then see something like this.

This isn’t really all that fun since we cannot see the video, just the path to it. Lets fix that by using the HTML video tag. Open up the app/views/video/show.html.erb file and change it to the following and then reload the page and you should see your video playing.

<p id="notice"><%= notice %></p>

  <%= @video.title %>

  <video controls width="640" height="480" src="<%= @video.file %>"></video>

<%= link_to 'Edit', edit_video_path(@video) %> |
<%= link_to 'Back', videos_path %>

Congratulation! You have the beginning of your very own video uploading service. If you try to load this in other browsers, you may run into problems however, since not all browsers are capable of playing all formats all the time. Another issue is that some web servers will send the entire video file down to the client, which we do not want. It would be a lot nicer if only the part of the video we request is what we receive, continuously. In the next part, we will continue to expand on our simple video uploading by adding some fancy transcoding techniques and use some front end tools that will help us render on all browsers, including mobile and stream smaller chunks of video at a time.

Hope this was fun. Take a look at Part II next!