Optical effects library — lens flares, camera optics, atmospheric/diffusion, stylized optics
Project description
optic-fx
Optical effects for video — lens flares, camera optics, atmospheric layers, and stylized optics. 86 named effects. Frame-accurate. Compositable.
Install
pip install optic-fx
Requires ffmpeg >= 6.0 on PATH.
Extras:
| Extra | What it adds | Approx size |
|---|---|---|
pip install optic-fx |
base: flares, optics, atmospherics, stylized | ~80 MB |
pip install optic-fx[advanced] |
scikit-image — higher quality atmospheric noise | ~120 MB |
pip install optic-fx[overlay] |
web-overlay + Playwright Chromium — SVG-rendered flares | ~230 MB |
pip install optic-fx[all] |
overlay + advanced | ~270 MB |
The [overlay] extra installs Playwright Chromium. Most pipelines do not need it — the PIL fallback is used automatically when web-overlay is absent.
5-minute tour
Apply a named effect to a clip:
from optic_fx import apply_optic
apply_optic(
video="raw.mp4",
effect="anamorphic_lens_flare_gold",
output="flared.mp4",
)
Add a dense fog layer with animated drift:
from optic_fx import render_atmosphere
render_atmosphere(
video="raw.mp4",
effect="fog_overlay_dense",
output="foggy.mp4",
density=0.8,
movement_speed=0.3,
)
Render a flare as a standalone overlay for compositing in another tool:
from optic_fx import render_flare
render_flare(
effect="anamorphic_lens_flare_subtle",
width=1920,
height=1080,
position=(0.7, 0.3), # normalized (x, y) of the flare origin
duration=2.0,
output="flare_overlay.webm",
)
The 86 effects
lens_flares_and_glow (25)
| Slug | Display name |
|---|---|
anamorphic_lens_flare_subtle |
Anamorphic Lens Flare (Subtle) |
anamorphic_lens_flare_intense |
Anamorphic Lens Flare (Intense) |
anamorphic_lens_flare_gold |
Anamorphic Lens Flare (Gold) |
sci_fi_aggressive_flare |
Sci-Fi Aggressive Flare |
sun_glint_small |
Sun Glint (Small) |
sun_glint_ribbon |
Sun Glint (Ribbon) |
lens_orb_flare_single |
Lens Orb Flare (Single) |
lens_orb_flare_chain |
Lens Orb Flare (Chain) |
rainbow_prism_flare |
Rainbow Prism Flare |
glow_bloom_soft |
Glow Bloom (Soft) |
glow_bloom_intense |
Glow Bloom (Intense) |
soft_diffusion_pro_mist |
Soft Diffusion (Pro Mist) |
soft_diffusion_white_diffusion |
Soft Diffusion (White Diffusion) |
halation |
Halation |
halation_warm |
Halation (Warm) |
neon_glow_magenta |
Neon Glow (Magenta) |
neon_glow_cyan |
Neon Glow (Cyan) |
neon_glow_warm |
Neon Glow (Warm) |
starburst_filter_4_point |
Starburst Filter (4 Point) |
starburst_filter_8_point |
Starburst Filter (8 Point) |
dirty_lens |
Dirty Lens |
bokeh_bloom_circular |
Bokeh Bloom (Circular) |
bokeh_bloom_hexagonal |
Bokeh Bloom (Hexagonal) |
bokeh_bloom_anamorphic_oval |
Bokeh Bloom (Anamorphic Oval) |
lens_breathing |
Lens Breathing |
camera_optics (18)
| Slug | Display name |
|---|---|
barrel_distortion_gentle |
Barrel Distortion (Gentle) |
barrel_distortion_strong |
Barrel Distortion (Strong) |
pincushion_distortion_gentle |
Pincushion Distortion (Gentle) |
pincushion_distortion_strong |
Pincushion Distortion (Strong) |
vignette_subtle |
Vignette (Subtle) |
vignette_heavy |
Vignette (Heavy) |
vignette_rectangular |
Vignette (Rectangular) |
lens_warp_organic |
Lens Warp (Organic) |
lens_warp_geometric |
Lens Warp (Geometric) |
soft_corners |
Soft Corners |
microscope_lens |
Microscope Lens |
telephoto_compression_moderate |
Telephoto Compression (Moderate) |
telephoto_compression_extreme |
Telephoto Compression (Extreme) |
underwater_lens_ripple |
Underwater Lens (Ripple) |
underwater_lens_deep |
Underwater Lens (Deep) |
prism_refraction_horizontal |
Prism Refraction (Horizontal) |
prism_refraction_radial |
Prism Refraction (Radial) |
prism_refraction_stacked |
Prism Refraction (Stacked) |
atmospheric_and_diffusion (25)
| Slug | Display name |
|---|---|
cinematic_haze_morning |
Cinematic Haze (Morning) |
cinematic_haze_evening |
Cinematic Haze (Evening) |
fog_overlay_light |
Fog Overlay (Light) |
fog_overlay_dense |
Fog Overlay (Dense) |
fog_overlay_ground_only |
Fog Overlay (Ground Only) |
smoke_diffusion_stage |
Smoke Diffusion (Stage) |
smoke_diffusion_cinematic |
Smoke Diffusion (Cinematic) |
heat_haze_desert |
Heat Haze (Desert) |
heat_haze_urban |
Heat Haze (Urban) |
rain_streak_refraction_light |
Rain Streak Refraction (Light) |
rain_streak_refraction_heavy |
Rain Streak Refraction (Heavy) |
snow_glow |
Snow Glow |
dust_storm_dry |
Dust Storm (Dry) |
dust_storm_apocalyptic |
Dust Storm (Apocalyptic) |
dream_fog |
Dream Fog |
moonlight_mist |
Moonlight Mist |
fire_smoke_warm |
Fire Smoke (Warm) |
fire_smoke_drifting |
Fire Smoke (Drifting) |
volumetric_atmosphere_forest |
Volumetric Atmosphere (Forest) |
volumetric_atmosphere_cathedral |
Volumetric Atmosphere (Cathedral) |
stage_spotlight_haze_concert |
Stage Spotlight Haze (Concert) |
stage_spotlight_haze_theatrical |
Stage Spotlight Haze (Theatrical) |
window_diffusion |
Window Diffusion |
clouded_lens_light |
Clouded Lens (Light) |
clouded_lens_heavy |
Clouded Lens (Heavy) |
stylized_optical (18)
| Slug | Display name |
|---|---|
kaleidoscope_prism_triangular |
Kaleidoscope Prism (Triangular) |
kaleidoscope_prism_hexagonal |
Kaleidoscope Prism (Hexagonal) |
glass_refraction |
Glass Refraction |
crystal_refraction |
Crystal Refraction |
mirror_hall |
Mirror Hall |
oil_smear_lens |
Oil Smear Lens |
dream_prism |
Dream Prism |
heatwave_blur |
Heatwave Blur |
tunnel_vision_subtle |
Tunnel Vision (Subtle) |
tunnel_vision_claustrophobic |
Tunnel Vision (Claustrophobic) |
psychedelic_refraction |
Psychedelic Refraction |
security_monitor_glow |
Security Monitor Glow |
holographic_reflections |
Holographic Reflections |
mirror_split_horizontal |
Mirror Split (Horizontal) |
mirror_split_vertical |
Mirror Split (Vertical) |
shattered_glass |
Shattered Glass |
retro_tv_curvature |
Retro TV Curvature |
acid_bloom |
Acid Bloom |
Engines
Four base engines implement all 86 effects. Each engine handles a family of variants.
| Engine | Effects | What it does |
|---|---|---|
flare_glow |
25 | Anamorphic streaks, orb artifacts, glow bloom, halation, neon glow, starburst, bokeh |
optical_distortion |
18 | Geometric remapping via OpenCV cv2.remap — barrel, pincushion, vignette, lens warp, prism |
atmospheric_layer |
25 | Procedural noise layers — fog, smoke, haze, dust, rain streaks, volumetric light |
stylized_optical |
18 | Kaleidoscope, mirror, glass/crystal refraction, CRT curvature, psychedelic transforms |
The resolver maps each slug to (base_engine, variant, params) from data/effects_catalog.json.
Engines are instantiated lazily. Optical distortion remap arrays are computed once and cached.
Atmospheric noise is procedural numpy — no extra dependency at base install; [advanced] adds
scikit-image for higher quality layering. Three flare effects use SVG templates rendered via
[overlay]; without it a PIL approximation runs with a UserWarning.
OpticConfig
OpticConfig is a Pydantic model. All fields except effect have defaults.
from optic_fx import OpticConfig
cfg = OpticConfig(
effect="anamorphic_lens_flare_gold",
intensity=0.9,
position=(0.75, 0.25),
blend_mode="screen",
)
| Field | Type | Default | Notes |
|---|---|---|---|
effect |
str |
required | Slug from the catalog |
intensity |
float |
0.75 |
Overall effect strength |
opacity |
float |
1.0 |
Layer opacity before blend |
blend_mode |
str |
"screen" |
screen, add, overlay, multiply, soft_light |
seed |
int | None |
None |
Fix random seed for reproducible noise |
start_time |
float |
0.0 |
Seconds into the clip to start effect |
duration |
float | None |
None |
Duration in seconds; None = full clip |
in_animation |
str |
"none" |
fade_in or none |
out_animation |
str |
"none" |
fade_out or none |
position |
tuple[float, float] | None |
None |
Normalized (x, y) for flare origin |
flare_color |
str | None |
None |
CSS color override for flare tint |
follow_motion |
bool |
False |
Subtle motion-based flare drift |
bloom_radius |
float |
12.0 |
Bloom kernel radius in pixels |
density |
float |
0.5 |
Atmospheric layer opacity/thickness |
movement_speed |
float |
0.5 |
Animation speed for fog/smoke drift |
depth_aware |
bool |
False |
Depth-map-weighted atmospheric composite (advanced) |
color_tint |
str | None |
None |
CSS color tint for atmospheric layer |
distortion_strength |
float |
0.5 |
Geometric distortion amount |
chromatic_separation |
float |
0.0 |
Extra RGB fringing on distortion edges |
video_codec |
str |
"libx264" |
Output video codec |
audio_codec |
str |
"copy" |
Output audio handling |
Extra fields are forbidden (extra="forbid") — unknown keys raise immediately.
CLI
Every subcommand accepts --help.
Apply an effect:
optic-fx apply --video raw.mp4 --effect anamorphic_lens_flare_gold --out flared.mp4
Render a standalone flare overlay (no input video):
optic-fx flare --effect anamorphic_lens_flare_subtle \
--width 1920 --height 1080 --position 0.7,0.3 --duration 2 --out flare.webm
Pre-render an atmospheric layer:
optic-fx atmosphere --effect fog_overlay_dense --width 1920 --height 1080 --duration 10 --out fog.webm
Browse the catalog:
optic-fx list # all 86, one slug per line
optic-fx list --category atmospheric_and_diffusion # 25
optic-fx categories # four category names
optic-fx info anamorphic_lens_flare_gold # engine, variant, description
Preview an effect on a generated test frame:
optic-fx preview --effect kaleidoscope_prism_hexagonal --out preview.mp4
Print the OpticConfig JSON schema: optic-fx schema --pretty
Composition with color-fx, video-fx
optic-fx is one of three siblings. Each handles a distinct layer of the finishing pass.
# video-fx → optic-fx → color-fx pipeline
from optic_fx import apply_optic_chain
apply_optic_chain(
video="dof.mp4", # output from video-fx
effects=[
{"effect": "barrel_distortion_gentle"},
{"effect": "anamorphic_lens_flare_subtle", "position": (0.7, 0.3)},
{"effect": "halation_warm", "intensity": 0.5},
{"effect": "vignette_subtle"},
],
output="optic.mp4", # feed into color-fx next
)
Pre-render a long atmospheric layer once, reuse across many shots:
from optic_fx import pre_render_atmosphere, composite_atmosphere
atmo = pre_render_atmosphere(
effect="volumetric_atmosphere_cathedral",
width=1920, height=1080, duration=10.0,
output="atmo_cathedral.webm",
)
for shot in shots:
composite_atmosphere(shot, atmo, output=f"{shot.stem}_atmo.mp4")
The siblings share no runtime state and can run in any order. Each installs independently.
What this is NOT
optic-fx is not a node-based compositor. No GUI, no real-time preview, no timeline. It processes clips, not projects.
The 9 effects overlapping with video-fx — Fisheye Lens, Tilt Shift, Rack Focus, Depth of Field, Chromatic Aberration, Rolling Shutter, Light Leak, God Rays, Underwater Caustics — are deliberately absent. Use the video-fx versions for those.
Atmospheric layers are procedurally generated, not physically simulated. Fog does not respond to
scene geometry. The depth_aware field requires an external depth map — optic-fx does not produce
depth maps.
Provenance
Built at Trollfabriken AITrix AB for the CineForge pipeline's anamorphic flare and atmospheric work, AIMOS Insight municipal report visual polish, SocKartan civic transparency segments, and the Timelock Film AB festival slate's optical finishing pass.
Source: https://github.com/tomastimelock/optic-fx — License: MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file optic_fx-0.1.0.tar.gz.
File metadata
- Download URL: optic_fx-0.1.0.tar.gz
- Upload date:
- Size: 161.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1d8ec12ac5bc29f9fd05341ac60f98d19319b9c6ddb0becea72387fd7b0a4dd
|
|
| MD5 |
0a524f042d67396fc889ceb32c5ee753
|
|
| BLAKE2b-256 |
6cf44146e23bccabc87a7d7d9b1bd1b11cd4ee1216fedd92104a2a5c7c5d75c1
|
Provenance
The following attestation bundles were made for optic_fx-0.1.0.tar.gz:
Publisher:
release.yml on tomastimelock/optic-fx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
optic_fx-0.1.0.tar.gz -
Subject digest:
d1d8ec12ac5bc29f9fd05341ac60f98d19319b9c6ddb0becea72387fd7b0a4dd - Sigstore transparency entry: 1629290786
- Sigstore integration time:
-
Permalink:
tomastimelock/optic-fx@b91dfaba54b96b5ad4a42dd8a645a3840f8e062a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tomastimelock
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b91dfaba54b96b5ad4a42dd8a645a3840f8e062a -
Trigger Event:
push
-
Statement type:
File details
Details for the file optic_fx-0.1.0-py3-none-any.whl.
File metadata
- Download URL: optic_fx-0.1.0-py3-none-any.whl
- Upload date:
- Size: 77.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52d568eef1fbe8ffb04ee858cba6e13ac48c3b904b35f6044176d09ac14f3cba
|
|
| MD5 |
961fcca9eb5e8bb4fa7f51ceff6e75fd
|
|
| BLAKE2b-256 |
2a63b6fa0ae7e044aa1a606b2d45efe7745936bca54a1fe6e9afbbb94c625b21
|
Provenance
The following attestation bundles were made for optic_fx-0.1.0-py3-none-any.whl:
Publisher:
release.yml on tomastimelock/optic-fx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
optic_fx-0.1.0-py3-none-any.whl -
Subject digest:
52d568eef1fbe8ffb04ee858cba6e13ac48c3b904b35f6044176d09ac14f3cba - Sigstore transparency entry: 1629290816
- Sigstore integration time:
-
Permalink:
tomastimelock/optic-fx@b91dfaba54b96b5ad4a42dd8a645a3840f8e062a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tomastimelock
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b91dfaba54b96b5ad4a42dd8a645a3840f8e062a -
Trigger Event:
push
-
Statement type: