Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jorisnoo's avatar

Stream Videos from S3 Bucket

Hi everyone,

I am struggling with finding the right way to stream videos from my S3 disk. I uploaded video files (*.webm) to my S3 disk with

Storage::disk('s3')->put('/videos/ABC.webm', File::get($videoTempPath));

The upload works fine. I now wonder what is the best way to display the videos in a HTML5 Player. I am using vue.js in the frontend (a single page app) and no Blade templates.

I know I could access the file directly on S3 like this: https://s3-eu-west-1.amazonaws.com/my-bucket/videos/ABC.webm but I would like to define a route like http://myapp.dev/media/video/ABC to get the video.

I defined a route and a Controller with the function:

public function getVideo(Request $request, $downloadCode) {
    ...
}

What is the best way to stream the video to the client in a performant and right way? I could just use return Storage::disk('s3')->get('/videos/ABC.webm'); but this would load the entire file to memory and then return it, right?

I tried some stuff with StreamedResponse like

$stream = Storage::disk('s3')->getDriver()->readStream($path);
$response = new StreamedResponse(function() use ($stream) {
    echo stream_get_contents($stream);
});

But I don't know if this is the right way? Is this really streaming the content?

Thanks for your help,

Robert

0 likes
5 replies
davestewart's avatar

I've only done this once, so there may be other ways, but how we did it was to set up Cloudfront and just access it via a URL.

Another dev in the team set that bit up, but that was what worked for us.

jorisnoo's avatar

@davestewart Yes this would also be a solution. But I don't know how to bypass the access restrictions then.

I currently use following solution:

$stream = Storage::disk('s3')->getDriver()->readStream($path);
return response()->stream(function () use ($stream) {
    fpassthru($stream);
}, $status, $headers);

Does this mean that the file is loaded from S3 to the server and then to the client or does the client directly stream it from S3 then? Or does it even matter?

It works fine so far, but I have no idea if it is performant or the right way to do.

martinbean's avatar

@jorisnoo Why pass a video from S3 to your application to your user? Just stream the video directly from S3. Use signed URLs is you don’t want to store the files with a public ACL. Even better, stream them from CloudFront rather than S3.

davestewart's avatar

@jorisnoo - we uploaded them to S3, and set the ACL to public.

Then you set up cloudfront, which gives you a different domain URL, but you use the same S3, path so:

// S3
s3domain.com/path/to/your/file.mp4

// Cloudfront
foobar.cloudfront.com/path/to/your/file.mp4

You then upload to S3 using the S3 domain, but give your users the Cloudfront URL.

Cloudfront is cool as it copies your videos to a network of global CDN locations, and they stream at super-high speeds. Once the video has uploaded, you don't need to think about it again :)

Even though I didn't set it up, I thought it was going to be complicated, but my colleague got the whole thing running in couple of hours.

As I said though, this wasn't my bit of the project so I'm not really an authority on what is best, just letting you know what worked in our case.

Please or to participate in this conversation.