Задать вопрос
Sergei_Erjemin
@Sergei_Erjemin
Улыбайся, будь самураем...

Как инициировать «генерацию» других форматов видео в django-videokit?

Решил применить для небольшого проекта Python/Django батарейку django-videokit (git). И в общем, оно у меня почти заработало. Но непонятно почему не происходит создание (конвертация) исходного видео в другие форматы. Django-videokit должен через Celery запустить утилиту ffmpeg и «приготовить» видео-файлы необходимых форматов (.mp4, .ogg и .webm). Cсылки на эти файлы окажутся в соответствующих полях VideoSpecField.

В models.py все почти как в документаци:
from videokit.models import VideoField, VideoSpecField
from my_project import settings

class tbVideoItems(models.Model):
    szVideoName = VideoField(
        upload_to = settings.PATH_FOR_VIDEO,
        null = True,
        blank = True,
        width_field = 'iVideoWidth',
        height_field = 'iVideoHeight',
        rotation_field = 'fVideoRotation',
        mimetype_field = 'szVideoMimetype',
        duration_field = 'iVideoDuration',
        thumbnail_field = 'imgVideoThumbnail'
    )
    iVideoWidth = models.IntegerField(null = True, blank = True)
    iVideoHeight = models.IntegerField(null = True, blank = True)
    fVideoRotation = models.FloatField(null = True, blank = True)
    szVideoMimetype = models.CharField(max_length = 32, null = True, blank = True)
    iVideoDuration = models.IntegerField(null = True, blank = True)
    imgVideoThumbnail = models.ImageField(null = True, blank = True)

    szVideoName_ogg = VideoSpecField(source = 'szVideoName', format = 'ogg')
    szVideoName_webm = VideoSpecField(source = 'szVideoName', format = 'webm')

    class Meta:
        verbose_name = u"Видео-ролик"
        verbose_name_plural = u"Видео-ролики"
        ordering = ['szVideoName']


Исходное видео «засасывается» и полям iVideoWidth, iVideoHeight, fVideoRotation, szVideoMimetype и iVideoDuration присваиваются правильные значения. Создаётся превьюшка imgVideoThumbnail. Поля же VideoSpecField (szVideoName_mp4, szVideoName_ogg и szVideoName_webm) остаются пустыми. Надо запустить генерацию. Для этого в views.py (например) пишем. что-то типа:

# ...
qVideos = tbVideoItems.objects.all()
    for i in qVideos:
        if i.szVideoName_ogg == "":
            i.szVideoName_ogg.generate()
        # ...
# ...


Соответсвенно генерация запускается. При втором вызове views.py видно, что szVideoName_ogg получило значение. При просмотре значений полей (через админку или через print i.szVideoName_ogg) значения меняются. Например:

videos/Futurama-S7e01\fc54f1c9ace5c6403763ae772a59adc6.ogg
через пару секунд:
videos/Futurama-S7e01\c57acb82ed465ed362f190495d9c4990.ogg
еще через пару секунд:
videos/Futurama-S7e01\ed046299f6622802ca36f76961b8aebf.ogg
и так далее...

В целевой папке никаких .ogg файлов нет. Для контроля проверил: вообще на диске (включая временные папки) нигде нет ни одного .ogg.

Что еще примечательно: при запуске под *nix видео-файлы, «всосанные» через szVideoName, не имеют статуса на чтение и, соотвественно, не могут быть отданы клиенту веб-сервером:
$ ls -l
-rw------- 1 web web   69537154 фев 27 17:05 Futurama-S7E07.mp4
-rw-r--r-- 1 web web      13053 фев 27 17:05 Futurama-S7E07.mp4.thumb.jpg

При этом у создаваемой превьюшки (.thumb.jpg) с правами все в порядке. Под Widows таких проблем нет и видео-файл через веб остдаётся.

У меня гипотеза, что как-то всетаки Celery файл подхватывает и что-то с ним делает (или пытается). Но вот что?!

