https://sppas.org/

SPPAS 4.16

Module sppas.src.videodata

Class sppasVideoWriter

Description

Class to write a video on disk, image by image.

This class is embedding a VideoWriter() object and define some

getters and setters to manage such video easily.

Videos have a default resolution of "SD": (704*528)@25

Constructor

Create a sppasVideoWriter.

def __init__(self):
    """Create a sppasVideoWriter. """
    self.__video = cv2.VideoWriter()
    self._fps = 25.0
    self._size = (704, 528)
    self._aspect = sppasVideoWriter.ASPECT['extend']
    self.__lock = False
    self.__nframes = 0

Public functions

get_extensions

Return the list of supported file extensions.

@staticmethod
def get_extensions():
    """Return the list of supported file extensions."""
    return tuple(sppasVideoWriter.FOURCC.keys())
get_fourcc

Return the FOURCC string corresponding to an extension.

Parameters

  • ext: (str) Extension of a filename

Returns

  • (str)
@staticmethod
def get_fourcc(ext):
    """Return the FOURCC string corresponding to an extension.

        :param ext: (str) Extension of a filename
        :return: (str)

        """
    ext = str(ext)
    if ext.startswith('.') is False:
        ext = '.' + ext.lower()
    return sppasVideoWriter.FOURCC.get(ext, '')
get_ext

Return the extension string corresponding to the fourcc.

Parameters

  • fourcc: (str) FOURCC name

Returns

  • (str)
@staticmethod
def get_ext(fourcc):
    """Return the extension string corresponding to the fourcc.

        :param fourcc: (str) FOURCC name
        :return: (str)

        """
    if isinstance(fourcc, (list, tuple)):
        fourcc = ''.join(fourcc)
    else:
        fourcc = str(fourcc)
        fourcc = fourcc.replace(' ', '')
    fourcc = fourcc.lower()
    for ext in sppasVideoWriter.FOURCC:
        if sppasVideoWriter.FOURCC[ext] == fourcc:
            return ext
    return ''
set_resolution

Set the video resolution: images size and frame rate.

Some of the possible values for the name of the resolution are:

  • LD: 640 x 480 / 15 fps
  • SD: 704 x 528 / 25 fps
  • HD: 1920 x 1080 / 25 fps
  • WFHD: 2560 x 1080 / 25 fps
  • UHD: 2560 x 1440 / 25 fps
  • 4K: 3840 x 2160 / 30 fps
  • 8K: 7680 x 4320 / 60 fps

Parameters

  • name: (str) Name of the resolution

Raises

VideoLockError, sppasKeyError

def set_resolution(self, name='SD'):
    """Set the video resolution: images size and frame rate.

        Some of the possible values for the name of the resolution are:

            - LD: 640 x 480 / 15 fps
            - SD: 704 x 528 / 25 fps
            - HD: 1920 x 1080 / 25 fps
            - WFHD: 2560 x 1080 / 25 fps
            - UHD: 2560 x 1440 / 25 fps
            - 4K: 3840 x 2160 / 30 fps
            - 8K: 7680 x 4320 / 60 fps

        :param name: (str) Name of the resolution
        :raise: VideoLockError, sppasKeyError

        """
    if self.__lock is True:
        logging.error('The video resolution can only be changed if the video stream is not already opened.')
        raise VideoLockError
    if name.upper() not in sppasVideoWriter.RESOLUTIONS.keys():
        raise sppasKeyError(name, 'RESOLUTIONS')
    resolution = sppasVideoWriter.RESOLUTIONS[name.upper()]
    self._size = (resolution[0], resolution[1])
    self._fps = resolution[2]
get_size

Return the (width, height) of the video.

def get_size(self):
    """Return the (width, height) of the video."""
    return self._size
set_size

Fix a personalized size for the video to write.

Parameters

  • width: (int) number of columns in range (20, 12000)
  • height: (int) number of rows in range (20, 5000)
def set_size(self, width, height):
    """Fix a personalized size for the video to write.

        :param width: (int) number of columns in range (20, 12000)
        :param height: (int) number of rows in range (20, 5000)

        """
    if self.__lock is True:
        logging.error('The video size can only be changed if the video stream is not already opened.')
        raise VideoLockError
    width = int(width)
    height = int(height)
    if width < 0 or width > 10000:
        raise IntervalRangeException(width, 0, 5000)
    if height < 0 or height > 5000:
        raise IntervalRangeException(height, 0, 5000)
    self._size = (width, height)
