Home > Blockchain >  Django ImageFiled thumbnail from video
Django ImageFiled thumbnail from video

Time:09-12

I need to make a thumbnail from a video and save it to Django's ImageField.

I already have the working code which saves the thumbnail to a specified folder but what I want is to redirect the output of FFmpeg directly to Imagefield (or to a in memory uploaded file and then to Imagefield)

This is my current code:

def clean(self):
    video_file = self.files['file']
    output_thumb = os.path.join(settings.MEDIA_ROOT, 'post/videos/thumbs', video_file.name)
    video_input_path = video_file.temporary_file_path()
    subprocess.call(
        ['ffmpeg', '-i', video_input_path, '-ss', '00:00:01', '-vf', 'scale=200:220', 
        '-vframes', '1', output_thumb])
    self.instance.video = video_file
    self.instance.video_thumb = output_thumb  

Model:

video = models.FileField(upload_to='post/videos/', blank=True,
                         validators=[FileExtensionValidator(allowed_extensions=['mp4', 'webm'])])
video_thumb = models.ImageField(upload_to='post/videos/thumbs', blank=True)

I'd like to do it so that I wouldn't need to specify the folder to save the thumb in (output_thumb in the code) and for Django to save it automatically using the upload_to='post/videos/thumbs option in the model definition

Please point me in the right direction of how to do this.

CodePudding user response:

Looking at your self-answer, you can compact your code a bit more:

file.seek(0)
args = ['ffmpeg', '-i', 'pipe:0', '-ss', '00:00:01', '-vf', 'scale=200:220',
        '-vframes', '1', '-f', 'image2pipe', '-c', 'mjpeg', 'pipe:1']
content = subprocess.run(args, input=file, stdout=subprocess.PIPE)
self.instance.video = self.files['file']
self.instance.video_thumb = ContentFile(content=output_stream[0], name=filename)

[original answer below]

Here is an partial answer. To get the ffmpeg output as bytes, specify the image format and codec and pipe it to stdout:

bytes = subprocess.run(
        ['ffmpeg', '-i', video_input_path, '-ss', '00:00:01', '-vf', 'scale=200:220', 
        '-vframes', '1', -f image2pipe -c mjpeg -],stdout=subprocess.PIPE)

I don't know Django to comment on what to do with this data here on out

CodePudding user response:

I think I managed to get it to work. Not sure if it's the right way to do this but looks like it's working. Would be grateful is someone could add something about it.

file.seek(0)
args = ['ffmpeg', '-i', 'pipe:0', '-ss', '00:00:01', '-vf', 'scale=200:220',
        '-vframes', '1', '-f', 'image2pipe', '-c', 'mjpeg', 'pipe:1']
ffmpeg_process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output_stream = ffmpeg_process.communicate(file.read())
self.instance.video = self.files['file']
self.instance.video_thumb = ContentFile(content=output_stream[0], name=filename)
  • Related