humble-video-demos/src/main/java/io/humble/video/demos/RecordAndEncodeVideo.java
private static void recordScreen(String filename, String formatname,
      String codecname, int duration, int snapsPerSecond) throws AWTException, InterruptedException, IOException {
    /**
     * Set up the AWT infrastructure to take screenshots of the desktop.
     */
    final Robot robot = new Robot();
    final Toolkit toolkit = Toolkit.getDefaultToolkit();
    final Rectangle screenbounds = new Rectangle(toolkit.getScreenSize());

    final Rational framerate = Rational.make(1, snapsPerSecond);
    
    /** First we create a muxer using the passed in filename and formatname if given. */
    final Muxer muxer = Muxer.make(filename, null, formatname);
    
    /** Now, we need to decide what type of codec to use to encode video. Muxers
     * have limited sets of codecs they can use. We're going to pick the first one that
     * works, or if the user supplied a codec name, we're going to force-fit that
     * in instead.
     */
    final MuxerFormat format = muxer.getFormat();
    final Codec codec;
    if (codecname != null) {
      codec = Codec.findEncodingCodecByName(codecname);
    } else {
      codec = Codec.findEncodingCodec(format.getDefaultVideoCodecId());
    }
    
    /**
     * Now that we know what codec, we need to create an encoder
     */
    Encoder encoder = Encoder.make(codec);
    
    /**
     * Video encoders need to know at a minimum:
     *   width
     *   height
     *   pixel format
     * Some also need to know frame-rate (older codecs that had a fixed rate at which video files could
     * be written needed this). There are many other options you can set on an encoder, but we're
     * going to keep it simpler here.
     */
    encoder.setWidth(screenbounds.width);
    encoder.setHeight(screenbounds.height);
    // We are going to use 420P as the format because that's what most video formats these days use
    final PixelFormat.Type pixelformat = PixelFormat.Type.PIX_FMT_YUV420P;
    encoder.setPixelFormat(pixelformat);
    encoder.setTimeBase(framerate);
    
    /** An annoynace of some formats is that they need global (rather than per-stream) headers,
     * and in that case you have to tell the encoder. And since Encoders are decoupled from
     * Muxers, there is no easy way to know this beyond 
     */
    if (format.getFlag(MuxerFormat.Flag.GLOBAL_HEADER))
      encoder.setFlag(Encoder.Flag.FLAG_GLOBAL_HEADER, true);

    /** Open the encoder. */
    encoder.open(null, null);
    
    
    /** Add this stream to the muxer. */
    muxer.addNewStream(encoder);
    
    /** And open the muxer for business. */
    muxer.open(null, null);
    
    /** Next, we need to make sure we have the right MediaPicture format objects
     * to encode data with. Java (and most on-screen graphics programs) use some
     * variant of Red-Green-Blue image encoding (a.k.a. RGB or BGR). Most video
     * codecs use some variant of YCrCb formatting. So we're going to have to
     * convert. To do that, we'll introduce a MediaPictureConverter object later. object.
     */
    MediaPictureConverter converter = null;
    final MediaPicture picture = MediaPicture.make(
        encoder.getWidth(),
        encoder.getHeight(),
        pixelformat);
    picture.setTimeBase(framerate);
    
    /** Now begin our main loop of taking screen snaps.
     * We're going to encode and then write out any resulting packets. */
    final MediaPacket packet = MediaPacket.make();
    for (int i = 0; i < duration / framerate.getDouble(); i++) {
      /** Make the screen capture && convert image to TYPE_3BYTE_BGR */
      final BufferedImage screen = convertToType(robot.createScreenCapture(screenbounds), BufferedImage.TYPE_3BYTE_BGR);
      
      /** This is LIKELY not in YUV420P format, so we're going to convert it using some handy utilities. */
      if (converter == null)
        converter = MediaPictureConverterFactory.createConverter(screen, picture);
      converter.toPicture(picture, screen, i);
      
      do {
        encoder.encode(packet, picture);
        if (packet.isComplete())
          muxer.write(packet, false);
      } while (packet.isComplete());
      
      /** now we'll sleep until it's time to take the next snapshot. */
      Thread.sleep((long) (1000 * framerate.getDouble()));
    }
    
    /** Encoders, like decoders, sometimes cache pictures so it can do the right key-frame optimizations.
     * So, they need to be flushed as well. As with the decoders, the convention is to pass in a null
     * input until the output is not complete.
     */
    do {
      encoder.encode(packet, null);
      if (packet.isComplete())
        muxer.write(packet,  false);
    } while (packet.isComplete());
    
    /** Finally, let's clean up after ourselves. */
    muxer.close();
  }
