diff --git a/pandora/app/config.py b/pandora/app/config.py index 6e940fda..5d7eadd1 100644 --- a/pandora/app/config.py +++ b/pandora/app/config.py @@ -165,6 +165,10 @@ def load_config(init=False): if set(old_formats) != set(formats): sformats = supported_formats() settings.FFMPEG_SUPPORTS_VP9 = 'vp9' in sformats + try: + settings.CHOP_SUPPORT = int(sformats.get('version', ['0'])[0]) > 2 + except: + settings.CHOP_SUPPORT = False if sformats: for f in formats: if f not in sformats or not sformats[f]: diff --git a/pandora/archive/chop.py b/pandora/archive/chop.py index 3720bb28..9738c9b5 100644 --- a/pandora/archive/chop.py +++ b/pandora/archive/chop.py @@ -5,10 +5,39 @@ from bisect import bisect_left import ox +def make_keyframe_index(video): + cmd = [ + 'ffprobe', + '-v', 'error', + '-show_packets', '-select_streams', 'v', + '-show_entries', 'packet=pts_time,flags', + '-of', 'csv', + '-i', video + ] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + result = stdout.decode().strip() + keyframe_times = [] + timecode = 0 + for line in result.split('\n'): + if line.split(',')[1] != 'N/A': + timecode = line.split(',')[1] + if ',K' in line: + keyframe_times.append(float(timecode)) + + last_keyframe = ox.avinfo(video)['duration'] + if keyframe_times[-1] != last_keyframe: + keyframe_times.append(last_keyframe) + + keyframes_cache = video + '.keyframes' + with open(keyframes_cache, 'w') as fd: + json.dump(keyframe_times, fd, indent=0) + return keyframe_times + + class Chop(object): keyframes = [] subtitles = None - info = {} ffmpeg = [ 'ffmpeg', '-nostats', '-loglevel', 'error', @@ -77,12 +106,6 @@ class Chop(object): for segment in segments: os.unlink(segment) - def get_info(self): - if self.info: - return self.info - self.info = ox.avinfo(self.video) - return self.info - def get_keyframes(self): video = self.video if self.keyframes: @@ -93,35 +116,8 @@ class Chop(object): with open(keyframes_cache, 'r') as fd: self.keyframes = json.load(fd) return self.keyframes - - cmd = [ - 'ffprobe', - '-v', 'error', - '-show_packets', '-select_streams', 'v', - '-show_entries', 'packet=pts_time,flags', - '-of', 'csv', - '-i', video - ] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - result = stdout.decode().strip() - keyframe_times = [] - timecode = 0 - for line in result.split('\n'): - if line.split(',')[1] != 'N/A': - timecode = line.split(',')[1] - if ',K' in line: - keyframe_times.append(float(timecode)) - - last_keyframe = self.get_info()['duration'] - if keyframe_times[-1] != last_keyframe: - keyframe_times.append(last_keyframe) - - self.keyframes = keyframe_times - if not os.path.exists(keyframes_cache): - with open(keyframes_cache, 'w') as fd: - json.dump(keyframe_times, fd) - return keyframe_times + self.keyframes = make_keyframe_index(video) + return self.keyframes def get_gop_sections(self, start: float, end: float) -> dict: keyframes = self.get_keyframes() @@ -141,17 +137,17 @@ class Chop(object): } def encode(self, source, target, start, duration): - info = self.get_info() - if self.info['audio']: + info = ox.avinfo(self.video) + if info['audio']: acodec = [ '-c:a', - self.info['audio'][0]['codec'] + info['audio'][0]['codec'] ] else: acodec = [] vcodec = [ '-c:v', - self.info['video'][0]['codec'] + info['video'][0]['codec'] ] cmd = self.ffmpeg + [ diff --git a/pandora/archive/extract.py b/pandora/archive/extract.py index 41311812..514b29ce 100644 --- a/pandora/archive/extract.py +++ b/pandora/archive/extract.py @@ -21,6 +21,8 @@ from ox.utils import json from django.conf import settings from PIL import Image +from .chop import Chop, make_keyframe_index + img_extension = 'jpg' MAX_DISTANCE = math.sqrt(3 * pow(255, 2)) @@ -55,7 +57,10 @@ def supported_formats(): stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() stdout = stdout.decode('utf-8') + stderr = stderr.decode('utf-8') + version = stderr.split('\n')[0].split(' ')[2] return { + 'version': version.split('.'), 'ogg': 'libtheora' in stdout and 'libvorbis' in stdout, 'webm': 'libvpx' in stdout and 'libvorbis' in stdout, 'vp8': 'libvpx' in stdout and 'libvorbis' in stdout, @@ -347,6 +352,7 @@ def stream(video, target, profile, info, audio_track=0, flags={}): shutil.move(enc_target, target) for f in glob('%s.log*' % target): os.unlink(f) + make_keyframe_index(target) return True, None @@ -613,8 +619,7 @@ def chop(video, start, end, subtitles=None): fd.write(subtitles) else: subtitles_f = None - if ext == '.mp4': - from .chop import Chop + if ext == '.mp4' and settings.CHOP_SUPPORT: Chop(video, choped_video, start, end, subtitles_f) if subtitles_f: os.unlink(subtitles_f) diff --git a/pandora/archive/models.py b/pandora/archive/models.py index ec0986e9..68ef30ab 100644 --- a/pandora/archive/models.py +++ b/pandora/archive/models.py @@ -370,6 +370,7 @@ class File(models.Model): self.info.update(stream.info) self.parse_info() self.save() + extract.make_keyframe_index(stream.media.path) return True, stream.media.size return save_chunk(stream, stream.media, chunk, offset, name, done_cb) return False, 0 diff --git a/static/js/metadataDialog.js b/static/js/metadataDialog.js index f1858105..ade551ed 100644 --- a/static/js/metadataDialog.js +++ b/static/js/metadataDialog.js @@ -5,7 +5,7 @@ pandora.ui.metadataDialog = function(data) { var keys = [ 'title', 'alternativeTitles', 'director', 'country', 'year', 'language', 'runtime', 'color', 'sound', - 'productionCompany', + 'productionCompany', 'filmingLocations' 'producer', 'writer', 'cinematographer', 'editor', 'composer', 'actor', 'lyricist', 'singer', 'genre', 'keyword', 'summary'