Integrating video hosting into Strapi Projects ensures faster content delivery, reduced server load, and a smoother playback experience. For media-heavy platforms like e-learning portals or streaming apps, connecting Strapi with a cloud video provider makes video storage, optimization, and delivery scalable.

Prerequisites

  • A working Strapi Project
  • Node.js installed on your machine
  • An account with a video-capable cloud storage provider (e.g., AWS S3 with MediaConvert).
  • Access credentials for the chosen provider (e.g., API key, API secret, access token, or bucket credentials depending on the service).

Set Up Media Storage in Strapi

Strapi"s default local upload isn"t suitable for production, so you need to configure a cloud provider like AWS S3. This involves installing the provider package and configuring environment variables. It replaces local storage with scalable & production-ready hosting for your media files.

Install the Provider Plugin

Run the plugin installation in your project root:

code
npm install @strapi/provider-upload-aws-s3

This allows Strapi to route uploads to your cloud storage instead of the local filesystem.

Configure Environment Variables

Hardcoding credentials is insecure and inflexible. Environment variables keep secrets out of source control and make it easy to switch between dev, staging, and production. Create or edit your .env file in the project root to include your cloud provider's credentials and bucket details.

code
AWS_ACCESS_KEY_ID=your_access_key_id
code
AWS_ACCESS_SECRET=your_secret_access_key
code
AWS_REGION=us-east-1
code
AWS_BUCKET=your_bucket_name
code

Explanation:

  • AWS_REGION : The AWS region where your resources (like S3 buckets) are hosted. Example: us-east-1.
  • AWS_BUCKET : The name of your Amazon S3 bucket where media files will be stored.
Embedding Videos in Strapi

Connect Strapi to the Provider

Strapi must know which provider to use and how to connect to it. The plugins.js file in Strapi project configuration reads your environment variables and passes them to the provider, completing the backend setup for cloud-based video storage.

code
module.exports = ({ env }) => ({
code
upload: {
code
config: {
code
provider: 'aws-s3',
code
providerOptions: {
code
accessKeyId: env('AWS_ACCESS_KEY_ID'),
code
secretAccessKey: env('AWS_ACCESS_SECRET'),
code
region: env('AWS_REGION'),
code
params: {
code
Bucket: env('AWS_BUCKET'),
code
},
code
},
code
},
code
},
code
});

Explanation:

  • accessKeyId: env('AWS_ACCESS_KEY_ID') : Reads your AWS access key ID from environment variables.
  • secretAccessKey: env('AWS_ACCESS_SECRET') : Reads your AWS secret key for secure authentication.
  • params: { Bucket: env('AWS_BUCKET') } : Specifies the target S3 bucket where files will be uploaded.

Handling Large File Uploads

By default, Strapi blocks large uploads. For video projects, that"s a bottleneck. Increasing the limits in ./config/middlewares.js to raise limits ensures your backend accepts high-resolution or long-duration videos without crashing.

code
// ./config/middlewares.js
code
module.exports = [
code
'strapi::errors',
code
{
code
name: 'strapi::body',
code
config: {
code
formLimit: '200mb',
code
jsonLimit: '200mb',
code
textLimit: '200mb',
code
},
code
},
code
'strapi::security',
code
'strapi::cors',
code
];

Explanation:

  • module.exports = [ ... ]: Exports middleware configurations that Strapi will apply globally.
  • { name: 'strapi::body', config: { ... } }: Configures the body parser middleware to process incoming request payloads.
  • 'strapi::security': Adds standard security headers to protect your application from common web vulnerabilities.
  • 'strapi::cors': Allows Cross-Origin Resource Sharing (CORS) so your frontend can make requests to the Strapi API.

Create a Video Content Type

Define a Video collection type with fields like title and video. Separating video metadata from the file itself makes videos easy to search, manage, and retrieve through Strapi"s API.

code
// This is a conceptual representation of the created content type.
code
{
code
"kind": "collectionType",
code
"collectionName": "videos",
code
"attributes": {
code
"title": {
code
"type": "string"
code
},
code
"video": {
code
"type": "media",
code
"multiple": false,
code
"required": true,
code
"allowedTypes": [
code
"videos"
code
]
code
}
code
}
code
}

Explanation:

  • collectionName: "videos": The database table name that will hold video entries.
  • attributes: { ... }: Defines the fields (columns) for each video entry.

Upload and Access Videos via Admin Panel

