module documentation

Video utilities.

Copyright 2017-2025, Voxel51, Inc.

Function concat_videos Concatenates the given list of videos, in order, into a single video.
Function exact_frame_count Returns the exact number of frames in the video.
Function extract_clip Extracts the specified clip from the video.
Function reencode_video Re-encodes the video using the H.264 codec.
Function reencode_videos Re-encodes the videos in the sample collection as H.264 MP4s that can be visualized in the FiftyOne App.
Function sample_frames_uniform Returns a list of frame numbers sampled uniformly according to the provided parameters.
Function sample_video Samples the video into a directory of per-frame images according to the provided parameters using ffmpeg.
Function sample_videos Samples the videos in the sample collection into directories of per-frame images according to the provided parameters using ffmpeg.
Function transform_video Transforms the video according to the provided parameters using ffmpeg.
Function transform_videos Transforms the videos in the sample collection according to the provided parameters using ffmpeg.
Variable logger Undocumented
Function _get_outpath Undocumented
Function _parse_parameters Undocumented
Function _transform_video Undocumented
Function _transform_videos Undocumented
def concat_videos(input_paths, output_path, verbose=False): (source)

Concatenates the given list of videos, in order, into a single video.

Parameters
input_pathsa list of video paths
output_paththe path to write the output video
verbose:Falsewhether to log the ffmpeg command that is executed
def exact_frame_count(input_path): (source)

Returns the exact number of frames in the video.

Warning

This method uses the -count_frames argument of ffprobe, which requires decoding the video and can be very slow.

Parameters
input_paththe path to the video
Returns
the number of frames in the video
def extract_clip(video_path, output_path, support=None, timestamps=None, metadata=None, fast=False): (source)

Extracts the specified clip from the video.

Provide either support or timestamps to this method.

When fast=False, the following ffmpeg command is used:

# Slower, more accurate option
ffmpeg -ss <start_time> -i <video_path> -t <duration> <output_path>

When fast is True, the following two-step ffmpeg process is used:

# Faster, less accurate option
ffmpeg -ss <start_time> -i <video_path> -t <duration> -c copy <tmp_path>
ffmpeg -i <tmp_path> <output_path>
Parameters
video_paththe path to the video
output_paththe path to write the extracted clip
support:Nonethe [first, last] frame number range to clip
timestamps:Nonethe [start, stop] timestamps to clip, in seconds
metadata:Nonethe fiftyone.core.metadata.VideoMetadata for the video
fast:Falsewhether to use a faster-but-potentially-less-accurate strategy to extract the clip
def reencode_video(input_path, output_path, verbose=False, **kwargs): (source)

Re-encodes the video using the H.264 codec.

By default, the re-encoding is performed via the following ffmpeg command:

ffmpeg \
    -loglevel error -vsync 0 -i $INPUT_PATH \
    -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p -vsync 0 -an \
    $OUTPUT_PATH

You can configure parameters of the re-encoding such as codec and compression by passing keyword arguments for eta.core.video.FFmpeg(**kwargs) to this function.

Parameters
input_paththe path to the input video
output_paththe path to write the output video
verbose:Falsewhether to log the ffmpeg command that is executed
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)
def reencode_videos(sample_collection, force_reencode=True, media_field='filepath', output_field=None, output_dir=None, rel_dir=None, update_filepaths=True, delete_originals=False, skip_failures=False, verbose=False, progress=None, **kwargs): (source)

Re-encodes the videos in the sample collection as H.264 MP4s that can be visualized in the FiftyOne App.

If no output_dir is specified and delete_originals is False, then if a transformation would result in overwriting an existing file with the same filename, the original file is renamed to <name>-original.<ext>.

By default, the re-encoding is performed via the following ffmpeg command:

ffmpeg \
    -loglevel error -vsync 0 -i $INPUT_PATH \
    -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p -vsync 0 -an \
    $OUTPUT_PATH

You can configure parameters of the re-encoding such as codec and compression by passing keyword arguments for eta.core.video.FFmpeg(**kwargs) to this function.

Note

This method will not update the metadata field of the collection after transforming. You can repopulate the metadata field if needed by calling:

sample_collection.compute_metadata(overwrite=True)
Parameters
sample_collectiona fiftyone.core.collections.SampleCollection
force_reencode:Truewhether to re-encode videos that are already MP4s
media_field:"filepath"the input field containing the video paths to transform
output_field:Nonean optional field in which to store the paths to the transformed videos. By default, media_field is updated in-place
output_dir:Nonean optional output directory in which to write the transformed videos. If none is provided, the videos are updated in-place
rel_dir:Nonean optional relative directory to strip from each input filepath to generate a unique identifier that is joined with output_dir to generate an output path for each video. This argument allows for populating nested subdirectories in output_dir that match the shape of the input paths
update_filepaths:Truewhether to store the output paths on the sample collection
delete_originals:Falsewhether to delete the original videos after re-encoding
skip_failures:Falsewhether to gracefully continue without raising an error if a video cannot be re-encoded
verbose:Falsewhether to log the ffmpeg commands that are executed
progress:Nonewhether to render a progress bar (True/False), use the default value fiftyone.config.show_progress_bars (None), or a progress callback function to invoke instead
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)
def sample_frames_uniform(frame_rate, total_frame_count=None, support=None, fps=None, max_fps=None, always_sample_last=False): (source)