В самом django-videokit в task.py есьт описание создания процесса для конвертации и создания файла:
process = subprocess.Popen(
    ['ffmpeg', '-i', source_file, '-y'] + options + [temp_file])

Но вот создается это процесс, и если создается, то работает ли он?

В django-videoki упоминается, что как-то можно проверить статус создания альтернативных видео-файлов, но не сказано как :(.

Все усложяется тем, что это мой первый опыт использования Celery и как там должна происходить инициализация очередей, выполнение заданий и тому подобное -- не понимаю. Ни RabbitMQ, ни Cellery никак не настраивал (из коробки). Куда «копать» не понимаю. Хелп.

P.S. В инструкциях по установке django-videokit указано, что предварительно надо установить RabbitMQ. Но в requirements.txt примера указан в числе прочего еще и redis==2.10.5. В коде
celery.py<code> примера тоже сипользуют Redis... Мне не понятно как и кто тогда управляет очередями.
  • Вопрос задан
  • 346 просмотров
Подписаться 1 Сложный 6 комментариев
Решения вопроса 2
tumbler
@tumbler Куратор тега Django
бекенд-разработчик на python
при запуске под *nix видео-файлы, «всосанные» через szVideoName, не имеют статуса на чтение и, соотвественно, не могут быть отданы клиенту веб-сервером

Если веб-сервер запущен под пользователем web, то права -rw------- означают доступ на чтение и запись для этого самого пользователя, значит отдача веб-сервером возможно. Это легко проверить, попытавшись скачать этот файл curl-ом, например.
У меня гипотеза, что как-то всетаки Celery файл подхватывает и что-то с ним делает (или пытается). Но вот что?

Celery делает ровно то, что указано в теле соответствующих задач, описанных в проекте django-videokit. Если любопытно, надо искать в исходниках "батарейки".
Но вот создается это процесс, и если создается, то работает ли он?

Во-первых, стоит почитать логи celery, там наверняка будут какие-то ошибки запуска (например, отсутствие ffmpeg на машине :-) ). Во-вторых, ffmpeg на любую ошибку ругается кодом ответа, отличным от нуля. Если django-videokit этот код ответа не проверяет - это плохая "батарейка".

это мой первый опыт использования Celery и как там должна происходить инициализация очередей, выполнение заданий и тому подобное -- не понимаю

Это очень обширный вопрос, для ответа на который нужно объяснить основы протокола AMQP, который реализует RabbitMQ, половину документации Celery "и тому подобное".
Если кратко, то схема следующая:
  1. при вызове celery_task.delay() отправляется сообщение в RabbitMQ
  2. RabbitMQ маршрутизирует сообщение в нужную очередь, в соответствии с настройками celery
  3. celery берет задачу в обработку, выполняет код, являющийся телом задачи
  4. после выполнения задачи, результат (return) записывается в redis
  5. код, отправивший задачу, может подождать ее завершения, вызвав async_result.get, который внутри периодически опрашивает redis, не появился ли там результат обработки задачи.
что предварительно надо установить RabbitMQ. Но в requirements.txt примера указан в числе прочего еще и redis==2.10.5.

Традиционно, celery использует RabbitMQ для передачи задач и Redis для хранения результатов их выполнения.

Мне не понятно как и кто тогда управляет очередями

Очередями (их настройкой) заведует Celery, объявляя их при старте worker-ов.
Ответ написан
Sergei_Erjemin
@Sergei_Erjemin Автор вопроса
Улыбайся, будь самураем...
В версии django 1.11 другое расположение файлов media и static внутри проекта. Раньше эти папки находились в "корне" относительно manager.py. теперь внутри папки с setings.py и url.py. Соответственно VideoKit пытался найти и приготовить файлы .ogg и .webm в тех папках которых не существовало. Но т.к. происходило это асинхронно в параллельном процессе, то и поймать ошибку сложно. Никаких сообщений в консоль основного процесса не попадало.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы