Skip to main content

Color-correct video I/O — drop-in replacement for OpenCV VideoCapture/VideoWriter

Project description

framewright

A drop-in replacement for cv::VideoCapture and cv::VideoWriter that gives you frame-precise seeking, color space control, HDR10 writing, and lossless encoding.

What framewright adds over OpenCV

Reading

Feature OpenCV framewright
Frame-precise seeking Forward only, not frame-accurate Forward and backward, keyframe-accelerated
Color space control Opaque, implementation-defined Explicit BT.709/BT.601 selection, full/limited range override
Color metadata Not exposed getColorSpace(), getColorRange(), getPixelFormat(), getCodecID()
Zero-copy frames No readRef() avoids per-frame clone
Untagged content Implementation-defined matrix Sensible defaults (BT.709 for HD, BT.601 for SD)

Writing

Feature OpenCV framewright
HDR10 output Not supported HEVC 10-bit with BT.2020, PQ, mastering display metadata
Lossless encoding Not supported FFV1 (RGB, no YUV loss), H.264 qp=0 with 4:4:4
10-bit SDR Not supported HEVC Main10 with BT.709 for high-precision intermediates
Color space control Opaque Explicit BT.709/BT.2020, full/limited range
QuickTime compatibility Varies hvc1 codec tag for Safari/QuickTime HDR playback

Verified accuracy

Measured by reading BT.709-tagged lossless test videos with both libraries (OpenCV 4.13.0 and framewright on macOS). Both produce identical pixel values when metadata is present — framewright adds control, not a different answer:

cmake -B build -DFRAMEWRIGHT_BUILD_EXAMPLES=ON && cmake --build build
./build/compare_readers your_video.mp4

Migrating from OpenCV

framewright is a drop-in replacement. The API follows the same conventions (BGR cv::Mat frames):

Reading

// OpenCV
cv::VideoCapture cap("video.mp4");
cv::Mat frame;
cap.read(frame);

// framewright — same API, more capabilities
framewright::VideoReader reader;
reader.open("video.mp4");
cv::Mat frame;
reader.read(frame);

// seek backward (not possible with cv::VideoCapture)
reader.seek(0);
reader.read(frame);

// inspect color metadata
std::cout << "Color space: " << reader.getColorSpace() << std::endl;
std::cout << "Pixel format: " << av_get_pix_fmt_name(reader.getPixelFormat()) << std::endl;

Writing

// OpenCV
cv::VideoWriter w("out.mp4",
    cv::VideoWriter::fourcc('a','v','c','1'),
    30, cv::Size(1920, 1080));
w.write(frame);

// framewright — same pattern, more control
framewright::VideoWriter w;
w.open("out.mp4", AV_CODEC_ID_H264, 1920, 1080, {30, 1});
w.write(frame);
w.release();

Property mapping

OpenCV framewright
cap.get(CAP_PROP_FRAME_WIDTH) reader.getWidth()
cap.get(CAP_PROP_FRAME_HEIGHT) reader.getHeight()
cap.get(CAP_PROP_FPS) reader.getFPS()
cap.get(CAP_PROP_FRAME_COUNT) reader.getFrameCount()
cap.get(CAP_PROP_POS_FRAMES) reader.getCurrentFrameNumber()

Quick start

C++

#include <framewright/framewright.h>

// Read with correct BT.709 color conversion
framewright::VideoReader reader;
reader.open("input.mp4", /*force_bt709=*/true);

cv::Mat frame;
while (reader.read(frame)) {
    // frame is BGR cv::Mat with correct pixel values
}

// Write HDR10 HEVC
framewright::VideoWriterOptions opts;
opts.pix_fmt = AV_PIX_FMT_YUV420P10LE;
opts.is_10bit = true;

framewright::VideoWriter writer;
writer.open("output.mp4", AV_CODEC_ID_HEVC, 3840, 2160,
            {60000, 1001}, opts);  // 59.94 fps
writer.write(hdr_frame);  // CV_16UC3 BGR
writer.release();

Python

import framewright

reader = framewright.VideoReader()
reader.open("input.mp4", force_bt709=True)
for frame in reader:  # numpy (H, W, 3) uint8 BGR
    print(frame.shape, frame.dtype)

writer = framewright.VideoWriter()
writer.open("output.mp4", codec="h264", width=1920, height=1080, fps=30)
writer.write(frame)
writer.release()

Building

As a dependency (CMake FetchContent)

include(FetchContent)
FetchContent_Declare(
    framewright
    GIT_REPOSITORY https://github.com/kmatzen/framewright.git
    GIT_TAG main
)
FetchContent_MakeAvailable(framewright)

target_link_libraries(your_target PRIVATE framewright::framewright)

Standalone

mkdir build && cd build
cmake .. -DFRAMEWRIGHT_BUILD_EXAMPLES=ON
make -j$(nproc)

Python

pip install framewright

Requirements

  • C++17 compiler
  • OpenCV 4.0+
  • FFmpeg 4.2+ (libavformat, libavcodec, libswscale, libavutil)

Logging

By default, framewright only logs errors. To see informational output:

framewright::setLogLevel(framewright::LogLevel::Info);     // See everything
framewright::setLogLevel(framewright::LogLevel::Error);    // Errors only (default)
framewright::setLogLevel(framewright::LogLevel::Quiet);    // Silence all output

API

framewright::VideoReader

Method Description
open(filename, force_bt709, force_full_range) Open a video file with optional color space overrides
read(frame) Read the next frame as BGR cv::Mat (cloned, always safe)
readRef(frame) Read the next frame without copying (valid until next read)
seek(frame_number) Seek to a frame (forward and backward)
getPixelFormat(), getCodecID() Source format info
getColorSpace(), getColorRange() Color metadata
getFPS(), getWidth(), getHeight() Video properties

framewright::VideoWriter

Method Description
open(filename, codec_id, w, h, fps, opts) Open output with full codec control
write(frame) Write a BGR frame (CV_8UC3 or CV_16UC3)
setHDR10Metadata(metadata) Set mastering display / content light level
release() Flush and finalize the file

framewright::VideoWriterOptions

Field Default Description
bitrate 25000000 Target bitrate in bits/sec
pix_fmt YUV420P Output pixel format
is_10bit false HDR10 mode (BT.2020 + PQ)
full_range false Full range (0-255) vs limited (16-235)
use_444 false 4:4:4 chroma (no subsampling)
lossless false Mathematically lossless encoding

Supported codecs: H.264, H.265/HEVC (8-bit and 10-bit), FFV1 (lossless RGB).

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

framewright-0.1.0.tar.gz (31.8 kB view details)

Uploaded Source

File details

Details for the file framewright-0.1.0.tar.gz.

File metadata

  • Download URL: framewright-0.1.0.tar.gz
  • Upload date:
  • Size: 31.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for framewright-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a6d73ca2e55797bf5c580eba693cf8a2a4d50a70c3f386896e8c309de2aa8bbf
MD5 cd4a405d3ee6e64b674a85dbbfe57706
BLAKE2b-256 2a81386d1fe1bf4dfa7cfb70f25c61d67b5425f1444a23333d55641d699128e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for framewright-0.1.0.tar.gz:

Publisher: release.yml on kmatzen/framewright

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page