Support libav for video processing

This commit is contained in:
Jerome Charaoui 2014-01-29 18:11:25 -05:00
parent 471e0eb820
commit 213fd2ffc7
2 changed files with 46 additions and 18 deletions

View File

@ -7,7 +7,7 @@ from PIL import Image
from PIL.ExifTags import TAGS from PIL.ExifTags import TAGS
import gc import gc
import tempfile import tempfile
import subprocess from VideoToolWrapper import *
class Album(object): class Album(object):
def __init__(self, path): def __init__(self, path):
@ -236,11 +236,8 @@ class Photo(object):
_photo_metadata.subject_distance_range_list = ["Unknown", "Macro", "Close view", "Distant view"] _photo_metadata.subject_distance_range_list = ["Unknown", "Macro", "Close view", "Distant view"]
def _video_metadata(self, path, original=True): def _video_metadata(self, path, original=True):
try: p = VideoProbeWrapper().call('-show_format', '-show_streams', '-of', 'json', '-loglevel', '0', path)
p = subprocess.check_output(['/usr/bin/ffprobe', '-show_format', '-show_streams', '-of', 'json', '-loglevel', '0', path]) if p == False:
except KeyboardInterrupt:
raise
except:
self.is_valid = False self.is_valid = False
return return
info = json.loads(p) info = json.loads(p)
@ -330,12 +327,8 @@ class Photo(object):
def _video_thumbnails(self, thumb_path, original_path): def _video_thumbnails(self, thumb_path, original_path):
(tfd, tfn) = tempfile.mkstemp(); (tfd, tfn) = tempfile.mkstemp();
try: p = VideoTranscodeWrapper().call('-i', original_path, '-f', 'image2', '-vsync', '1', '-vframes', '1', '-an', '-loglevel', 'quiet', tfn)
subprocess.check_call(['/usr/bin/ffmpeg', '-i', original_path, '-f', 'image2', '-vsync', '1', '-vframes', '1', '-an', '-loglevel', 'quiet', tfn]) if p == False:
except KeyboardInterrupt:
os.unlink(tfn)
raise
except:
message("couldn't extract video frame", os.path.basename(original_path)) message("couldn't extract video frame", os.path.basename(original_path))
os.unlink(tfn) os.unlink(tfn)
self.is_valid = False self.is_valid = False
@ -364,7 +357,7 @@ class Photo(object):
def _video_transcode(self, transcode_path, original_path): def _video_transcode(self, transcode_path, original_path):
transcode_path = os.path.join(transcode_path, cache_base(self._path) + '.webm') transcode_path = os.path.join(transcode_path, cache_base(self._path) + '.webm')
transcode_cmd = ['/usr/bin/ffmpeg', '-i', original_path, '-c:v', 'libvpx', '-crf', '10', '-b:v', '800k', '-c:a', 'libvorbis', '-f', 'webm', '-threads', '2', '-loglevel', '0', '-y'] transcode_cmd = ['-i', original_path, '-c:v', 'libvpx', '-crf', '10', '-b:v', '800k', '-c:a', 'libvorbis', '-f', 'webm', '-threads', '2', '-loglevel', '0', '-y']
filters = [] filters = []
info_string = "%s -> webm" % (os.path.basename(original_path)) info_string = "%s -> webm" % (os.path.basename(original_path))
message("transcoding", info_string) message("transcoding", info_string)
@ -384,11 +377,8 @@ class Photo(object):
transcode_cmd.append('-vf') transcode_cmd.append('-vf')
transcode_cmd.append(','.join(filters)) transcode_cmd.append(','.join(filters))
transcode_cmd.append(transcode_path) transcode_cmd.append(transcode_path)
try: p = VideoTranscodeWrapper().call(*transcode_cmd)
subprocess.call(transcode_cmd) if p == False:
except KeyboardInterrupt:
raise
except:
message("transcoding failure", os.path.basename(original_path)) message("transcoding failure", os.path.basename(original_path))
try: try:
os.unlink(transcode_path) os.unlink(transcode_path)

View File

@ -0,0 +1,38 @@
from CachePath import message
import os
import subprocess
class VideoToolWrapper(object):
def call(self, *args):
path = args[-1]
for tool in self.wrappers:
try:
p = subprocess.check_output((tool,) + args)
except KeyboardInterrupt:
if self.cleanup:
self.remove(path)
raise
except OSError:
continue
except:
if self.cleanup:
self.remove(path)
return False
return p
return False
def remove(self, path):
try:
os.unlink(path)
except:
pass
class VideoTranscodeWrapper(VideoToolWrapper):
def __init__(self):
self.wrappers = ['avconv', 'ffmpeg']
self.cleanup = True
class VideoProbeWrapper(VideoToolWrapper):
def __init__(self):
self.wrappers = ['avprobe', 'ffprobe']
self.cleanup = False