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()
def _add_media_image(self, image, order):
return PostImage.create_post_media_image(image=image, post_id=self.pk, order=order)
def _add_media_video(self, video, order):
return PostVideo.create_post_media_video(file=video, post_id=self.pk, order=order)
@classmethod
def create_post_media_image(cls, image, post_id, order):
hash = sha256sum(file=image.file)
post_image = cls.objects.create(image=image, post_id=post_id, hash=hash, thumbnail=image)
PostMedia.create_post_media(type=PostMedia.MEDIA_TYPE_IMAGE,
content_object=post_image,
post_id=post_id, order=order)
return post_image
@classmethod
def create_post_media_video(cls, file, post_id, order):
hash = sha256sum(file=file.file)
video_backend = get_backend()
if isinstance(file, InMemoryUploadedFile):
# If its in memory, doing read shouldn't be an issue as the file should be small.
in_disk_file = write_in_memory_file_to_disk(file)
thumbnail_path = video_backend.get_thumbnail(video_path=in_disk_file.name, at_time=0.0)
else:
thumbnail_path = video_backend.get_thumbnail(video_path=file.file.name, at_time=0.0)
with open(thumbnail_path, 'rb+') as thumbnail_file:
post_video = cls.objects.create(file=file, post_id=post_id, hash=hash, thumbnail=File(thumbnail_file), )
PostMedia.create_post_media(type=PostMedia.MEDIA_TYPE_VIDEO,
content_object=post_video,
post_id=post_id, order=order)
return post_video
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.
If the code is not correctly updating the
file_mime_typeto 'video' after converting the GIF to MP4, the_add_media_imagemethod 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.Make sure that
file_mime_typeis correctly updated to 'video' after the GIF conversion so that the_add_media_videomethod is triggered.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.
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.