# `pyffstream`

A Python library to ease processing of video frames.

`pyffstream` is mostly a wrapper around external [FFmpeg][] processes (via
[`ffmpeg-python`][]) intended to be used with [OpenCV][].

[FFmpeg]: https://ffmpeg.org
[`ffmpeg-python`]: https://github.com/kkroening/ffmpeg-python
[OpenCV]: https://opencv.org

## Usage

`pyffstream` provides your application with a command line interface (CLI) and
handles reading and writing video files (with the original audio intact),
filtering the frames through a callback that you define. The API consists
mainly of the single function

```python
run(description, process, init=None, args_pre=None, args_post=None)
```

that takes the application description to present in the CLI and some
callbacks, all but one being optional:

-   `process(args, state, frame, frame_num)`:

    Takes:

    -   `args`: [`argparse.Namespace`][] containing parsed command line
        arguments.
    -   `state`: arbitrary object returned by `init` (see below).
    -   `frame`: [`numpy.array`][] with shape
        `(args.working_width, args.working_height, 3)` containing RGB data to
        be processed.
    -   `frame_num`: integer in the range [`args.frame_start`,
        `args.frame_end`) representing the number of the current frame.

    Returns:

    -   `output_frame`: [`numpy.array`][] with shape
        `(args.output_width, args.output_height, 3)` containing RGB output.
    -   `debug_frame`: [`numpy.array`][] with shape
        `(args.working_width, args.working_height, 3)` containing RGB debug
        output.

-   `init(args)`:

    Takes:

    -   `args`: [`argparse.Namespace`][] containing parsed command line
        arguments.

    Returns:

    -   `state`: arbitrary object passed to `process` (see above).

-   `args_pre(parser)`, `args_post(parser)`:

    Takes:

    -   `args`: [`argparse.ArgumentParser`][] before (for `args_pre`) or after
        (for `args_post`) being filled with `pyffstream` arguments.

    Returns nothing.

A number of hepler functions are also supplied:

-   `resize(image, width, height, resample)`: wrapper around
    [`PIL.Image.resize`][].
-   `text(image, text, x, y, thickness, font=cv2.FONT_HERSHEY_SIMPLEX)`:
    wrapper around [`cv2.putText`][] that automatically adjusts text placement
    and scaling.
-   `fix_rect(args, x, y, w, h)`: forces a rectangle to aspect ratio
    `args.output_aspect` and to be inside `(0, 0, args.working_width,
    args.working_height)`.

[`argparse.Namespace`]: https://docs.python.org/3/library/argparse.html#argparse.Namespace
[`argparse.ArgumentParser`]: https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser
[`numpy.array`]: https://numpy.org/doc/stable/reference/generated/numpy.array.html
[`PIL.Image.resize`]: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize
[`cv2.putText`]: https://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#ga5126f47f883d730f633d74f07456c576

### Examples

Projects using `pyffstream`:

-   [`autozoom`][]: Automatically zoom in on video content of interest.

[`autozoom`]: https://git.rcrnstn.net/rcrnstn/autozoom

## Installation

### With `pip`

```sh
python3 -m pip install git+https://git.rcrnstn.net/rcrnstn/pyffstream
```

### In `setuptools` `setup.py`

```python
from setuptools import setup

setup(
    # ...
    install_requires=[
        'pyffstream @ git+https://git.rcrnstn.net/rcrnstn/pyffstream',
    ],
    # ...
)
```

## License

Licensed under the [ISC license][], see the [`LICENSE`](LICENSE) file.

[ISC license]: https://en.wikipedia.org/wiki/ISC_license
