0

The client app uploaded a video file and i need to generate a thumbnail and dump it to AWS s3 and return the client the link to the thumbnail. I searched around and found ffmpeg fit for the purpose. The following was the code i could come up with:

from ffmpy import FFmpeg
import tempfile

def generate_thumbnails(file_name):
    output_file = tempfile.NamedTemporaryFile(suffix='.jpg', delete=False, prefix=file_name)
    output_file_path = output_file.name
    try:
        # generate the thumbnail using the first frame of the video
        ff = FFmpeg(inputs={file_name: None}, outputs={output_file_path: ['-ss', '00:00:1', '-vframes', '1']})
        ff.run()

        # upload generated thumbnail to s3 logic
        # return uploaded s3 path 
    except:
        error = traceback.format_exc()
        write_error_log(error)
    finally:
        os.remove(output_file_path)
    return ''

I was using django and was greeted with permission error for the above. I found out later than ffmpeg requires the file to be on the disk and doesn't just take into account the InMemory uploaded file (I may be wrong as i assumed this).

Is there a way to read in memory video file likes normal ones using ffmpeg or should i use StringIO and dump it onto a temp. file? I prefer not to do the above as it is an overhead.

Any alternative solution with a better benchmark also would be appreciated.

Thanks.

Update: To save the inmemory uploaded file to disk: How to copy InMemoryUploadedFile object to disk

Adarsh
  • 3,273
  • 3
  • 20
  • 44

1 Answers1

0

One of the possible ways i got it to work were as follows:

Steps:

a) read the InMemory uploaded file onto a temp file chunk by chunk

temp_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
temp_file_path = temp_file.name
with open(temp_file_path, 'wb+') as destination:
     for chunk in in_memory_file_content.chunks():
               destination.write(chunk)

b) generate thumbnail using ffmpeg and subprocess

ffmpeg_command = 'ffmpeg -y -i {} -ss 00:00:01 vframes 1 {}'.format(video_file_path, thumbail_file_path                                                                                            
subprocess.call(ffmpeg_command, shell=True)

where,

-y is to overwrite the destination if it already exists

00:00:01 is to grab the first frame

More info on ffmpeg: https://ffmpeg.org/ffmpeg.html

Adarsh
  • 3,273
  • 3
  • 20
  • 44