Returns a list of frame numbers sampled uniformly according to the provided parameters.

Parameters
frame_ratethe video frame rate
total_frame_count:Nonethe total number of frames in the video
support:Nonea [first, last] frame range from which to sample
fps:Nonea frame rate at which to sample frames
max_fps:Nonea maximum frame rate at which to sample frames
always_sample_last:Falsewhether to always sample the last frame
Returns
a list of frame numbers, or None if all frames should be sampled
def sample_video(input_path, output_patt, frames=None, fps=None, max_fps=None, size=None, min_size=None, max_size=None, original_frame_numbers=True, verbose=False, **kwargs): (source)

Samples the video into a directory of per-frame images according to the provided parameters using ffmpeg.

Parameters
input_paththe path to the input video
output_patta pattern like /path/to/images/%%06d.jpg specifying the filename/format to write the sampled frames
frames:Nonean iterable of frame numbers to sample. If provided, fps and max_fps are ignored
fps:Nonean optional frame rate at which to sample the frames
max_fps:Nonean optional maximum frame rate. Videos with frame rate exceeding this value are downsampled
size:Nonean optional (width, height) for each frame. One dimension can be -1, in which case the aspect ratio is preserved
min_size:Nonean optional minimum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
max_size:Nonean optional maximum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
original_frame_numbers:Truewhether to use the original frame numbers when writing the output frames (True) or to instead reindex the frames as 1, 2, ... (False)
verbose:Falsewhether to log the ffmpeg command that is executed
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)
def sample_videos(sample_collection, frames_patt=None, frames=None, fps=None, max_fps=None, size=None, min_size=None, max_size=None, original_frame_numbers=True, force_sample=False, media_field='filepath', output_field=None, output_dir=None, rel_dir=None, save_filepaths=False, delete_originals=False, skip_failures=False, verbose=False, progress=None, **kwargs): (source)

Samples the videos in the sample collection into directories of per-frame images according to the provided parameters using ffmpeg.

By default, each folder of images is written using the same basename as the input video. For example, if frames_patt = "%%06d.jpg", then videos with the following paths:

/path/to/video1.mp4
/path/to/video2.mp4
...

would be sampled as follows:

/path/to/video1/
    000001.jpg
    000002.jpg
    ...
/path/to/video2/
    000001.jpg
    000002.jpg
    ...

However, you can use the optional output_dir and rel_dir parameters to customize the location and shape of the sampled frame folders. For example, if output_dir = "/tmp" and rel_dir = "/path/to", then videos with the following paths:

/path/to/folderA/video1.mp4
/path/to/folderA/video2.mp4
/path/to/folderB/video3.mp4
...

would be sampled as follows:

/tmp/folderA/
    video1/
        000001.jpg
        000002.jpg
        ...
    video2/
        000001.jpg
        000002.jpg
        ...
/tmp/folderB/
    video3/
        000001.jpg
        000002.jpg
        ...
Parameters
sample_collectiona fiftyone.core.collections.SampleCollection
frames_patt:Nonea pattern specifying the filename/format to use to store the sampled frames, e.g., "%%06d.jpg". The default value is fiftyone.config.default_sequence_idx + fiftyone.config.default_image_ext
frames:Nonean optional list of lists defining specific frames to sample from each video. Entries can also be None, in which case all frames will be sampled. If provided, fps and max_fps are ignored
fps:Nonean optional frame rate at which to sample frames
max_fps:Nonean optional maximum frame rate. Videos with frame rate exceeding this value are downsampled
size:Nonean optional (width, height) for each frame. One dimension can be -1, in which case the aspect ratio is preserved
min_size:Nonean optional minimum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
max_size:Nonean optional maximum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
original_frame_numbers:Truewhether to use the original frame numbers when writing the output frames (True) or to instead reindex the frames as 1, 2, ... (False)
force_sample:Falsewhether to resample videos whose sampled frames already exist
media_field:"filepath"the input field containing the video paths to sample
output_field:Nonean optional frame field in which to store the paths to the sampled frames. By default, media_field is used
output_dir:Nonean optional output directory in which to write the sampled frames. By default, the frames are written in folders with the same basename of each video
rel_dir:Nonea relative directory to remove from the filepath of each video, if possible. The path is converted to an absolute path (if necessary) via fiftyone.core.storage.normalize_path. This argument can be used in conjunction with output_dir to cause the sampled frames to be written in a nested directory structure within output_dir matching the shape of the input video's folder structure
save_filepaths:Falsewhether to save the sampled frame paths in the output_field field of each frame of the input collection
delete_originals:Falsewhether to delete the original videos after sampling
skip_failures:Falsewhether to gracefully continue without raising an error if a video cannot be sampled
verbose:Falsewhether to log the ffmpeg commands that are executed
progress:Nonewhether to render a progress bar (True/False), use the default value fiftyone.config.show_progress_bars (None), or a progress callback function to invoke instead
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)
def transform_video(input_path, output_path, fps=None, min_fps=None, max_fps=None, size=None, min_size=None, max_size=None, reencode=False, verbose=False, **kwargs): (source)

