跳转到主要内容

django-video-encoding帮助将您的视频转换为不同的格式和分辨率。

项目描述

django-video-encoding

PyPI GitHub Workflow Status (master) Coveralls github branch PyPI - Python Version PyPI - License

django-video-encoding帮助将您的视频转换为不同的格式和分辨率。

要求

  • Python 3.6.1或更高版本
  • ffmpeg和ffprobe

安装

  1. 安装django-video-encoding

    pip install django-video-encoding
    
  2. video_encoding添加到您的INSTALLED_APPS

集成

VideoFieldGenericRelation(Format)添加到您的模型中。您可以可选地通过向VideoField提供相应的字段名来存储视频的widthheightduration

from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from video_encoding.fields import VideoField
from video_encoding.models import Format


class Video(models.Model):
   width = models.PositiveIntegerField(editable=False, null=True)
   height = models.PositiveIntegerField(editable=False, null=True)
   duration = models.FloatField(editable=False, null=True)

   file = VideoField(width_field='width', height_field='height',
                     duration_field='duration')

   format_set = GenericRelation(Format)

要显示所有转换后的视频在管理员中,您应该将FormatInline添加到您的ModelAdmin

from django.contrib import admin
from video_encoding.admin import FormatInline

from .models import Video


@admin.register(Video)
class VideoAdmin(admin.ModelAdmin):
   inlines = (FormatInline,)

   list_dispaly = ('get_filename', 'width', 'height', 'duration')
   fields = ('file', 'width', 'height', 'duration')
   readonly_fields = fields

视频的转换应在单独的进程中完成。典型选项是django-rqcelery。以下示例将使用django-rqcelery的配置类似。django-video-encoding已提供任务(convert_all_videos)用于转换模型上的所有视频。当上传视频时应触发此任务。因此,我们监听post-save信号并将保存的实例排队进行处理。

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django_rq import enqueue

from video_encoding import tasks

from .models import Video


@receiver(post_save, sender=Video)
def convert_video(sender, instance, **kwargs):
    enqueue(tasks.convert_all_videos,
            instance._meta.app_label,
            instance._meta.model_name,
            instance.pk)

一段时间后,您可以使用以下方式访问转换后的视频:

video = Video.objects.get(...)
for format in video.format_set.complete().all():
   # do something

生成视频缩略图

后端提供了一个 get_thumbnail() 方法,用于从视频中提取缩略图。以下是一个如何生成缩略图并将其存储在模型中的基本示例。

# models.py
from django.db import models

class Video(models.Model):
   width = models.PositiveIntegerField(editable=False, null=True)
   height = models.PositiveIntegerField(editable=False, null=True)
   duration = models.FloatField(editable=False, null=True)

   thumbnail = ImageField(blank=True)
   file = VideoField(width_field='width', height_field='height',
                     duration_field='duration')

   format_set = GenericRelation(Format)


# tasks.py
from django.core.files import File
from video_encoding.backends import get_backend

from .models import Video


def create_thumbnail(video_pk):
   video = Video.objects.get(pk=video_pk)
   if not video.file:
      # no video file attached
      return

   if video.thumbnail:
      # thumbnail has already been generated
      return

   encoding_backend = get_backend()
   thumbnail_path = encoding_backend.get_thumbnail(video.file.path)
   filename = os.path.basename(self.url),

   try:
      with open(thumbnail_path, 'rb') as file_handler:
         django_file = File(file_handler)
         video.thumbnail.save(filename, django_file)
      video.save()
   finally:
      os.unlink(thumbnail_path)

您应该通过使用 django-rqcelery 或类似工具,在单独的进程中运行此方法,并从 post_save 信号中排队执行。

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django_rq import enqueue

from . import tasks
from .models import Video


@receiver(post_save, sender=Video)
def create_thumbnail(sender, instance, **kwargs):
    enqueue(tasks.create_thumbnail, instance.pk)

信号

在编码过程中,会发出多个信号以报告进度。您可以根据 Django 文档 中的说明注册到信号。

此简单示例演示了如何在转换完成后更新“视频模型”。

# apps.py
from django.apps import AppConfig


class MyAppConfig(AppConfig):
   # ...

    def ready(self) -> None:
      from . import signals  # register signals


# signals.py
from typing import Type

from django.dispatch import receiver
from video_encoding import signals

from myapp.models import Video


@receiver(signals.encoding_finished, sender=Video)
def mark_as_finished(sender: Type[Video], instance: Video) -> None:
   """
   Mark video as "convertion has been finished".
   """
   video.processed = True
   video.save(update_fields=['processed'])

