← All work
Case studySecure streaming · E-learning

Anti-Piracy Video LMS

A learning platform for paid, recorded courses where the hard problem is not playing video — it is stopping it from being shared. Every stream carries a watermark unique to the viewer, access depends on where the student is watching from, sessions are locked to one device, and progress is tracked to the second.

I built it twice in 2021: a first version on CodeIgniter 4 in about a month, then a rebuild on Laravel 8 with a real-time admin and stricter, location-aware access control.

Client
Core by Phei & Co
Role
Design, engineering & coding
Domain
E-learning · secure video streaming
Versions
CodeIgniter 4, then Laravel 8
Status
In use 2021 – 2023
The problem
Paid, recorded courses lose their value the moment a video is shared or an account is passed around.
What was built
Morsalin designed and built a Laravel platform with DRM streaming, watermarks unique to each viewer, location-aware access, single-device sessions and a real-time admin.
The result
In use from 2021 to 2023. Any leaked recording traces back to one student, and course access matches how courses are sold — at a centre, at home, or both.
5checks before every stream
5 minplayback token lifetime
43real-time events
74permission gates
133routes
~14klines of PHP
~12.5klines of JavaScript
~15klines in the first version
01The problem

Paid video is easy to share.

01

Paid video is easy to share.

One login passed around a class, or one screen recording posted online, and a course stops earning.

02

Some courses are taught in a room.

Students were meant to watch at a registered study centre, at home, or either — and the platform had to know which.

03

A leak has to be traceable.

Blocking every recording is impossible. Making every recording point back to the student who made it is not.

02What it does

A course platform built around protecting the video.

Courses

Content organised as modules, lessons and topics, with a course built from a module and a chosen set of lessons.

Enrolment

Admins enrol students one by one or in bulk, each with a policy: study centre only, home only, or both.

Secure streaming

DRM playback through short-lived tokens, with a watermark unique to the viewer on every frame.

Study centres

Centres recognised by their public IP, each with its own watermark design.

Progress & reports

Watch position and time tracked to the second, rolled up by course, enrolment, module, lesson and topic.

Lesson notes

Attachments per lesson, downloaded through signed links.

Video library

Uploads go straight to the video host; a signed webhook registers each video when it has finished processing.

Real-time admin

Every admin page updates live as students, enrolments and content change.

03Every stream request

No token until every check passes.

fig.02 — every stream requestchecks · token · watermark · progress
Studentopens a topicCHECKS, IN ORDER1. Attach progressone record per topic2. Resolve locationcentre by IP, else home3. Location policycentre · home · both4. Pin home viewingfirst IP and browser5. One deviceothers signed outall passedPlayback tokenvalid for five minutescarries the viewer's watermarkDRM video hostencrypted playbackwebhook when a video is readyPlayerviewer ID on screenresumes where you stoppedprogress every 5 sProgress recordonly ever moves forwardAdmin, livereports update over private channels
  1. 1

    Attach a progress record

    One record per student, enrolment and topic, created on first view.

  2. 2

    Resolve the location

    Is the request coming from a registered study centre? If not, the student is treated as watching from home.

  3. 3

    Enforce the enrolment’s policy

    A centre-only enrolment cannot stream from home, and the reverse.

  4. 4

    Pin home viewing

    When required, home viewing is locked to the IP address and browser recorded at the student’s first sign-in.

  5. 5

    Only then, a token

    The server asks the video host for a playback token valid for five minutes, carrying the viewer’s watermark.

04Forensic watermarks

Every recording names its maker.

Built from the viewer

Name, phone, email, username, ID or IP — whichever fields the centre chooses — are written onto the video for that one stream.

Static or moving

Fixed text at a set position, or moving text that relocates at an interval so it cannot simply be cropped out.

Designed per centre

Colour, opacity, size and position are configured per study centre, including patterns that repeat across the frame.

Inside the token

The watermark travels with the five-minute playback token, so it cannot be removed on the student’s side.

05One student, one device

Sharing a login stops being convenient.

Signing in signs everyone else out

A new sign-in ends every other session on the account.

A heartbeat on the player

The stream page checks its session every 30 seconds and leaves the moment it has been revoked.

Two-step sign-in