get_fps

Return the defined fps value (float) to write video files.

def get_fps(self):
    """Return the defined fps value (float) to write video files."""
    return self._fps
set_fps

Fix the framerate of the output video.

Parameters

  • value: (float) frame per seconds

Raises

NegativeValueError, IntervalRangeError

def set_fps(self, value):
    """Fix the framerate of the output video.

        :param value: (float) frame per seconds
        :raise: NegativeValueError, IntervalRangeError

        """
    if self.__lock is True:
        logging.error('The video fps can only be changed if the video stream is not already opened.')
        raise VideoLockError
    value = float(value)
    if value < 0.0:
        raise NegativeValueError(value)
    if value > sppasVideoWriter.MAX_FPS:
        raise IntervalRangeException(value, 0.0, sppasVideoWriter.MAX_FPS)
    self._fps = value
open

Open a file stream to write images into.

Parameters

  • video: (str) Filename
def open(self, video):
    """Open a file stream to write images into.

        :param video: (str) Filename

        """
    if self.__lock is True:
        logging.error("The video can't be opened because another video stream is not already opened.")
        raise VideoLockError
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    try:
        self.__video.open(video, fourcc, self._fps, self._size)
        if self.__video.isOpened() is False:
            raise IOError('The video was not opened by OpenCV Library for an unknown reason.')
        self.__lock = True
        self.__nframes = 0
    except Exception as e:
        logging.error("Video {} can't be created: {}".format(video, str(e)))
        raise VideoWriteError(video)
is_opened

Return True if a video is already opened and ready to write.

def is_opened(self):
    """Return True if a video is already opened and ready to write."""
    return self.__lock
close

Release the flow taken by the reading of the video.

def close(self):
    """Release the flow taken by the reading of the video."""
    self.__video.release()
    self.__lock = False
    self.__nframes = 0
get_framerate

Return the FPS of the current video (float).

def get_framerate(self):
    """Return the FPS of the current video (float)."""
    return self._fps
get_width

Return the width of the frames in the video.

def get_width(self):
    """Return the width of the frames in the video."""
    return self._size[0]
get_height

Return the height of the frames in the video.

def get_height(self):
    """Return the height of the frames in the video."""
    return self._size[1]
get_nframes

Return the number of frames written in the video.

def get_nframes(self):
    """Return the number of frames written in the video."""
    return self.__nframes
get_duration

Return the duration of the written video in seconds (float).

def get_duration(self):
    """Return the duration of the written video in seconds (float)."""
    if self.__lock is False:
        return 0.0
    return float(self.get_nframes()) * (1.0 / self.get_framerate())
get_aspect

Return a string defining the aspect strategy to write images.

Parameters
  • as_int
def get_aspect(self, as_int=True):
    """Return a string defining the aspect strategy to write images."""
    if as_int is True:
        return self._aspect
    return sppasVideoWriter.ASPECT[self._aspect]
set_aspect

Set the aspect strategy to write the image.

Parameters

  • aspect: (int or str)
def set_aspect(self, aspect):
    """Set the aspect strategy to write the image.

        :param aspect: (int or str)

        """
    if aspect not in sppasVideoWriter.ASPECT:
        raise KeyError('Unknown image aspect {}'.format(self._aspect))
    if isinstance(aspect, int):
        aspect = sppasVideoWriter.ASPECT[aspect]
    self._aspect = sppasVideoWriter.ASPECT[aspect]
write

Append an image to the video stream.

Parameters
  • image
def write(self, image):
    """Append an image to the video stream."""
    if self.__lock is False:
        raise Exception("Actually there's no video stream defined.")
    w, h = self._size
    if self._aspect in ('center', sppasVideoWriter.ASPECT['center']):
        img = image.icenter(w, h)
    elif self._aspect in ('stretch', sppasVideoWriter.ASPECT['stretch']):
        img = image.iresize(w, h)
    elif self._aspect in ('extend', sppasVideoWriter.ASPECT['extend']):
        img = image.iextend(w, h)
    elif self._aspect in ('zoom', sppasVideoWriter.ASPECT['zoom']):
        img = image.izoom(w, h)
    else:
        raise Exception("Can't write image: unknown image aspect {}".format(self._aspect))
    if img.width != w or img.height != h:
        img = img.iresize(w, h)
    self.__video.write(img)