signals.encoding_started

在编码开始之前发出。

参数
sender: Type[models.Model]:包含 VideoField 的模型。
instance: models.Model:包含 VideoField 的模型的实例。

signals.encoding_finished

encoding_started() 类似,但在文件被转换为所有格式之后发出。

参数
sender: Type[models.Model]:包含 VideoField 的模型。
instance: models.Model:包含 VideoField 的模型的实例。

signals.format_started

在视频被转换为配置的格式之一之前发出。

参数
sender: Type[models.Model]:包含 VideoField 的模型。
instance: models.Model:包含 VideoField 的模型的实例。
format: Format:格式实例,将引用编码后的视频文件。

signals.format_finished

format_finished 类似,但在视频编码过程之后发出,并包括编码是否成功。

参数
sender: Type[models.Model]:包含 VideoField 的模型。
instance: models.Model:包含 VideoField 的模型的实例。
format: Format:格式实例,将引用编码后的视频文件。
result: ConversionResultvideo_encoding.signals.ConversionResult 的实例,指示转换是否 FAILEDSUCCEEDED 或被 SKIPPED

配置

VIDEO_ENCODING_THREADS(默认:1
定义应使用多少个线程进行编码。这可能不是每个后端都支持的。

VIDEO_ENCODING_BACKEND(默认:'video_encoding.backends.ffmpeg.FFmpegBackend'
选择编码的后端。 django-video-encoding 仅支持 ffmpeg,但您可以实现自己的后端。您可以自由发布您的插件并提交拉取请求。

VIDEO_ENCODING_BACKEND_PARAMS(默认:{}
如果您的后端需要一些特殊配置,您可以在这里将其指定为 dict

VIDEO_ENCODING_FORMATS(默认值请参阅 video_encoding/config.py
此字典定义了所有必需的编码,并有一些合理的默认值。如果您想自定义格式,您必须为每个格式指定 nameextensionparams。例如

VIDEO_ENCODING_FORMATS = {
    'FFmpeg': [
        {
            'name': 'webm_sd',
            'extension': 'webm',
            'params': [
                '-b:v', '1000k', '-maxrate', '1000k', '-bufsize', '2000k',
                '-codec:v', 'libvpx', '-r', '30',
                '-vf', 'scale=-1:480', '-qmin', '10', '-qmax', '42',
                '-codec:a', 'libvorbis', '-b:a', '128k', '-f', 'webm',
           ],
        },
     ]

编码后端

video_encoding.backends.ffmpeg.FFmpegBackend(默认)

使用 ffmpegffprobe 转换您的视频的后端。

选项

VIDEO_ENCODING_FFMPEG_PATH
ffmpeg 的路径。如果没有提供路径,后端使用 which 来定位它。 VIDEO_ENCODING_FFPROBE_PATH
ffprobe 的路径。如果没有提供路径,后端使用 which 来定位它。

自定义后端

您可以实现自定义编码后端。创建一个继承自 video_encoding.backends.base.BaseEncodingBackend 的新类。您必须设置属性 name 并实现方法 encodeget_media_infoget_thumbnail。有关更多详细信息,请参阅参考实现:video_encoding.backends.ffmpeg.FFmpegBackend

如果您想开源您的后端,请按照以下步骤操作。

  1. 创建一个名为 django-video-encoding-BACKENDNAME 的包

  2. 将您的包发布到 pypi

  3. 提交包含以下更改的拉取请求

    • 将包添加到 extra_requires
    • VIDEO_ENCODING_FORMATS 提供合理的默认值

开发

本项目使用 poetry 进行打包和管理所有依赖,并使用 pre-commit 运行 flake8isortmypyblack

克隆此仓库并运行

poetry install
poetry run pre-commit install

以创建包含所有依赖项的虚拟环境。之后,您可以使用以下命令运行测试套件

poetry run pytest

此仓库遵循 Conventional Commits 风格。

Cookiecutter 模板

本项目使用 cruftcookiecutter-pyproject 模板创建。要更新此仓库到最新模板版本,请在仓库根目录下运行

cruft update

项目详情


下载文件

下载适用于您平台上的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源分布

django-video-encoding-1.0.0.tar.gz (18.0 kB 查看哈希值)

上传时间

构建分布

django_video_encoding-1.0.0-py3-none-any.whl (17.7 kB 查看哈希值)

上传时间 Python 3

由以下机构支持