【问题标题】:How to compress base64 decoded video data using ffmpeg in django如何在 django 中使用 ffmpeg 压缩 base64 解码的视频数据
【发布时间】:2021-08-09 15:17:31
【问题描述】:

我想在我的 django-channels 项目中上传视频/音频文件。所以我从 websocket 连接上传了视频(base64 编码的 url)。它工作正常。但现在解码 base64 视频数据后,我想使用 ffmpeg 压缩该视频。但它显示这样的错误。 ''原始:没有这样的文件或目录'' 我在 consumer.py 文件中使用了“AsyncJsonWebsocketConsumer”。这是我的代码: 消费者.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: No such file or directory”。 我该如何解决这个问题?任何建议。如果可以在将对象保存到数据库之前对其进行压缩,将会更有帮助。提前致谢。

【问题讨论】:

  • 检查文件系统。文件在那里吗?
  • 在 post_save 信号的情况下它存在,因为对象已保存完毕。
  • 你能看到文件吗?该错误表明它找不到该文件,因此请务必检查该文件是否确实存在于您希望保存它的文件系统中
  • 是的,文件保存在确切的位置。我手动检查了它。我认为问题在于查找文件的路径。
  • 这意味着它没有保存在存储在数据库中的路径中。因此,这可能是您如何在模型中指定路径的问题。发布您的型号代码

标签: python django ffmpeg django-channels


【解决方案1】:

经过一番努力,我已经解决了这里的问题。我不知道这是否是一个好的解决方案,但对我来说它已经奏效了。我在这里使用了 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"

我认为这是因为“个人聊天室”内的空间。后来我尝试了

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 现在正在引用第二个。所以,第一个可以稍后删除。

【讨论】:

    猜你喜欢
    • 2014-05-28
    • 1970-01-01
    • 2021-02-27
    • 2014-07-02
    • 1970-01-01
    • 2011-08-09
    • 2013-12-29
    • 2017-03-02
    • 2016-05-27
    相关资源
    最近更新 更多