  
          if self._task == "save" and not os.path.isdir(self.location):
              raise FaceswapError("The output location '{}' is not a folder".format(self.location))
  
          is_video = (self._task == "load" and
                      os.path.isfile(self.location) and
                      os.path.splitext(self.location)[1].lower() in _video_extensions)
          if is_video:
              logger.debug("Input is video")
          else:
              logger.debug("Input is folder")
          return is_video
  
      def _set_thread(self, io_args=None):
 
</s> remove         if self._task == "save" and not os.path.isdir(self.location):
            raise FaceswapError("The output location '{}' is not a folder".format(self.location))
 </s> add         Raises
        ------
        FaceswapError
            If the given location is a file and does not have a valid video extension. </s> remove             logger.debug("Input is folder")
        return is_video
 </s> add             raise FaceswapError("The input file '{}' is not a valid video".format(self.location))
        logger.debug("Input '%s' is_video: %s", self.location, retval)
        return retval

    def _get_count_and_filelist(self, fast_count):
        """ Set the count of images to be processed and set the file list </s> remove         """
        if not os.path.exists(self.location):
            raise FaceswapError("The location '{}' does not exist".format(self.location))
 </s> add  </s> remove     def _set_thread(self, io_args=None):
        """ Set the load/save thread
 </s> add             If the input is a video, a dummy file list is created for checking against an
            alignments file, otherwise it will be a list of full filenames. </s> remove     # SAVING #
    @staticmethod
    def _save(*args):
 </s> add class ImagesSaver(ImageIO):
    """ Perform image saving to a destination folder.

    Images are saved in a background ThreadPoolExecutor to allow for concurrent saving.
    See also :class:`ImageIO` for additional attributes.

    Parameters
    ----------
    path: str
        The folder to save images to. This must be an existing folder.
    queue_size: int, optional
        The amount of images to hold in the internal buffer. Default: 8.
    as_bytes: bool, optional
        ``True`` if the image is already encoded to bytes, ``False`` if the image is a
        :class:`numpy.ndarray`. Default: ``False``.

    Examples
    --------

    >>> saver = ImagesSaver('/path/to/save/folder')
    >>> for filename, image in <image_iterator>:
    >>>     saver.save(filename, image)
    >>> saver.close()
    """

    def __init__(self, path, queue_size=8, as_bytes=False):
        logger.debug("Initializing %s: (path: %s, load_with_hash: %s, as_bytes: %s)",
                     self.__class__.__name__, path, queue_size, as_bytes)

        super().__init__(path, queue_size=queue_size)
        self._as_bytes = as_bytes

    def _check_location_exists(self):
        """ Check whether the output location exists and is a folder

        Raises
        ------
        FaceswapError
            If the given location does not exist or the location is not a folder
        """
        if not isinstance(self.location, str):
            raise FaceswapError("The output location must be a string not a "
                                "{}".format(type(self.location)))
        super()._check_location_exists()
        if not os.path.isdir(self.location):
            raise FaceswapError("The output location '{}' is not a folder".format(self.location))

    def _process(self, queue):
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
  
          if self._task == "save" and not os.path.isdir(self.location):
              raise FaceswapError("The output location '{}' is not a folder".format(self.location))
  
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
        """
        if os.path.isdir(self.location):
            retval = False
        elif os.path.splitext(self.location)[1].lower() in _video_extensions:
            retval = True
          else:
              logger.debug("Input is folder")
          return is_video
  
      def _set_thread(self, io_args=None):
keep keep keep keep replace replace replace replace replace keep keep keep keep keep
 scripts.extract - code optimizations

Limit queue sizes to reduce RAM usage
Rename lib.image.BackgroundIO to ImageIO
Create separate ImagesLoader and ImagesSaver classes
Load/Save images from centralized lib.image.ImageIO
scripts.extract documentation 
lib/image.py