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:
- 
videos– to store video metadata
- 
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
  
  
  ✅ 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
🧠 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
🔁 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
# 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
📈 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
This gives you a hash like:
{
  5 => 3,
  6 => 3,
  7 => 14,  # 👈 most replayed second
  8 => 2
}
💻 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
}
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
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
    }
  }'
📦 Summary
| Part | Description | 
|---|---|
| videostable | 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)