Django ImageFiled миниатюра из видеоролика
Мне нужно сделать миниатюру из видео и сохранить ее в Django ImageField.
У меня уже есть рабочий код, который сохраняет миниатюру в указанную папку, но я хочу перенаправить вывод FFmpeg непосредственно в Imagefield (или в загруженный в память файл, а затем в Imagefield)
Вот мой текущий код:
def clean(self):
file = self.files['file']
output_thumb = os.path.join(settings.MEDIA_ROOT, 'post/videos/thumbs', file.name)
video_input_path = file.temporary_file_path()
subprocess.call(
['ffmpeg', '-i', video_input_path, '-ss', '00:00:01', '-vf', 'scale=200:220',
'-vframes', '1', output_thumb])
self.instance.video = self.files['file']
self.instance.video_thumb = output_thumb
Я бы хотел сделать так, чтобы мне не нужно было указывать папку, в которую сохранять палец (output_thumb
в коде), а чтобы Django сохранял его автоматически, используя опцию upload_to='post/videos/thumbs
в определении модели
Пожалуйста, направьте меня в правильном направлении, как это сделать.
Посмотрев на свой самоответ, вы можете немного уплотнить свой код:
file.seek(0)
args = ['ffmpeg', '-i', 'pipe:0', '-ss', '00:00:01', '-vf', 'scale=200:220',
'-vframes', '1', '-f', 'image2pipe', '-c', 'mjpeg', 'pipe:1']
content = subprocess.run(args, input=file, stdout=subprocess.PIPE)
self.instance.video = self.files['file']
self.instance.video_thumb = ContentFile(content=output_stream[0], name=filename)
[оригинальный ответ ниже]
Вот частичный ответ. Чтобы получить вывод ffmpeg в виде bytes
, укажите формат изображения и кодек и передайте его в stdout
:
bytes = subprocess.run(
['ffmpeg', '-i', video_input_path, '-ss', '00:00:01', '-vf', 'scale=200:220',
'-vframes', '1', -f image2pipe -c mjpeg -],stdout=subprocess.PIPE)
Я не знаю Django, чтобы прокомментировать, что делать с этими данными дальше
Кажется, мне удалось заставить его работать. Не уверен, что это правильный способ сделать это, но похоже, что это работает. Буду благодарен, если кто-нибудь добавит что-нибудь по этому поводу.
file.seek(0)
args = ['ffmpeg', '-i', 'pipe:0', '-ss', '00:00:01', '-vf', 'scale=200:220',
'-vframes', '1', '-f', 'image2pipe', '-c', 'mjpeg', 'pipe:1']
ffmpeg_process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output_stream = ffmpeg_process.communicate(file.read())
self.instance.video = self.files['file']
self.instance.video_thumb = ContentFile(content=output_stream[0], name=filename)