1

I'm trying to upload a .gif to my django 3.2 api. I have already ran troubleshoots through Postman and came to the conclusion that my flutter app sends it as a .gif and it gets returned as a .jpg. The problem is on the backend. Here is my relevant code which checks for file_meme subtype and then the function should convert the incoming .gif to a video:

def add_media(self, file, order=None):
    check_can_add_media(post=self)

    is_in_memory_file = isinstance(file, InMemoryUploadedFile) or isinstance(file, SimpleUploadedFile)

    if is_in_memory_file:
        file_mime = magic.from_buffer(file.read())
    elif isinstance(file, TemporaryUploadedFile):
        file_mime = magic.from_file(file.temporary_file_path())
    else:
        file_mime = magic.from_file(file.name)

    check_mimetype_is_supported_media_mimetypes(file_mime)
    # Mime check moved pointer
    file.seek(0)

    file_mime_types = file_mime.split('/')

    file_mime_type = file_mime_types[0]
    file_mime_subtype = file_mime_types[1]

    temp_files_to_close = []

    if file_mime_subtype == 'gif':
                if is_in_memory_file:
                    file = write_in_memory_file_to_disk(file)

                temp_dir = tempfile.gettempdir()
                converted_gif_file_name = os.path.join(temp_dir, str(uuid.uuid4()) + '.mp4')

                ff = ffmpy.FFmpeg(
                    inputs={file.temporary_file_path() if hasattr(file, 'temporary_file_path') else file.name: None},
                    outputs={converted_gif_file_name: None})
                ff.run()
                converted_gif_file = open(converted_gif_file_name, 'rb')
                temp_files_to_close.append(converted_gif_file)
                file = File(file=converted_gif_file)
                file_mime_type = 'video'

            has_other_media = self.media.exists()
    
    if file_mime_type == 'image':
        post_image = self._add_media_image(image=file, order=order)
        if not has_other_media:
            self.media_width = post_image.width
            self.media_height = post_image.height
            self.media_thumbnail = file

    elif file_mime_type == 'video':
        post_video = self._add_media_video(video=file, order=order)
        if not has_other_media:
            self.media_width = post_video.width
            self.media_height = post_video.height
            self.media_thumbnail = post_video.thumbnail.file
    else:
        raise ValidationError(
            _('Unsupported media file type')
        )

    for file_to_close in temp_files_to_close:
        file_to_close.close()
            
            
    self.save()        

I'm not sure where the problem is. From my limited understanding, it is taking only the first frame of the .gif and uploading it as an image.

Earthling
  • 83
  • 3
  • 13

1 Answers1

0

If the code is not correctly updating the file_mime_type to 'video' after converting the GIF to MP4, the _add_media_image method might be invoked instead of _add_media_video. That would cause only the first frame to be stored as it would treat it as an image.

elif file_mime_type == 'video':
    post_video = self._add_media_video(video=file, order=order)

Make sure that file_mime_type is correctly updated to 'video' after the GIF conversion so that the _add_media_video method is triggered.

if file_mime_subtype == 'gif':
    # conversion logic ...
    file_mime_type = 'video'

In other words, check in a debugging session that file_mime_type = 'video' is executed.

It is also possible that the conversion from GIF to MP4 is not being performed correctly. You might want to inspect the temporary MP4 file to see if it contains all the frames or just the first one.

ff.run()
converted_gif_file = open(converted_gif_file_name, 'rb')

If the MIME type is not being updated correctly, the program will treat the MP4 as an image, and this might cause it to only take the first frame and save it as a JPEG. Debugging at the points where these actions occur could provide more insights into the issue.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250