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

CGuy's avatar
Level 5

Get image/video metadata from stream

Hi, in the app I am currently building I need to download files from remote locations and store them on S3. In order to reduce memory usage I am currently making use of fopen to create a stream and pass that to Storage::put(). However I need to get information such as the size, width, height, duration and possibly an MD5 of those files. Do you know how to achieve this with streams or any other solution while staying efficient?

0 likes
6 replies
ohffs's avatar

Your best option might be to run ffprobe against the file once it has finished being ::put() to the remote server. I think mpeg streams have to be read as a whole (or rather the stream info can be anywhere in the file) to figure out what they contain - so I don't think you could just use a chunk or stream to get the info - I might be very wrong though! I have vague memories of trying to do this a few years ago by just storing the first few kb/mb of the file - but it never worked :-/

CGuy's avatar
Level 5

@OHFFS - Okay but as far as I understand running ffprobe will download the whole file again right? So I would be streaming files from remote location to S3 and the downloading from S3 again to read metadata? I really hope there is a more efficient method of doing this. Thanks for your answer

ohffs's avatar

@CGUY - I think it would have to read the whole file through memory - yeah. I'm not sure if there's a better way without storing the file temporarily I'm afraid. Maybe someone else will chip in though :-)

CGuy's avatar
Level 5

So I have not found a way to get video metadata from an fopen resource. However I have found that collecting metadata and specific frames with FFMpeg and FFProbe does not download the whole file. So even though I have to make multiple requests (one for metadata, one for the frame and one to stream the file from the origin to the destination) I do not need to keep the whole file on the server at once.

ohffs's avatar

Can you post some of your code here so if anyone else is trying to do the same thing they will be able to see how to do it? :-)

CGuy's avatar
CGuy
OP
Best Answer
Level 5

Get video Metadata

   $ffprobe = FFProbe::create();
   $videoStream = $ffprobe->streams($videoURL) // extracts streams informations
                            ->videos()                      // filters video streams
                            ->first();                       // returns the first video stream
            
        $info = [
            'width' => $videoStream->get('width'),
            'height' => $videoStream->get('height'),
            'duration' => (float) $videoStream->get('duration'),
        ];

Get the size of the video (because it is often missing in the headers)

$format = $ffprobe->format($videoURL); // extracts streams informations
$info['size'] = $format->get('size');

And finally because the Guzzle Documentation lacking information on how to get the actual resource from a response

$client = new Guzzle\Client([
    'stream' => true,
]);
$client->get($videoURL);
$stream = $response->getBody()->detach();// Get the stream resource from Guzzle response

   Storage::putStream(
                    $destinationPath,
                    $stream);
1 like

Please or to participate in this conversation.