Skip to content

FPS gets rounded to two decimals after the point #116

@isarandi

Description

@isarandi

https://github.com/imageio/imageio-ffmpeg/blob/0585a7b5fa0ea0628712b319ff898ad6f537b03e/imageio_ffmpeg/_io.py#L528C4-L528C65

Here, the fps gets rounded, which makes it hard to transform an existing video's frames while keeping the source fps in the resulting video (so that it e.g. doesn't lose sync when you add audio to it or subtitles or anything else).

Even the metadata['fps'] is rounded when checking the fps of an existing video since it gets parsed from ffmpeg output header.

My workaround for getting the fps is:

def get_fps(video_path):
    command = [
        'ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=r_frame_rate',
        '-of', 'json', video_path]
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT, universal_newlines=True)
        frame_rate = json.loads(output)['streams'][0]['r_frame_rate']
        numerator, denominator = map(int, frame_rate.split('/'))
        return numerator / denominator
    except subprocess.CalledProcessError as e:
        raise ValueError(f"Failed to retrieve FPS: {e.output}")
    except KeyError as e:
        raise ValueError(f"Key error: {e}")

And the workaround for specifying the fps is:

imageio.get_writer(path, input_params=['-r', str(fps)])

or

from fractions import Fraction
fps_frac = Fraction(fps).limit_denominator()
imageio.get_writer(path, input_params=['-r', str(fps_frac)])

But it would be best if imageio handled exact frame rates out of the box without rounding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions