def _get_repr_html_ffmpeg(images: List[PilImage]) -> str:
  """Runs ffmpeg to get the mp4 encoded <video> str."""
  # Find number of digits in len to give names.
  num_digits = len(str(len(images))) + 1
  with tempfile.TemporaryDirectory() as video_dir:
    for i, img in enumerate(images):
      f = os.path.join(video_dir, f'img{i:0{num_digits}d}.png')
      img.save(f, format='png')

    ffmpeg_args = [
        '-framerate', str(_VISU_FRAMERATE),
        '-i', os.path.join(video_dir, f'img%0{num_digits}d.png'),
        # Using native h264 to encode video stream to H.264 codec
        # Default encoding does not seems to be supported by chrome.
        '-vcodec', 'h264',
        # When outputting H.264, `-pix_fmt yuv420p` maximize compatibility
        # with bad video players.
        # Ref: https://trac.ffmpeg.org/wiki/Slideshow
        '-pix_fmt', 'yuv420p',
        # Native encoder cannot encode images of small scale
        # or the the hardware encoder may be busy which raises
        # Error: cannot create compression session
        # so allow software encoding
        # '-allow_sw', '1',
    ]
    video_path = utils.as_path(video_dir) / 'output.mp4'
    ffmpeg_args.append(os.fspath(video_path))
    utils.ffmpeg_run(ffmpeg_args)
    video_str = utils.get_base64(video_path.read_bytes())
  return (
      f'<video height="{THUMBNAIL_SIZE}" width="175" '
      'controls loop autoplay muted playsinline>'
      f'<source src="data:video/mp4;base64,{video_str}"  type="video/mp4" >'
      '</video>'
  )
def make_video_repr_html(ex, *, use_colormap: bool):
  """Returns the encoded `<video>` or GIF <img/> HTML."""
  # Use GIF to generate a HTML5 compatible video if FFMPEG is not
  # installed on the system.
  images = [_create_thumbnail(frame, use_colormap=use_colormap) for frame in ex]

  if not images:
    return 'Video with 0 frames.'

  # Display the video HTML (either GIF of mp4 if ffmpeg is installed)
  try:
    utils.ffmpeg_run(['-version'])  # Check for ffmpeg installation.
  except FileNotFoundError:
    # print as `stderr` is displayed poorly on Colab
    print('FFMPEG not detected. Falling back on GIF.')
    return _get_repr_html_gif(images)
  else:
    return _get_repr_html_ffmpeg(images)
Exemple #3
0
    def _ffmpeg_decode(self, path_or_fobj):
        if isinstance(path_or_fobj, type_utils.PathLikeCls):
            ffmpeg_args = ['-i', os.fspath(path_or_fobj)]
            ffmpeg_stdin = None
        else:
            ffmpeg_args = ['-i', 'pipe:0']
            ffmpeg_stdin = path_or_fobj.read()
        ffmpeg_args += self._extra_ffmpeg_args

        with tempfile.TemporaryDirectory() as ffmpeg_dir:
            out_pattern = os.path.join(ffmpeg_dir,
                                       f'%010d.{self._encoding_format}')
            ffmpeg_args.append(out_pattern)
            utils.ffmpeg_run(ffmpeg_args, ffmpeg_stdin)
            frames = [  # Load all encoded images
                p.read_bytes()
                for p in sorted(utils.as_path(ffmpeg_dir).iterdir())
            ]
        return frames