Skip to content

Commit

Permalink
Base functionality to create movies from images (#776)
Browse files Browse the repository at this point in the history
* ADD: Adding utility to combine images into a movie using moviepy

* ENH: Adding moviepy to readme as optional dependency and to CI file

* ENH: Adding moviepy to docs build environment as well

* ENH: Resolving requests for modifications

* ENH: PEP8 errors

* ENH: Changing test to use images on github repo
  • Loading branch information
AdamTheisen authored Dec 19, 2023
1 parent 23dc947 commit 0025a74
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Optional Dependencies
* `scikit-posthocs <https://scikit-posthocs.readthedocs.io/en/latest/>`_ Using interquartile range or generalized Extreme Studentized Deviate quality control tests
* `icartt <https://mbees.med.uni-augsburg.de/docs/icartt/2.0.0/>`_ icartt is an ICARTT file format reader and writer for Python
* `PySP2 <https://arm-doe.github.io/PySP2/>`_ PySP2 is a python package for reading and processing Single Particle Soot Photometer (SP2) datasets.
* `MoviePy <https://zulko.github.io/moviepy/>`_ MoviePy is a python package for creating movies from images

Installation
~~~~~~~~~~~~
Expand Down
23 changes: 22 additions & 1 deletion act/tests/utils/test_io_utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import tempfile
from pathlib import Path
from os import PathLike
from os import PathLike, getcwd
from string import ascii_letters
import random
import glob
import pytest
import os

import act
from act.tests import sample_files

try:
import moviepy.video.io.ImageSequenceClip
MOVIEPY_AVAILABLE = True
except ImportError:
MOVIEPY_AVAILABLE = False


def test_read_netcdf_gztarfiles():
with tempfile.TemporaryDirectory() as tmpdirname:
Expand Down Expand Up @@ -203,3 +212,15 @@ def test_gunzip():
assert file.endswith('.nc')

assert Path(unpack_filename).is_file() is False


@pytest.mark.skipif(not MOVIEPY_AVAILABLE, reason='MoviePy is not installed.')
def test_generate_movie():
files = [
'https://github.com/ARM-DOE/ACT/blob/main/act/tests/plotting/baseline/test_contour.png?raw=true',
'https://github.com/ARM-DOE/ACT/blob/main/act/tests/plotting/baseline/test_contour2.png?raw=true',
'https://github.com/ARM-DOE/ACT/blob/main/act/tests/plotting/baseline/test_contourf.png?raw=true',
'https://github.com/ARM-DOE/ACT/blob/main/act/tests/plotting/baseline/test_contourf2.png?raw=true'
]
result = act.utils.generate_movie(files, fps=5)
assert str(result) == 'movie.mp4'
3 changes: 2 additions & 1 deletion act/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
'cleanup_files',
'is_gunzip_file',
'pack_gzip',
'unpack_gzip'
'unpack_gzip',
'generate_movie'
],
},
)
58 changes: 58 additions & 0 deletions act/utils/io_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
import shutil
import tempfile

try:
import moviepy.video.io.ImageSequenceClip
MOVIEPY_AVAILABLE = True
except ImportError:
MOVIEPY_AVAILABLE = False


def pack_tar(filenames, write_filename=None, write_directory=None, remove=False):
"""
Expand Down Expand Up @@ -276,3 +282,55 @@ def unpack_gzip(filename, write_directory=None, remove=False):
Path(filename).unlink()

return str(write_filename)


def generate_movie(images, write_directory=None, write_filename=None, fps=10, codec=None, threads=None):
"""
Creates a movie from a list of images
...
Parameters
----------
images : list
List of images in the correct order to make into a movie
write_directory : str, pahtlib.Path, list, None
Path to directory to place newly created gunzip file.
write_filename : str, pathlib.Path, None
Movie output filename
fps: int
Frames per second
codec: int
Codec to use for image encoding
threads: int
Number of threads to use for ffmpeg
Returns
-------
write_filename : str
Full path name of created gunzip file
"""
if not MOVIEPY_AVAILABLE:
raise ImportError(
'MoviePy needs to be installed on your system to make movies.'
)

if write_filename is None:
write_filename = 'movie.mp4'

if write_directory is not None:
write_directory = Path(write_directory)
write_directory.mkdir(parents=True, exist_ok=True)
write_filename = Path(write_filename).name
elif Path(write_filename).parent != Path('.'):
write_directory = Path(write_filename).parent
else:
write_directory = Path('.')

full_path = write_directory / write_filename
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(images, fps=fps)
clip.write_videofile(str(full_path), codec=codec, threads=threads)

return full_path
1 change: 1 addition & 0 deletions continuous_integration/environment_actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies:
- lazy_loader
- cmweather
- arm-test-data
- moviepy
- pip:
- mpl2nc
- metpy
Expand Down
1 change: 1 addition & 0 deletions docs/environment_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies:
- pip
- shapely<1.8.3
- arm-test-data
- moviepy
- pip:
- mpl2nc
- lazy_loader
Expand Down

0 comments on commit 0025a74

Please sign in to comment.