diff --git a/.travis.yml b/.travis.yml index 46f1db6..a34d751 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ python: before_install: # Dependencies to build PIL - sudo apt-get update -qq + - sudo apt-get install -qq ubuntu-restricted-extras - sudo apt-get install -qq libfreetype6-dev libjpeg8-dev zlib1g-dev ffmpeg - sudo locale-gen fr_FR.UTF-8 install: diff --git a/AUTHORS b/AUTHORS index 30d99e0..215c7da 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,7 @@ alphabetical order): - Keith Johnson - Lukas Vacek - Matthias Vogelgesang +- Miroslav Pavleski - Nicolas Arnaud-Cormos - Nikolai Prokoschenko - @phaer diff --git a/sigal/gallery.py b/sigal/gallery.py index 62e2689..9eef6c8 100644 --- a/sigal/gallery.py +++ b/sigal/gallery.py @@ -181,9 +181,13 @@ class Video(Media): self.date = None self.src_filename = filename if not settings['use_orig'] or not is_valid_html5_video(ext): - self.filename = self.url = base + '.webm' - self.mime = get_mime('.webm') - self.dst_path = join(settings['destination'], path, base + '.webm') + video_format = settings['video_format'] + + ext = '.' + video_format + + self.filename = self.url = base + ext + self.mime = get_mime(ext) + self.dst_path = join(settings['destination'], path, base + ext) else: self.mime = get_mime(ext) diff --git a/sigal/plugins/upload_s3.py b/sigal/plugins/upload_s3.py index 3025f0c..0594ab0 100644 --- a/sigal/plugins/upload_s3.py +++ b/sigal/plugins/upload_s3.py @@ -72,7 +72,7 @@ def generate_cache_metadata(gallery, f): proposed_cache_control = None if 'media_max_age' in gallery.settings['upload_s3_options'] and \ - file_extension in ['.jpg','.png','.webm']: + file_extension in ['.jpg','.png','.webm','.mp4']: proposed_cache_control = "max-age=%s" % \ gallery.settings['upload_s3_options']['media_max_age'] elif 'max_age' in gallery.settings['upload_s3_options']: diff --git a/sigal/settings.py b/sigal/settings.py index e6518cc..39380c4 100644 --- a/sigal/settings.py +++ b/sigal/settings.py @@ -67,8 +67,10 @@ _DEFAULT_CONFIG = { 'use_orig': False, 'video_size': (480, 360), 'watermark': '', + 'video_format': 'webm', 'webm_options': ['-crf', '10', '-b:v', '1.6M', '-qmin', '4', '-qmax', '63'], + 'mp4_options': ['-crf', '23', '-strict', '-2' ], 'write_html': True, 'zip_gallery': False, 'zip_media_format': 'resized', diff --git a/sigal/templates/sigal.conf.py b/sigal/templates/sigal.conf.py index 752e5b1..dabf9f4 100644 --- a/sigal/templates/sigal.conf.py +++ b/sigal/templates/sigal.conf.py @@ -122,6 +122,10 @@ ignore_files = [] # 'optimize': True, # 'progressive': True} +# Video format +# specify an alternative format, valid are 'webm' (default) and 'mp4' +# video_format = 'webm' + # Webm options # Options used in ffmpeg to encode the webm video. You may want to read # http://ffmpeg.org/trac/ffmpeg/wiki/vpxEncodingGuide @@ -130,6 +134,11 @@ ignore_files = [] # webm_options = ['-crf', '10', '-b:v', '1.6M', # '-qmin', '4', '-qmax', '63'] +# MP4 options +# Options used to encode the mp4 video. You may want to read +# https://trac.ffmpeg.org/wiki/Encode/H.264 +# mp4_options = ['-crf', '23' ] + # Size of resized video (default: (480, 360)) # video_size = (480, 360) diff --git a/sigal/video.py b/sigal/video.py index 0d7aed3..aed6514 100644 --- a/sigal/video.py +++ b/sigal/video.py @@ -156,9 +156,15 @@ def process_video(filepath, outpath, settings): outname = os.path.join(outpath, filename) utils.copy(filepath, outname, symlink=settings['orig_link']) else: - outname = os.path.join(outpath, basename + '.webm') + valid_formats = ['mp4', 'webm'] + video_format = settings['video_format'] + + if video_format not in valid_formats: + raise ValueError('Invalid video_format. Please choose one of: ' + str(valid_formats)) + + outname = os.path.join(outpath, basename + '.' + video_format) generate_video(filepath, outname, settings, - options=settings['webm_options']) + options=settings[video_format + '_options']) except Exception: return Status.FAILURE diff --git a/tests/test_video.py b/tests/test_video.py index 61eda75..2841052 100644 --- a/tests/test_video.py +++ b/tests/test_video.py @@ -3,6 +3,7 @@ from __future__ import division import os +import pytest from sigal.video import video_size, generate_video from sigal.settings import create_settings @@ -16,13 +17,16 @@ def test_video_size(): size_src = video_size(SRCFILE) assert size_src == (480, 270) - -def test_generate_video_fit_height(tmpdir): +@pytest.mark.parametrize("fmt", [ + ('webm'), + ('mp4') +]) +def test_generate_video_fit_height(tmpdir, fmt): """largest fitting dimension is height""" base, ext = os.path.splitext(TEST_VIDEO) - dstfile = str(tmpdir.join(base + '.webm')) - settings = create_settings(video_size=(50, 100)) + dstfile = str(tmpdir.join(base + '.' + fmt)) + settings = create_settings(video_size=(50, 100), video_format=fmt) generate_video(SRCFILE, dstfile, settings) size_src = video_size(SRCFILE) @@ -32,13 +36,16 @@ def test_generate_video_fit_height(tmpdir): # less than 2% error on ratio assert abs(size_dst[0]/size_dst[1] - size_src[0]/size_src[1]) < 2e-2 - -def test_generate_video_fit_width(tmpdir): +@pytest.mark.parametrize("fmt", [ + ('webm'), + ('mp4') +]) +def test_generate_video_fit_width(tmpdir, fmt): """largest fitting dimension is width""" base, ext = os.path.splitext(TEST_VIDEO) - dstfile = str(tmpdir.join(base + '.webm')) - settings = create_settings(video_size=(100, 50)) + dstfile = str(tmpdir.join(base + '.' + fmt)) + settings = create_settings(video_size=(100, 50), video_format=fmt) generate_video(SRCFILE, dstfile, settings) size_src = video_size(SRCFILE) @@ -48,15 +55,17 @@ def test_generate_video_fit_width(tmpdir): # less than 2% error on ratio assert abs(size_dst[0]/size_dst[1] - size_src[0]/size_src[1]) < 2e-2 - -def test_generate_video_dont_enlarge(tmpdir): +@pytest.mark.parametrize("fmt", [ + ('webm'), + ('mp4') +]) +def test_generate_video_dont_enlarge(tmpdir, fmt): """video dimensions should not be enlarged""" base, ext = os.path.splitext(TEST_VIDEO) - dstfile = str(tmpdir.join(base + '.webm')) - settings = create_settings(video_size=(1000, 1000)) + dstfile = str(tmpdir.join(base + '.' + fmt)) + settings = create_settings(video_size=(1000, 1000), video_format=fmt) generate_video(SRCFILE, dstfile, settings) - size_src = video_size(SRCFILE) size_dst = video_size(dstfile)