Credentials are checked first; the session is then opened through an encrypted, signed link that lasts 30 seconds and only works from the same IP.

Pause hides the video

Pausing hides the player and leaves full screen, removing the easiest moment to capture a frame.

06Progress tracking

Watch time, to the second.

Resume where you stopped

The player seeks to the furthest point reached and counts how many times a topic was opened.

Every five seconds

Position and cumulative watch time are recorded while the video plays — and only while the device is online.

Only forward

The furthest-watched position never moves backwards, and a topic is marked complete when the video ends.

Reports at every level

Completion rolls up by course, enrolment, module, lesson and topic for the admin team.

07Real-time admin

Every admin page stays current on its own.

Observers → events → channels

Model observers fire 43 broadcast events — created, updated, status changed, deleted — over private channels.

Only real changes

A status event fires only when the status actually changed, not on every save.

Every page listens

Admin lists and detail pages refresh their tables and show notices as colleagues work.

Consistency on moves

Moving a topic or lesson to another module re-points every progress report that depends on it.

Behind it: JSON API controllers kept separate from page controllers, 74 permission gates, 40 validated request types, and bulk user and enrolment import that validates every row and reports errors, saved rows and issues separately.

08Two generations

Built once to learn, rebuilt to last.

v1 · April – May 2021

CodeIgniter 4, in about a month

~15k lines: modules, lessons and topics; DRM streaming with moving watermarks; multiple-choice quizzes with reports; support tickets with replies; email templates; user logs; and a JSON API behind the admin.

v2 · from April 2021

Laravel 8, rebuilt for operations

Study centres and location policies, device and connection pinning, per-centre watermark designs, second-by-second progress, a real-time admin over private channels, a webhook-fed video library and a clean split between API and page controllers.

09Key decisions

Every non-obvious choice, with its reason.

Trace leaks instead of only blocking them

A recording can always be made; a recording that names its maker is a deterrent.

Checks as a middleware chain

Each rule is small, testable and runs in a fixed order before any token exists.

Five-minute playback tokens

A copied player link stops working almost immediately.

Location as part of the enrolment

Where a student may watch is a property of what they bought, not of their account.

Progress only moves forward

Scrubbing back to rewatch a section never erases what was already watched.

Separate API and page controllers

Pages stay thin; every action is a JSON endpoint the real-time UI can call and refresh.

Webhook-driven video library

A video is only added to the library when the host confirms it is ready to play.

Rebuild rather than patch v1

Real-time updates and location rules needed a different structure, and the product was young enough to change it.

10Outcome

Protected content, measured learning.

Secure playback

DRM streaming with per-viewer watermarks and five-minute tokens.

Access control

Study-centre, home and device rules enforced before every stream.

Learning data

Second-by-second progress, resume and completion reports at every level.

Operations

A real-time admin with bulk import, permissions and a webhook-fed video library.

  • Every leaked recording points back to one student — the watermark is part of the stream, not an overlay on the page.
  • Course access matches how courses are sold — at a centre, at home, or both, per enrolment.
  • Account sharing gets harder — one device at a time, with home viewing pinned to the student’s own connection.
  • Built twice in 2021 — a first version in about a month, then a rebuild with real-time operations.

My role

I designed, built and coded the platform: the first version on CodeIgniter 4, then the Laravel rebuild — the course and enrolment model, the stream access checks, forensic watermarking, session security, progress tracking, the real-time admin and the video library integration.

Stack

Backend
PHP · Laravel 8 · Sanctum · MySQL
Real time
Laravel Echo · Pusher · private channels
Frontend
Blade · jQuery · server-side data tables · Laravel Mix
Video
VdoCipher DRM · playback tokens · webhooks
v1
PHP · CodeIgniter 4
PHPLaravelCodeIgniterMySQLJavaScriptReal-time (Echo / Pusher)DRM videoAccess controlSession securityE-learningWebhooksData modelling

Built for Core by Phei & Co, where I was an independent contractor from 2019 to 2022. The product brand is kept confidential. The watermark shown is an illustration with made-up values.

Next

Content worth protecting?

Get in touch →
© 2026 MD Morsalinbuilt with care · OSS-first · sustainable by design
lat: 23.81°Nlon: 90.41°Etz: UTC+6status: 200 OK