Transforms the video according to the provided parameters using ffmpeg.

In addition to the size and frame rate parameters, if reencode == True, the following basic ffmpeg command structure is used to re-encode the video as an H.264 MP4:

ffmpeg \
    -loglevel error -vsync 0 -i $INPUT_PATH \
    -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p -vsync 0 -an \
    $OUTPUT_PATH
Parameters
input_paththe path to the input video
output_paththe path to write the output video
fps:Nonean optional frame rate at which to resample the videos
min_fps:Nonean optional minimum frame rate. Videos with frame rate below this value are upsampled
max_fps:Nonean optional maximum frame rate. Videos with frame rate exceeding this value are downsampled
size:Nonean optional (width, height) for each frame. One dimension can be -1, in which case the aspect ratio is preserved
min_size:Nonean optional minimum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
max_size:Nonean optional maximum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
reencode:Falsewhether to reencode the video (see main description)
verbose:Falsewhether to log the ffmpeg command that is executed
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)
def transform_videos(sample_collection, fps=None, min_fps=None, max_fps=None, size=None, min_size=None, max_size=None, reencode=False, force_reencode=False, media_field='filepath', output_field=None, output_dir=None, rel_dir=None, update_filepaths=True, delete_originals=False, skip_failures=False, verbose=False, progress=None, **kwargs): (source)

Transforms the videos in the sample collection according to the provided parameters using ffmpeg.

If no output_dir is specified and delete_originals is False, then if a transformation would result in overwriting an existing file with the same filename, the original file is renamed to <name>-original.<ext>.

In addition to the size and frame rate parameters, if reencode == True, the following basic ffmpeg command structure is used to re-encode the videos as H.264 MP4s:

ffmpeg \
    -loglevel error -vsync 0 -i $INPUT_PATH \
    -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p -vsync 0 -an \
    $OUTPUT_PATH

Note

This method will not update the metadata field of the collection after transforming. You can repopulate the metadata field if needed by calling:

sample_collection.compute_metadata(overwrite=True)
Parameters
sample_collectiona fiftyone.core.collections.SampleCollection
fps:Nonean optional frame rate at which to resample the videos
min_fps:Nonean optional minimum frame rate. Videos with frame rate below this value are upsampled
max_fps:Nonean optional maximum frame rate. Videos with frame rate exceeding this value are downsampled
size:Nonean optional (width, height) for each frame. One dimension can be -1, in which case the aspect ratio is preserved
min_size:Nonean optional minimum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
max_size:Nonean optional maximum (width, height) for each frame. A dimension can be -1 if no constraint should be applied. The frames are resized (aspect-preserving) if necessary to meet this constraint
reencode:Falsewhether to re-encode the videos as H.264 MP4s
force_reencode:Falsewhether to re-encode videos whose parameters already satisfy the specified values
media_field:"filepath"the input field containing the video paths to transform
output_field:Nonean optional field in which to store the paths to the transformed videos. By default, media_field is updated in-place
output_dir:Nonean optional output directory in which to write the transformed videos. If none is provided, the videos are updated in-place
rel_dir:Nonean optional relative directory to strip from each input filepath to generate a unique identifier that is joined with output_dir to generate an output path for each video. This argument allows for populating nested subdirectories in output_dir that match the shape of the input paths
update_filepaths:Truewhether to store the output paths on the sample collection
delete_originals:Falsewhether to delete the original videos after re-encoding
skip_failures:Falsewhether to gracefully continue without raising an error if a video cannot be transformed
verbose:Falsewhether to log the ffmpeg commands that are executed
progress:Nonewhether to render a progress bar (True/False), use the default value fiftyone.config.show_progress_bars (None), or a progress callback function to invoke instead
**kwargskeyword arguments for eta.core.video.FFmpeg(**kwargs)

Undocumented

def _get_outpath(inpath, output_dir=None, rel_dir=None): (source)

Undocumented

def _parse_parameters(video_path, fps, min_fps, max_fps, size, min_size, max_size, sample_frames, original_frame_numbers): (source)

Undocumented

def _transform_video(inpath, outpath, frames=None, fps=None, min_fps=None, max_fps=None, size=None, min_size=None, max_size=None, sample_frames=False, original_frame_numbers=True, reencode=False, force_reencode=False, delete_original=False, skip_failures=False, verbose=False, **kwargs): (source)

Undocumented

def _transform_videos(sample_collection, frames=None, fps=None, min_fps=None, max_fps=None, size=None, min_size=None, max_size=None, sample_frames=False, frames_patt=None, original_frame_numbers=True, reencode=False, force_reencode=False, media_field='filepath', output_field=None, output_dir=None, rel_dir=None, save_filepaths=False, update_filepaths=True, delete_originals=False, skip_failures=False, verbose=False, progress=None, **kwargs): (source)

Undocumented