Tweaks to support processing lighthouse videos
diff --git a/visualmetrics.py b/visualmetrics.py
index b1cb3a0..075f2de 100755
--- a/visualmetrics.py
+++ b/visualmetrics.py
@@ -80,6 +80,7 @@
remove_orange_frames(dir, orange_file)
find_first_frame(dir, white_file)
find_render_start(dir)
+ find_last_frame(dir, white_file)
adjust_frame_times(dir)
if timeline_file is not None and not multiple:
synchronize_to_timeline(dir, timeline_file)
@@ -388,7 +389,18 @@
def find_first_frame(directory, white_file):
global options
try:
- if options.findstart > 0 and options.findstart <= 100:
+ if options.startwhite:
+ files = sorted(glob.glob(os.path.join(directory, 'video-*.png')))
+ count = len(files)
+ if count > 1:
+ from PIL import Image
+ for i in xrange(count):
+ if is_white_frame(files[i], white_file):
+ break
+ else:
+ logging.debug('Removing non-white frame {0} from the beginning'.format(files[i]))
+ os.remove(files[i])
+ elif options.findstart > 0 and options.findstart <= 100:
files = sorted(glob.glob(os.path.join(directory, 'video-*.png')))
count = len(files)
if count > 1:
@@ -429,6 +441,27 @@
logging.exception('Error finding first frame')
+def find_last_frame(directory, white_file):
+ global options
+ try:
+ if options.endwhite:
+ files = sorted(glob.glob(os.path.join(directory, 'video-*.png')))
+ count = len(files)
+ if count > 2:
+ found_end = False
+ from PIL import Image
+ for i in xrange(2, count):
+ if found_end:
+ logging.debug('Removing frame {0} from the end'.format(files[i]))
+ os.remove(files[i])
+ if is_white_frame(files[i], white_file):
+ found_end = True
+ logging.debug('Removing ending white frame {0}'.format(files[i]))
+ os.remove(files[i])
+ except:
+ logging.exception('Error finding last frame')
+
+
def find_render_start(directory):
global options
global client_viewport
@@ -651,10 +684,15 @@
def is_white_frame(file, white_file):
global client_viewport
+ global options
white = False
if os.path.isfile(white_file):
- command = ('convert "{0}" "(" "{1}" -gravity Center -crop 50%x33%+0+0 -resize 200x200! ")" miff:- | '
- 'compare -metric AE - -fuzz 10% null:').format(white_file, file)
+ if options.viewport:
+ command = ('convert "{0}" "(" "{1}" -resize 200x200! ")" miff:- | '
+ 'compare -metric AE - -fuzz 10% null:').format(white_file, file)
+ else:
+ command = ('convert "{0}" "(" "{1}" -gravity Center -crop 50%x33%+0+0 -resize 200x200! ")" miff:- | '
+ 'compare -metric AE - -fuzz 10% null:').format(white_file, file)
if client_viewport is not None:
crop = '{0:d}x{1:d}+{2:d}+{3:d}'.format(client_viewport['width'], client_viewport['height'], client_viewport['x'], client_viewport['y'])
command = ('convert "{0}" "(" "{1}" -crop {2} -resize 200x200! ")" miff:- | '
@@ -663,7 +701,7 @@
out, err = compare.communicate()
if re.match('^[0-9]+$', err):
different_pixels = int(err)
- if different_pixels < 100:
+ if different_pixels < 500:
white = True
return white
@@ -922,6 +960,23 @@
########################################################################################################################
+# Screen Shots
+########################################################################################################################
+
+
+def save_screenshot(directory, dest, quality):
+ directory = os.path.realpath(directory)
+ files = sorted(glob.glob(os.path.join(directory, 'ms_*.png')))
+ if files is not None and len(files) >= 1:
+ src = files[-1]
+ if dest[-4:] == '.jpg':
+ command = 'convert "{0}" -set colorspace sRGB -quality {1:d} "{2}"'.format(src, quality, dest)
+ subprocess.call(command, shell=True)
+ else:
+ shutil.copy(src, dest)
+
+
+########################################################################################################################
# JPEG conversion
########################################################################################################################
@@ -1236,6 +1291,7 @@
parser.add_argument('-i', '--video', help="Input video file.")
parser.add_argument('-d', '--dir', help="Directory of video frames "
"(as input if exists or as output if a video file is specified).")
+ parser.add_argument('--screenshot', help="Save the last frame of video as an image to the path provided.")
parser.add_argument('-g', '--histogram', help="Histogram file (as input if exists or as output if "
"histograms need to be calculated).")
parser.add_argument('-m', '--timeline', help="Timeline capture from Chrome dev tools. Used to synchronize the video"
@@ -1270,6 +1326,10 @@
"of the video (like a browser address bar).")
parser.add_argument('--renderignore', type=int, default=0, help="Ignore the center X% of the frame when looking for "
"the first rendered frame (useful for Opera mini).")
+ parser.add_argument('--startwhite', action='store_true', default=False,
+ help="Find the first fully white frame as the start of the video.")
+ parser.add_argument('--endwhite', action='store_true', default=False,
+ help="Find the first fully white frame after render start as the end of the video.")
parser.add_argument('--forceblank', action='store_true', default=False,
help="Force the first frame to be blank white.")
parser.add_argument('--trimend', type=int, default=0, help="Time to trim from the end of the video "
@@ -1327,7 +1387,7 @@
orange_file = os.path.join(temp_dir, 'orange.png')
generate_orange_png(orange_file)
white_file = None
- if options.white:
+ if options.white or options.startwhite or options.endwhite:
white_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'white.png')
if not os.path.isfile(white_file):
white_file = os.path.join(temp_dir, 'white.png')
@@ -1339,6 +1399,11 @@
calculate_histograms(directory, histogram_file, options.force)
metrics = calculate_visual_metrics(histogram_file, options.start, options.end, options.perceptual,
directory)
+ if options.screenshot is not None:
+ quality = 30
+ if options.quality is not None:
+ quality = options.quality
+ save_screenshot(directory, options.screenshot, quality)
# JPEG conversion
if options.dir is not None and options.quality is not None:
convert_to_jpeg(directory, options.quality)