DEV Community

Sparsh Garg
Sparsh Garg

Posted on

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

Top comments (0)