By configuring the Video content type, editors can upload videos from Strapi"s admin interface. This ensures that files are sent to the cloud provider securely while metadata like title, MIME type, and size is stored in the database. This keeps your media organized and accessible via the API.

code
{
code
"id": 1,
code
"title": "Demo Video",
code
"video": {
code
"id": 5,
code
"name": "sample.mp4",
code
"url": "https://your-bucket.s3.region.amazonaws.com/sample.mp4",
code
"provider": "aws-s3",
code
"mime": "video/mp4",
code
"size": 24500
code
}
code
}
code

Explanation:

  • provider: "aws-s3": Indicates that the file is stored using the AWS S3 provider.
  • mime: "video/mp4": MIME type of the file, describing its format (mp4 video).

Access Videos via API

Strapi generates REST and GraphQL endpoints for all content types, including videos. Accessing these endpoints allows your frontend to fetch video metadata and cloud-hosted file URLs. This provides the links to display or stream videos in browsers or player libraries.

REST Example:

code
{
code
"data": [
code
{
code
"id": 1,
code
"attributes": {
code
"title": "My First Hosted Video",
code
"video": {
code
"data": {
code
"attributes": {
code
"url": "https://your-bucket.s3.region.amazonaws.com/video_file.mp4"
code
}
code
}
code
}
code
}
code
}
code
]
code
}

Explanation:

  • data: [ ... ]: The root property returned by Strapi contains an array of entries (in this case, video entries).
  • attributes: { ... } : Contains all the actual fields defined in the content type (e.g., title, video).

GraphQL Example:

code
query {
code
videos {
code
data {
code
id
code
attributes {
code
title
code
video {
code
data {
code
attributes { url }
code
}
code
}
code
}
code
}
code
}
code
}

Enable Streaming & Thumbnails

Videos can be processed into multiple resolutions and formats and paired with thumbnails. This ensures smooth playback across devices and networks, while thumbnails improve UX by giving users previews.

code
{
code
"title": "Demo Video",
code
"video": { "url": "s3://bucket/video.mp4" },
code
"thumbnail": { "url": "s3://bucket/frame.jpg" },
code
"streaming": {
code
"hls": "https://stream-service.com/playlist.m3u8",
code
"dash": "https://stream-service.com/manifest.mpd"
code
}
code
}

After converting the original video into multiple resolutions with HLS/DASH, the generated streaming URLs are stored in the entry. This ensures device-compatible playback and avoids serving large MP4 files directly.

code
{
code
"id": 1,
code
"title": "Demo Video",
code
"video": {
code
"url": "https://your-bucket.s3.region.amazonaws.com/original.mp4"
code
},
code
"streaming": {
code
"hls": "https://streaming-service.com/video/playlist.m3u8",
code
"dash": "https://streaming-service.com/video/manifest.mpd"
code
}
code
}

Explanation:

  • hls: "https://.../playlist.m3u8": HLS (HTTP Live Streaming) URL, optimized for iOS and browsers.
  • dash: "https://.../manifest.mpd": MPEG-DASH URL, supported by many modern players and devices.

Integrate on Frontend

Strapi"s API can be consumed in an HTML <video> element or with player libraries like Video.js or hls.js. Using adaptive players improves playback quality, supports multiple resolutions, and reduces buffering issues for end users.

code
<video controls>
code
<source src="https://signed-url.com/video.mp4" type="video/mp4" />
code
</video>

To display hosted videos, fetch them from Strapi"s API with populate=* to include file URLs. The frontend can then use these URLs directly in an HTML5 <video> element or pass them to a player library for advanced streaming features.

code
const response = await fetch('http://your-strapi-app.com/api/videos?populate=*');
code
const jsonData = await response.json();
code
const videoUrl = jsonData.data[0].attributes.video.data.attributes.url;

Implement Adaptive Streaming

Using HLS or DASH manifests with a player library like hls.js or Video.js allows adaptive streaming. This ensures smooth playback across different devices and network conditions while supporting multiple bitrates and resolutions.

code
if (Hls.isSupported()) {
code
const video = document.getElementById('video');
code
const hls = new Hls();
code
hls.loadSource("https://streaming-service.com/playlist.m3u8");
code
hls.attachMedia(video);
code
}
code

Explanation:

  • Hls.loadSource: loads the streaming manifest.
  • hls.attachMedia(video): binds the stream to the HTML video element.