                                       len(self._rollover.detected_faces), frame_faces,
                                       item.filename)
                      break
          if batch:
              logger.trace("Returning batch: %s", {k: v.shape if isinstance(v, np.ndarray) else v
                                                   for k, v in batch.items()})
          else:
              logger.trace(item)
          return exhausted, batch
  
      def _collect_item(self, queue):
 
</s> remove             logger.trace(item)
 </s> add             logger.trace(item)  # type:ignore </s> remove                         logger.trace("Rolled over %s faces of %s to next batch for '%s'",
                                     len(self._rollover.detected_faces), frame_faces,
 </s> add                         logger.trace("Rolled over %s faces of %s to next batch "  # type:ignore
                                     "for '%s'", len(self._rollover.detected_faces), frame_faces, </s> remove     def _collect_item(self, queue):
        """ Collect the item from the :attr:`_rollover` dict or from the queue
            Add face count per frame to self._faces_per_filename for joining
            batches back up in finalize """
 </s> add     def _collect_item(self, queue: "Queue") -> Union[Literal["EOF"], ExtractMedia]:
        """ Collect the item from the :attr:`_rollover` dict or from the queue. Add face count per
        frame to self._faces_per_filename for joining batches back up in finalize

        Parameters
        ----------
        queue: :class:`queue.Queue`
            The input queue to the aligner. Should contain
            :class:`~plugins.extract.pipeline.ExtractMedia` objects

        Returns
        -------
        :class:`~plugins.extract.pipeline.ExtractMedia` or EOF
            The next extract media object, or EOF if pipe has ended
        """ </s> remove         logger.trace("Item out: %s", {key: val.shape if isinstance(val, np.ndarray) else val
                                      for key, val in batch.items()})
 </s> add         logger.trace("Item out: %s", {key: val.shape  # type:ignore
                                      if isinstance(val, np.ndarray) else val
                                      for key, val in batch.__dict__.items()}) </s> remove         for filename, face in zip(batch["filename"], batch["detected_faces"]):
 </s> add         for frame, filename, face in zip(batch.image, batch.filename, batch.detected_faces):
            logger.trace("Returning batch: %s", {k: v.shape  # type:ignore
                                                 if isinstance(v, np.ndarray) else v
                                                 for k, v in batch.__dict__.items()})
                                       len(self._rollover.detected_faces), frame_faces,
                                       item.filename)
                      break
          if batch:
            logger.trace("Returning batch: %s", {k: v.shape  # type:ignore
                                                 if isinstance(v, np.ndarray) else v
                                                 for k, v in batch.__dict__.items()})
            logger.trace("Returning batch: %s", {k: v.shape  # type:ignore
                                                 if isinstance(v, np.ndarray) else v
                                                 for k, v in batch.__dict__.items()})
          else:
              logger.trace(item)
          return exhausted, batch
  
      def _collect_item(self, queue):
keep keep keep keep replace replace keep keep keep keep keep
 Extract updates:
  - Default CPU detector to MTCNN
  - add basic Aligner false positive filters
  - Typing: align + plugins
  - Use specific AlignerBatch class for alignment
  - 
plugins/extract/align/_base.py