145 lines
5.1 KiB
Python
145 lines
5.1 KiB
Python
#!/usr/bin/env python
|
|
import os.path
|
|
import sys
|
|
import ffmpeg
|
|
import time
|
|
from datetime import datetime
|
|
|
|
from _media_file import MediaFile
|
|
|
|
class VideoFile(MediaFile):
|
|
def __init__(self,max_width=1024,*args,**kwargs):
|
|
super(VideoFile, self).__init__(*args, **kwargs)
|
|
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.file = kwargs['file']
|
|
self.out = 'thumbnail.jpg'
|
|
self.max_width = max_width
|
|
self.probe = ffmpeg.probe(self.path_file_name)
|
|
self.video_capture_date = self.get_video_capture_date()
|
|
|
|
if 'video' == self.probe['streams'][0]['codec_type'].lower():
|
|
self.video_stream = self.probe['streams'][0]
|
|
elif 'video' == self.probe['streams'][1]['codec_type'].lower():
|
|
self.video_stream = self.probe['streams'][1]
|
|
elif 'video' == self.probe['streams'][2]['codec_type'].lower():
|
|
self.video_stream = self.probe['streams'][2]
|
|
|
|
if 'audio' == self.probe['streams'][0]['codec_type'].lower():
|
|
self.audio_stream = self.probe['streams'][0]
|
|
elif 'audio' == self.probe['streams'][1]['codec_type'].lower():
|
|
self.audio_stream = self.probe['streams'][1]
|
|
elif 'audio' == self.probe['streams'][2]['codec_type'].lower():
|
|
self.audio_stream = self.probe['streams'][2]
|
|
|
|
self.format_stream = self.probe['format']
|
|
self.size_width = self.get_video_width()
|
|
self.size_height = self.get_video_height()
|
|
self.size = self.get_video_size()
|
|
|
|
self.stream = {}
|
|
|
|
@staticmethod
|
|
def convert_from_seconds(seconds):
|
|
return time.strftime("%H:%M:%S", time.gmtime(seconds))
|
|
|
|
def gen_video_thumbnail(self):
|
|
"""
|
|
Generate a thumbnail from a video
|
|
"""
|
|
self.get_video_meta()
|
|
time_seconds = self.stream['video']['seconds'] // 5
|
|
v_width = int(self.stream['video']['size']['width'])
|
|
width = self.set_thumb_width(v_width)
|
|
|
|
try:
|
|
(
|
|
ffmpeg.input(
|
|
self.file,
|
|
ss = time_seconds
|
|
)
|
|
.filter(
|
|
'scale',
|
|
width,
|
|
-1
|
|
)
|
|
.output(
|
|
self.out,
|
|
vframes = 1
|
|
)
|
|
.overwrite_output()
|
|
.run(
|
|
capture_stdout = True,
|
|
capture_stderr = True
|
|
)
|
|
)
|
|
except ffmpeg.Error as e:
|
|
print(e.stderr.decode(),
|
|
file = sys.stderr)
|
|
|
|
return self.out
|
|
|
|
def set_thumb_width(self, v_width):
|
|
if v_width > self.max_width:
|
|
width = self.max_width
|
|
else:
|
|
width = v_width
|
|
|
|
return width
|
|
|
|
def get_video_width(self):
|
|
return self.video_stream['width']
|
|
|
|
def get_video_height(self):
|
|
return self.video_stream['height']
|
|
|
|
def get_video_size(self):
|
|
if self.size_width is None:
|
|
self.size_width = self.get_video_width()
|
|
if self.size_height is None:
|
|
self.size_height = self.get_video_height()
|
|
return f'{self.size_width}x{self.size_height}'
|
|
|
|
def get_video_capture_date(self):
|
|
#TODO: refactor this try/except logic.
|
|
try:
|
|
stamp = datetime.strptime(
|
|
self.format_stream['tags']['creation_time'],
|
|
'%Y-%m-%dT%H:%M:%S.%f%z'
|
|
)
|
|
except:
|
|
try:
|
|
stamp = datetime.fromtimestamp(
|
|
os.path.getctime(
|
|
self.path_file_name
|
|
)
|
|
)
|
|
except:
|
|
stamp = datetime.strptime(
|
|
str('1900:01:01 00:00:00'),
|
|
'%Y:%m:%d %H:%M:%S'
|
|
)
|
|
return stamp
|
|
|
|
def get_video_meta(self):
|
|
self.stream = {
|
|
'video': {
|
|
'bits_per_raw_sample': self.video_stream['bits_per_raw_sample'],
|
|
'codec_long_name': self.video_stream['codec_long_name'],
|
|
'duration': self.convert_from_seconds(float(self.video_stream['duration'])),
|
|
'encoding_brand': self.format_stream['tags']['major_brand'],
|
|
'pix_fmt': self.video_stream['pix_fmt'],
|
|
'profile': self.video_stream['profile'],
|
|
'r_frame_rate': self.video_stream['r_frame_rate'],
|
|
'size': {
|
|
'width_height': self.size,
|
|
'height': self.video_stream['height'],
|
|
'width': self.video_stream['width']
|
|
}
|
|
},
|
|
'audio': {},
|
|
'format': {}
|
|
}
|
|
|
|
return self.stream |