DEV Community

Sparsh Garg
Sparsh Garg

Posted on

2

How YouTube Might Track “Most Replayed” Parts of a Video — in Ruby on Rails

Have you ever noticed the spiky graph above the YouTube timeline showing "Most Replayed" sections?

In this post, we’ll build a simplified version of that system using Ruby on Rails — to track, store, and visualize which parts of a video are being re-watched the most.


🧱 Step 1: Database Design

We'll use two tables:

  1. videos – to store video metadata
  2. video_interactions – to log when a user scrubs, replays, or pauses at a specific second

✅ Migration: videos

# db/migrate/20250515120000_create_videos.rb
class CreateVideos < ActiveRecord::Migration[7.0]
  def change
    create_table :videos do |t|
      t.string :title
      t.integer :duration_seconds
      t.references :uploaded_by, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

✅ Migration: video_interactions

# db/migrate/20250515120500_create_video_interactions.rb
class CreateVideoInteractions < ActiveRecord::Migration[7.0]
  def change
    create_table :video_interactions do |t|
      t.references :video, null: false, foreign_key: true
      t.references :user, foreign_key: true
      t.string :interaction_type  # e.g. 'replay', 'scrub'
      t.integer :timestamp_in_video  # second in timeline

      t.timestamps
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

🧠 Step 2: Models

# app/models/video.rb
class Video < ApplicationRecord
  has_many :video_interactions, dependent: :destroy
end

# app/models/video_interaction.rb
class VideoInteraction < ApplicationRecord
  belongs_to :video
  belongs_to :user, optional: true

  enum interaction_type: { replay: 'replay', scrub: 'scrub', pause: 'pause' }

  validates :timestamp_in_video, presence: true
end
Enter fullscreen mode Exit fullscreen mode

🔁 Step 3: API Endpoint to Track Interactions

Let’s make an endpoint to log interactions.

# config/routes.rb
Rails.application.routes.draw do
  resources :videos do
    resources :video_interactions, only: [:create]
  end
end
Enter fullscreen mode Exit fullscreen mode
# app/controllers/video_interactions_controller.rb
class VideoInteractionsController < ApplicationController
  def create
    interaction = VideoInteraction.new(interaction_params)
    if interaction.save
      render json: { status: "ok" }, status: :created
    else
      render json: { errors: interaction.errors.full_messages }, status: :unprocessable_entity
    end
  end

  private

  def interaction_params
    params.require(:video_interaction).permit(
      :video_id,
      :user_id,
      :interaction_type,
      :timestamp_in_video
    )
  end
end
Enter fullscreen mode Exit fullscreen mode

📈 Step 4: Aggregating the "Most Replayed" Data

Now let’s create a method to find which parts of the video were replayed the most.

# app/models/video.rb
def replay_heatmap
  video_interactions
    .where(interaction_type: 'replay')
    .group(:timestamp_in_video)
    .order(:timestamp_in_video)
    .count
end

def most_replayed_second
  replay_heatmap.max_by { |_, count| count }&.first
end
Enter fullscreen mode Exit fullscreen mode

This gives you a hash like:

{
  5 => 3,
  6 => 3,
  7 => 14,  # 👈 most replayed second
  8 => 2
}
Enter fullscreen mode Exit fullscreen mode

💻 Step 5: Visualizing on the Frontend

You can send the replay_heatmap hash to your frontend via an API, and render a chart using any JS library like:

  • Chart.js
  • ApexCharts
  • D3.js
GET /videos/123/replay_heatmap

{
  "5": 3,
  "6": 3,
  "7": 14,
  "8": 2
}
Enter fullscreen mode Exit fullscreen mode

You can then show a hoverable graph above your video player like YouTube.


🚀 Bonus: Background Summary Table (Optional)

To speed up performance on popular videos, you can pre-aggregate data using a background job:

rails generate model VideoReplaySummary video:references timestamp_in_video:integer replay_count:integer
Enter fullscreen mode Exit fullscreen mode

Use a job (e.g. with Sidekiq or ActiveJob) to refresh this hourly.


🧪 Testing It Locally

Use curl or Postman to simulate a replay:

curl -X POST http://localhost:3000/videos/1/video_interactions \
  -H "Content-Type: application/json" \
  -d '{
    "video_interaction": {
      "user_id": 1,
      "interaction_type": "replay",
      "timestamp_in_video": 142
    }
  }'
Enter fullscreen mode Exit fullscreen mode

📦 Summary

Part Description
videos table Stores basic video info
video_interactions Logs every replay/scrub with timestamp
Aggregation method Groups interactions by timestamp for heatmap
Visualization Displays the graph on video timeline

Gen AI apps are built with MongoDB Atlas

Gen AI apps are built with MongoDB Atlas

MongoDB Atlas is the developer-friendly database for building, scaling, and running gen AI & LLM apps—no separate vector DB needed. Enjoy native vector search, 115+ regions, and flexible document modeling. Build AI faster, all in one place.

Start Free

Top comments (0)

Scale globally with MongoDB Atlas. Try free.

Scale globally with MongoDB Atlas. Try free.

MongoDB Atlas is the global, multi-cloud database for modern apps trusted by developers and enterprises to build, scale, and run cutting-edge applications, with automated scaling, built-in security, and 125+ cloud regions.

Learn More

👋 Kindness is contagious

Explore this insightful piece, celebrated by the caring DEV Community. Programmers from all walks of life are invited to contribute and expand our shared wisdom.

A simple "thank you" can make someone’s day—leave your kudos in the comments below!

On DEV, spreading knowledge paves the way and fortifies our camaraderie. Found this helpful? A brief note of appreciation to the author truly matters.

Let’s Go!