private static void recordScreen(String filename, String formatname,
      String codecname, int duration, int snapsPerSecond) throws AWTException, InterruptedException, IOException {
    /**
     * Set up the AWT infrastructure to take screenshots of the desktop.
     */
    final Robot robot = new Robot();
    final Toolkit toolkit = Toolkit.getDefaultToolkit();
    final Rectangle screenbounds = new Rectangle(toolkit.getScreenSize());

    final Rational framerate = Rational.make(1, snapsPerSecond);
    
    /** First we create a muxer using the passed in filename and formatname if given. */
    final Muxer muxer = Muxer.make(filename, null, formatname);
    
    /** Now, we need to decide what type of codec to use to encode video. Muxers
     * have limited sets of codecs they can use. We're going to pick the first one that
     * works, or if the user supplied a codec name, we're going to force-fit that
     * in instead.
     */
    final MuxerFormat format = muxer.getFormat();
    final Codec codec;
    if (codecname != null) {
      codec = Codec.findEncodingCodecByName(codecname);
    } else {
      codec = Codec.findEncodingCodec(format.getDefaultVideoCodecId());
    }
    
    /**
     * Now that we know what codec, we need to create an encoder
     */
    Encoder encoder = Encoder.make(codec);
    
    /**
     * Video encoders need to know at a minimum:
     *   width
     *   height
     *   pixel format
     * Some also need to know frame-rate (older codecs that had a fixed rate at which video files could
     * be written needed this). There are many other options you can set on an encoder, but we're
     * going to keep it simpler here.
     */
    encoder.setWidth(screenbounds.width);
    encoder.setHeight(screenbounds.height);
    // We are going to use 420P as the format because that's what most video formats these days use
    final PixelFormat.Type pixelformat = PixelFormat.Type.PIX_FMT_YUV420P;
    encoder.setPixelFormat(pixelformat);
    encoder.setTimeBase(framerate);
    
    /** An annoynace of some formats is that they need global (rather than per-stream) headers,
     * and in that case you have to tell the encoder. And since Encoders are decoupled from
     * Muxers, there is no easy way to know this beyond 
     */
    if (format.getFlag(MuxerFormat.Flag.GLOBAL_HEADER))
      encoder.setFlag(Encoder.Flag.FLAG_GLOBAL_HEADER, true);

    /** Open the encoder. */
    encoder.open(null, null);
    
    
    /** Add this stream to the muxer. */
    muxer.addNewStream(encoder);
    
    /** And open the muxer for business. */
    muxer.open(null, null);
    
    /** Next, we need to make sure we have the right MediaPicture format objects
     * to encode data with. Java (and most on-screen graphics programs) use some
     * variant of Red-Green-Blue image encoding (a.k.a. RGB or BGR). Most video
     * codecs use some variant of YCrCb formatting. So we're going to have to
     * convert. To do that, we'll introduce a MediaPictureConverter object later. object.
     */
    MediaPictureConverter converter = null;
    final MediaPicture picture = MediaPicture.make(
        encoder.getWidth(),
        encoder.getHeight(),
        pixelformat);
    picture.setTimeBase(framerate);
    
    /** Now begin our main loop of taking screen snaps.
     * We're going to encode and then write out any resulting packets. */
    final MediaPacket packet = MediaPacket.make();
    for (int i = 0; i < duration / framerate.getDouble(); i++) {
      /** Make the screen capture && convert image to TYPE_3BYTE_BGR */
      final BufferedImage screen = convertToType(robot.createScreenCapture(screenbounds), BufferedImage.TYPE_3BYTE_BGR);
      
      /** This is LIKELY not in YUV420P format, so we're going to convert it using some handy utilities. */
      if (converter == null)
        converter = MediaPictureConverterFactory.createConverter(screen, picture);
      converter.toPicture(picture, screen, i);
      
      do {
        encoder.encode(packet, picture);
        if (packet.isComplete())
          muxer.write(packet, false);
      } while (packet.isComplete());
      
      /** now we'll sleep until it's time to take the next snapshot. */
      Thread.sleep((long) (1000 * framerate.getDouble()));
    }
    
    /** Encoders, like decoders, sometimes cache pictures so it can do the right key-frame optimizations.
     * So, they need to be flushed as well. As with the decoders, the convention is to pass in a null
     * input until the output is not complete.
     */
    do {
      encoder.encode(packet, null);
      if (packet.isComplete())
        muxer.write(packet,  false);
    } while (packet.isComplete());
    
    /** Finally, let's clean up after ourselves. */
    muxer.close();
  }
Records the screen