如何在django中使用ffmpeg压缩base64解码视频数据

How to compress base64 decoded video data using ffmpeg in django

我想在我的 django-channels 项目中上传 video/audio 文件。所以我从 websocket 连接上传了视频(base64 编码 url)。它工作正常。但现在在解码 base64 视频数据后,我想使用 ffmpeg 压缩该视频。但它显示这样的错误。 ''原始:没有这样的文件或目录'' 我在 consumers.py file.Here 中使用了 'AsyncJsonWebsocketConsumer' 是我的代码: consumers.py:

async def send_file_to_room(self, room_id, dataUrl, filename):
        # decoding base64 data
        format, datastr = dataUrl.split(';base64,')
        ext = format.split('/')[-1]
        file = ContentFile(base64.b64decode(datastr), name=filename)
        print(f'file: {file}')
        # It prints 'Raw content'
        output_file_name = filename + '_temp.' + ext
        ff = f'ffmpeg -i {file} -vf "scale=iw/5:ih/5" {output_file_name}'
        subprocess.run(ff,shell=True) 

可能是这里ffmpeg无法识别要压缩的文件。我也尝试使用 post_save 信号来解决这个问题。

signals.py:

@receiver(post_save, sender=ChatRoomMessage)
def compress_video_or_audio(sender, instance, created, **kwargs):
    print("Inside signal")
    if created:
        if instance.id is None:
            print("Instance is not present")
        else:
            video_full_path = f'{instance.document.path}'
            print(video_full_path)
   // E:\..\..\..\Personal Chat Room\media\PersonalChatRoom\file\VID_20181219_134306_w5ow8F7.mp4
            output_file_name = filename + '_temp.' + extension
            ff = f'ffmpeg -i {filename} -vf "scale=iw/5:ih/5" {output_file_name}'
            subprocess.run(ff,shell=True)
            instance.document = output_file_name
            instance.save()

它也导致 “E:..\Django\New_Projects\Personal: 没有那个文件或目录”。 我该如何解决这个问题?如果可以在将对象保存到数据库之前对其进行压缩,任何 suggetions.It 都会更有帮助。提前致谢。

经过一番努力,我已经解决了这里的问题。我不知道这是否是一个好的解决方案,但对我来说它已经奏效了。我在这里使用了 post_save 信号。所以文件已经保存好了。我首先尝试 instance.document.path 将文件路径传递给 ffmpeg。但是ffmpeg无法识别该文件。

video_full_path = f'{instance.document.path}'
print(video_full_path)
# E:\..\..\..\Personal Chat Room\media\PersonalChatRoom\file\VID_20181219_134306_w5ow8F7.mp4

错误是:

"E:..\Django\New_Projects\Personal: No such file or directory"

我认为是因为'Personal Chat Room'里面的space。后来我尝试了

media_in = instance.document.url
print(media_in)
# /media/PersonalChatRoom-2/file/VID_20181219_134306_jS7H8fL.mp4

ffmpeg 仍然无法识别媒体中的文件。 对我有用的技巧是:

media_in = '.' + instance.document.url
print(media_in)
# ./media/PersonalChatRoom-2/file/VID_20181219_134306_jS7H8fL.mp4
filename, extension = os.path.splitext(media_in)
media_out = filename + '_temp' + extension
print(media_out)
# ./media/PersonalChatRoom-2/file/VID_20181219_134306_jS7H8fL_temp.mp4
subprocess.run('ffmpeg -i ' + media_in + ' -vf "scale=iw/4:ih/4" ' +  media_out,  shell=True)

此时 ffmpeg 识别了文件并将输出保存在 media/ 中。 我遇到的下一个问题,

instance.document = media_out
instance.save()
print(instance.document.url)
# /media/media/PersonalChatRoom-1/file/VID_20181219_134306_jS7H8fL_temp.mp4

浏览器无法从该位置找到文件,因为在额外保存之后 '/media/' 添加了路径。 为了解决这个问题,

output_file_name = media_out.split('./media/')[-1]
print(output_file_name)
# PersonalChatRoom-1/file/VID_20181219_134306_jS7H8fL_temp.mp4
...
...
instance.document = output_file_name
instance.save()

这次完美运行。

完整代码:signals.py:

from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver

import os
import subprocess

from chat.models import ChatRoomMessage

@receiver(post_save, sender=ChatRoomMessage)
def compress_video_or_audio(sender, instance, created, **kwargs):
    if created:
        if instance.id is None:
            print("Instance is not present")
        else:
            media_in = '.' + instance.document.url
            filename, extension = os.path.splitext(media_in)
            media_out = filename + '_temp' + extension
            output_file_name = media_out.split('./media/')[-1]
            subprocess.run('ffmpeg -i ' + media_in + ' -vf "scale=iw/4:ih/4" ' +  media_out, shell=True)
            instance.document = output_file_name
            instance.save()
           

这里给出了答案,保存对象后压缩视频文件(保存前仍然不知道如何压缩)。所以在媒体文件夹中为每个对象创建了两个视频文件。 object.document.url 现在引用第二个。所以,第一个可以稍后删除。