hunterhawley's avatar

Queuing File Transformation After File Upload

Hey there! I have been Googling around, and was surprised that I couldn't find the answer to this anywhere. I have a form that has a few text/integer fields, and one multi-select file field for videos. Currently, I've got code that will upload everything, put the text fields in the DB, then use FFMPEG to compress and combine every video into one concatenated larger video.

All of this works, my problem is that for any video larger than a minute or two, the FFMPEG process takes FOREVER. So, I've been watching the Laracasts about Queuing. I haven't found anything about how to pass $request data, and when I tried, I was told that serialization was not allowed for that. At this point, I just need to know how to pass my video objects to a job where they can be processed, so that the user doesn't have to sit there and wait. Any thoughts?

0 likes
5 replies
JohnBraun's avatar

I am not sure if you are asking for a general flow, or for a practical code example.

I guess, the general flow could be:

In your controller:

  • Accept the request
  • Store every uploaded video on your server
  • Pass the uploaded files to a job, e.g. ProcessVideos($videos)

In your job:

  • Make the job implement ShouldQueue
  • Handle all logic for processing the videos
  • [optional] Fire an event that the processing was succesful

In your environment file:

  • Set the appropriate queue driver (e.g. redis), making sure that you've installed the required driver

Optionally, you could also listen for that VideoProcessingSucces event and broadcast that back to that user, let me know if you want more info on that as well.

hunterhawley's avatar

@JOHNBRAUN - Hey John,

This is super helpful. Now the only questions I have are

  1. How do I get $videos ready to send over to the job? Right now (I'm currently just processing this in the controller and now I am converting it) I can do $request->file('video_file'); and then just loop through each file with a foreach. I can't pass $request though, because I get an error that says "serialization of 'closure' is not allowed laravel job"

  2. So, I could put something in the DB that says "in progress" while the video processing is happening, and then change it to "processed" once it is done? Basically what do you call to make something happen upon successful processing?

Thank you so much!

JohnBraun's avatar
Level 33

I dont know if the approach Im going to describe is the best, but this is how I would do it in your situation.

When a user uploads multiple videos, loop over them and store them in a unprocessed-videos database and assign an upload_uuid, to easily get all videos that belong together. This table should also store the file path and a user_id.

Then, you can either pass all these videos as an Iluminate collection to the Job class or just pass the uuid and let the job collect all videos from the unprocessed videos table.

When the job is finished, you can fire an event (or hook into Laravels own event when a job is finished) and make a listener which (for example) sends an e-mail to the user to inform them that their videos were processed.

For the concatenating the videos, I would loop over all videos in your job until all videos are concatenated. Then write that video to disk (using Storage facade) and then to a processed videos table which has the file path, upload_uuid and user_id. Pass the newly created concatenated video to a VideoProcessed event and inform the user.

Does this help you to get started?

Edit: if you want to learn more about your broadcasting options in Laravel, maybe this article would be helpful https://johnbraun.blog/posts/websockets-in-laravel

hunterhawley's avatar

@JOHNBRAUN - This actually helps a lot. There is a lot to unpack here, so it'll probably take me a bit before I get it running, but I'll post an update on here with any further questions! Thanks a lot John! Nice website too!

JohnBraun's avatar

@HUNTERHAWLEY - Allright, good luck! If you have any questions don't hesitate to ask them on the forum. Thanks for your nice words regarding my weblog :-)

Please or to participate in this conversation.