在 django 中使用 celery 和 ffmpeg 对视频进行转码

Posted

技术标签:

【中文标题】在 django 中使用 celery 和 ffmpeg 对视频进行转码【英文标题】:Transcode video using celery and ffmpeg in django 【发布时间】:2015-04-21 23:41:15 【问题描述】:

我想使用 celery 对用户上传的视频进行转码。我想首先我应该上传视频,然后生成一个 celery 任务进行转码。

tasks.py 中可能是这样的:

subprocess.call('ffmpeg -i path/.../original path/.../output')

刚刚完成First steps with celery,很困惑如何在views.pytasks.py 中完成。这也是一个很好的解决方案吗?我非常感谢您的帮助和建议。谢谢。

models.py:

class Video(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=100)
    original = models.FileField(upload_to=get_upload_file_name)
    mp4_480 = models.FileField(upload_to=get_upload_file_name, blank=True, null=True)
    mp4_720 = models.FileField(upload_to=get_upload_file_name, blank=True, null=True)
    privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)

我不完整的views.py:

@login_required
def upload_video(request):
    if request.method == 'POST':
        form = VideoForm(request.POST, request.FILES)
        if form.is_valid():
            if form.cleaned_data:
                user = request.user
                #
                #
                # No IDEA WHAT TO DO NEXT
                #
                #
                return HttpResponseRedirect('/')

    else:
        form = VideoForm()
        return render(request, 'upload_video.html', 
            'form':form
            )

【问题讨论】:

【参考方案1】:

我猜你已经解决了这个问题,但我会提供更多关于 GwynBleidD 的信息,因为我遇到了同样的问题。

因此,作为 GwynBleidD,您需要调用 Celery 任务,但如何编写这些任务?这是结构:

    任务从数据库中获取视频 它使用 ffmepg 对其进行编码并在任何你想要的地方输出 编码完成后,将对应的属性设置为模型并保存(注意,如果您在同一视频上运行各种任务,请不要使用旧实例保存,因为您可能会丢失其他任务的信息运行)

首先,在您的设置中设置一个FFMPEG_PATH 变量,然后:

import os, subprocess
from .models import Video

@app.task
def encode_mp4(video_id, height):
    try:
        video = Video.objects.get(id = video_id)
        input_file_path = video.original.path
        input_file_name = video.original.name

        #get the filename (without extension)
        filename = os.path.basename(input_file_path)

        # path to the new file, change it according to where you want to put it
        output_file_name = os.path.join('videos', 'mp4', '.mp4'.format(filename))
        output_file_path = os.path.join(settings.MEDIA_ROOT, output_file_name)

        # 2-pass encoding
        for i in range(1):
            subprocess.call([FFMPEG_PATH, '-i', input_file_path, '-s', 'x'.format(height * 16 /9, height), '-vcodec', 'mpeg4', '-acodec', 'libvo_aacenc', '-b', '10000k', '-pass', i, '-r', '30', output_file_path])

        # Save the new file in the database
        video.mp4_720.name = output_file_name
        video.save(update_fields=['mp4_720'])

【讨论】:

【参考方案2】:

修改您的模型,这样您就可以在没有转码版本的情况下保存原始(上传的)视频,并且可能会在您的模型中添加一些标志,以便在视频被转码时保存状态(并且基于该标志,您可以向用户显示该视频转码仍在进行中)。

上传视频并将其模型保存到数据库后,运行 celery 任务将视频的 ID 传递到其中。在 celery 任务中从数据库中检索视频,对其进行转码并使用更改的标志将其保存到数据库中。

【讨论】:

我已经修改了我的模型以便可以保存它。请您写下您在代码中提到的内容,因为这就是我感到困惑的地方。谢谢。

以上是关于在 django 中使用 celery 和 ffmpeg 对视频进行转码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中使用 Celery 上传和处理大型 excel 文件?

在 Celery 任务中使用 Django 的 ORM

在 django 中使用 celery 和 ffmpeg 对视频进行转码

Django+Celery+Redis 使用

Django 和 Celery 的示例:周期性任务

如何在 Django 和 Celery 中配置多个代理?