#frame #gstreamer #image #iterator #uri #iterate

vid_frame_iter

a library to iterate over files, using gstreamer

1 unstable release

new 0.2.0 Dec 22, 2024

#227 in Video


Used in 3 crates (2 directly)

MIT/Apache

2.5MB
467 lines

A crate for reading video frames and processing them as images, using gstreamer as a backend.

To start reading frames, you create a VideoFrameIterBuilder with a URI to the location of the video. Then call spawn_gray of spawn_rgb to receive an iterator over video frames.

Has integration with the image crate for easy image processing (but also allows direct access to raw pixels if that's what you want)

The interface is small and minimal.

Examples

Iterate over all video frames, and print the total number of frames.

use vid_frame_iter::VideoFrameIterBuilder;
use glib::Error;

fn main() -> Result<(), glib::Error> {

      //Must call this first.
      vid_frame_iter::init_gstreamer();

      //(If you have a file on disk you have to convert it to a URI string first)

      // Create a VideoFrameIterBuilder. There are a few extra methods for
      // providing options, but for now we can just provide the URI.
      let builder = VideoFrameIterBuilder::from_uri(VIDEO_URI_HERE);
      let mut frames = builder.spawn_rgb()?;

      // Count the frames and print them!
      let total_frames = frames.count();
      println!("total frames: {total_frames}");

      Ok(())
}

Save one from per second to disk

use vid_frame_iter::VideoFrameIterBuilder;
use vid_frame_iter::ImageFns;
use glib::Error;

fn main() -> Result<(), glib::Error> {

      //Must call this first.
      vid_frame_iter::init_gstreamer();

      //(If you have a file on disk you have to convert it to a URI string first)

      let mut builder = VideoFrameIterBuilder::from_uri(VIDEO_URI_HERE);
      builder.frame_rate((1, 1));
      let mut frames = builder.spawn_rgb()?;

      //Gstreamer is internally discarding unwanted frames, so we just process every frame we receive.
      for (idx, frame) in frames.enumerate() {
          match frame {
              Err(e) => return Err(e),
              Ok(frame) => {
                  // We have to convert the frame to an [`image::ImageBuffer`] to be able to save it.
                  let frame_buf: image::RgbImage = frame.to_imagebuffer();
                  match frame_buf.save_with_format(format!("{idx}.bmp"), image::ImageFormat::Bmp) {
                      Ok(()) => (),
                      Err(_e) => () //handle image save error here
                  }
              }
          }
      }

      Ok(())
}

Error handling

Instead of defining its own error type this crate uses the libglib glib::Error type. You can handle errors by switching on the matches method from glib::Error.

use vid_frame_iter::VideoFrameIterBuilder;
use glib::Error;

fn main() -> Result<(), glib::Error> {
      vid_frame_iter::init_gstreamer();


      // A video file that doesn't exist...
      match VideoFrameIterBuilder::from_uri(BAD_VIDEO_URI_HERE).spawn_rgb() {
          Ok(frame_iterator) => (),//no error
          Err(e) => {

              // You need to write an if-elsif chain for all the errors you
              // want to handle.
              if e.matches(gstreamer::ResourceError::NotFound) {
                  println!("oh no! That file doesn't exist!");
              } else {
                  println!("whoops! This is a different error!")
              }
          }
      }
      Ok(())
}

Supported operating systems

Currently only tested on Ubuntu Linux 22.04. This crate should work in MacOS and windows but this has not been tested.

Installing

You should follow the detailed instructions written for gstreamer-rs here.

Dependencies

~13MB
~286K SLoC