Audio and video content sales on website

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Audio and video content sales on website
Complex
~5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Implementing Audio/Video Content Sales on a Website

Media content sales (music tracks, podcasts, educational videos, films, documentaries) are technically harder than PDF sales. Main issues — streaming protection from unauthorized access, bandwidth management, and simultaneous business models: one-time purchase (own) vs subscription (stream).

Two Delivery Modes

Download-to-own: user pays once, downloads file. Applicable for music tracks, audiobooks, individual video lectures. Mechanism identical to ebook sales — S3 + temporary signed URLs.

Stream-only: user watches/listens online, can't download. Applicable for films, series, subscription courses. Requires special infrastructure.

Direct S3 distribution for streaming is not ideal for two reasons: traffic cost and inability to control concurrent sessions. Correct stack:

S3 (origin) → CloudFront CDN → Signed Cookies → Player (HLS.js / Shaka Player)

Video Streaming via CloudFront + HLS

Video stored in S3 at source quality (MOV/MP4 4K). AWS MediaConvert transcodes to multiple bitrates and packages as HLS (.m3u8 + .ts segments):

output/
  movie-uuid/
    index.m3u8          # master playlist
    360p/stream.m3u8
    720p/stream.m3u8
    1080p/stream.m3u8
    360p/seg-000.ts
    360p/seg-001.ts
    ...

CloudFront distributes with signed cookies (not URL — cookies to cover all segments with one signature):

// Generate CloudFront signed cookies
use Aws\CloudFront\CloudFrontClient;

$cf = new CloudFrontClient(['region' => 'us-east-1', 'version' => 'latest']);

$policy = json_encode([
    'Statement' => [[
        'Resource' => "https://cdn.example.com/output/{$movie->uuid}/*",
        'Condition' => [
            'DateLessThan' => ['AWS:EpochTime' => time() + 14400], // 4 hours
            'IpAddress'    => ['AWS:SourceIp' => $request->ip() . '/32'],
        ],
    ]],
]);

$cookies = $cf->getSignedCookie([
    'policy'      => $policy,
    'private_key' => storage_path('app/cf-private-key.pem'),
    'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID'),
]);

// Return cookies in Set-Cookie headers
foreach ($cookies as $name => $value) {
    Cookie::queue($name, $value, 240, '/', '.example.com', true, true, false, 'None');
}

Frontend player receives cookies via /api/media/{id}/access endpoint, then plays HLS:

import Hls from 'hls.js';

const hls = new Hls({
  xhrSetup: (xhr) => {
    xhr.withCredentials = true; // send CloudFront cookies
  },
});

hls.loadSource(`https://cdn.example.com/output/${movieUuid}/index.m3u8`);
hls.attachMedia(videoElement);

Audio Streaming

For audio (music, podcasts) schema is simpler. MP3/AAC/FLAC files stored in S3. For streaming without download use CloudFront signed URL with limited lifetime and IP binding:

$signedUrl = $cloudFront->getSignedUrl([
    'url'         => "https://cdn.example.com/audio/{$track->file_key}",
    'expires'     => time() + 7200,
    'private_key' => storage_path('app/cf-private-key.pem'),
    'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID'),
]);

For preview (30-second sample) store separate file {uuid}-preview.mp3 in publicly accessible CDN path.

View Analytics

Critical for video: watchability, exit points. Affects recommendation system and shows what content works.

// Send heartbeat every 10 seconds
let lastReported = 0;
videoElement.addEventListener('timeupdate', () => {
    const current = Math.floor(videoElement.currentTime);
    if (current - lastReported >= 10) {
        navigator.sendBeacon('/api/analytics/heartbeat', JSON.stringify({
            content_id: contentId,
            position:   current,
            duration:   Math.floor(videoElement.duration),
        }));
        lastReported = current;
    }
});

navigator.sendBeacon doesn't block tab closing — data arrives even if user suddenly closes browser.

Subscription Model

For streaming service (Netflix-like) use Stripe Subscriptions:

const subscription = await stripe.subscriptions.create({
  customer: customer.stripe_id,
  items: [{ price: 'price_monthly_plan' }],
  payment_behavior: 'default_incomplete',
  expand: ['latest_invoice.payment_intent'],
});

Table subscriptions(user_id, stripe_subscription_id, plan, status, current_period_end). Webhook customer.subscription.updated / customer.subscription.deleted syncs status. Middleware checks subscriptions.status = 'active' and current_period_end > now().

Quality Management and Adaptive Streaming

ABR (Adaptive Bitrate) — HLS auto-switches quality per connection speed. But set transcoding rules in MediaConvert:

Profile Resolution Video Bitrate Audio Bitrate
360p 640×360 800 kbps 96 kbps
720p 1280×720 2500 kbps 128 kbps
1080p 1920×1080 5000 kbps 192 kbps
1080p HDR 1920×1080 8000 kbps 192 kbps

Implementation Timelines

Stage Time
S3 + MediaConvert pipeline 2–3 days
CloudFront signed cookies + HLS player 2 days
Payment integration (one-time/subscription) 2 days
View analytics 1 day
Admin panel (content upload) 2–3 days

Total: 9–11 working days for full platform with subscription and streaming.

Common Issues

Hotlinking. If URL is predictable or unprotected, bots and users will share direct links. CloudFront Signed Cookies + IP binding solve this.

Mobile buffering. HLS segments of 6–10 seconds give good balance. Too short (2s) increases HTTP requests, too long (20s) increases initial delay.

Concurrent sessions. Subscription platforms often limit simultaneous views. Implemented via Redis: SET stream:{user_id}:{session_id} EX 30 updated every 10 seconds. If active key count for stream:{user_id}:* exceeds limit — new session blocked.