Skip to content

Commit 95fca3c

Browse files
authored
Merge pull request #3 from Reflct/develop
Sharp Frames v0.4.0
2 parents a80453a + 6b02cb5 commit 95fca3c

53 files changed

Lines changed: 8414 additions & 3775 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master, develop]
6+
pull_request:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
test:
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os: [ubuntu-latest, macos-latest, windows-latest]
17+
python-version: ["3.10", "3.11", "3.12", "3.13"]
18+
runs-on: ${{ matrix.os }}
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- uses: actions/setup-python@v5
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
cache: pip
27+
28+
- name: Install FFmpeg (Ubuntu)
29+
if: runner.os == 'Linux'
30+
run: sudo apt-get update && sudo apt-get install --yes ffmpeg
31+
32+
- name: Install FFmpeg (macOS)
33+
if: runner.os == 'macOS'
34+
run: brew install ffmpeg
35+
36+
- name: Install FFmpeg (Windows)
37+
if: runner.os == 'Windows'
38+
run: choco install ffmpeg --yes --no-progress
39+
40+
- name: Install package and test dependencies
41+
run: python -m pip install --upgrade pip && python -m pip install -r requirements.txt
42+
43+
- name: Run tests
44+
run: python -m pytest -q
45+
46+
- name: Build wheel
47+
run: python -m pip wheel . --no-deps --wheel-dir dist
48+
49+
minimum-textual:
50+
runs-on: ubuntu-latest
51+
52+
steps:
53+
- uses: actions/checkout@v4
54+
55+
- uses: actions/setup-python@v5
56+
with:
57+
python-version: "3.10"
58+
cache: pip
59+
60+
- name: Install FFmpeg
61+
run: sudo apt-get update && sudo apt-get install --yes ffmpeg
62+
63+
- name: Install minimum supported Textual
64+
run: >-
65+
python -m pip install --upgrade pip &&
66+
python -m pip install -e . -r tests/requirements.txt "textual==5.0.0" &&
67+
python -m pip check
68+
69+
- name: Run tests at the minimum Textual version
70+
run: python -m pytest -q
71+
72+
package:
73+
runs-on: ubuntu-latest
74+
75+
steps:
76+
- uses: actions/checkout@v4
77+
78+
- uses: actions/setup-python@v5
79+
with:
80+
python-version: "3.13"
81+
cache: pip
82+
83+
- name: Install build tooling and FFmpeg
84+
run: |
85+
sudo apt-get update && sudo apt-get install --yes ffmpeg
86+
python -m pip install --upgrade pip build
87+
88+
- name: Build distribution artifacts
89+
run: python -m build
90+
91+
- name: Smoke test installed wheel outside the checkout
92+
run: |
93+
python -m venv "$RUNNER_TEMP/wheel-smoke"
94+
"$RUNNER_TEMP/wheel-smoke/bin/python" -m pip install dist/*.whl
95+
cd "$RUNNER_TEMP"
96+
"$RUNNER_TEMP/wheel-smoke/bin/python" -c "import sharp_frames; from sharp_frames.ui.components.raster_preview import RasterImagePreview; print(sharp_frames.__version__)"
97+
"$RUNNER_TEMP/wheel-smoke/bin/sharp-frames" --help

‎.gitignore‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ pip-delete-this-directory.txt
3030
htmlcov/
3131
.tox/
3232

33-
# Editor files
33+
# Editor and local agent files
3434
.vscode/
3535
.idea/
36+
.codex/
3637
*.swp
3738
*.swo
3839

‎CHANGELOG.md‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@ All notable changes to the Sharp Frames project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.4.0] - 2026-07-18
9+
10+
### Added
11+
- Scrollable full-frame selection timeline with click-to-inspect and keyboard navigation
12+
- Inline terminal frame preview via Sixel/Kitty raster graphics with an external-viewer fallback
13+
- Automatic color space detection and conversion to sRGB for HDR and wide-gamut sources (BT.2020, HLG, PQ)
14+
- Resolution-normalized focus scoring for more consistent comparisons across source sizes
15+
- Trend-aware outlier detection with improved defaults
16+
- Responsive selection layout that keeps the preview and chart visible on short terminals
17+
- Shared alpha-preserving image decode/resize/encode helpers
18+
- Cross-platform CI coverage for Python 3.10 through 3.13 on Linux, macOS, and Windows, plus the minimum supported Textual version
19+
- Regression coverage for selection quality, output collisions, cancellation, and runtime cleanup
20+
21+
### Changed
22+
- Selection methods now balance sharpness and temporal distribution more consistently
23+
- Frame extraction, analysis, preview, and saving pipelines provide stricter validation and failure reporting
24+
- Image-directory exports preserve content while correctly handling format conversion and case-insensitive filename collisions
25+
- Configuration and selection screens provide clearer controls, status, and keyboard behavior; the processing screen is vertically centered
26+
- Textual requirement raised to 5.0 or newer; new dependencies `textual-image` and `Pillow`
27+
28+
### Fixed
29+
- FFmpeg and FFprobe process cleanup, cancellation, timeout, and pipe handling
30+
- Partial or failed image reads being treated as valid zero-quality frames
31+
- Selection previews disagreeing with the frames produced during processing
32+
- Output metadata reporting frames that were not successfully saved
33+
- Platform-specific dependency guidance and Windows-safe process startup
34+
- Start Over after saving returning to the middle of setup instead of the first step
35+
- Cancel during setup leaving the application running on an empty screen
36+
837
## [0.3.1] - 2025-01-29
938

1039
### Fixed
@@ -136,4 +165,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
136165
- outlier-removal: Remove outliers based on comparison with neighbors
137166
- Interactive mode with guided prompts
138167
- Proper Python package structure for pip and pipx installation
139-
- Command-line interface with `sharp-frames` command
168+
- Command-line interface with `sharp-frames` command

‎README.md‎

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ Or with pipx for isolated installation:
1414
pipx install sharp-frames
1515
```
1616

17-
**IMPORTANT: Video Processing Requirement**: Install FFmpeg separately for video input support.
17+
**IMPORTANT: Video Processing Requirement**: Install an FFmpeg distribution that includes both `ffmpeg` and `ffprobe`. Both executables must be on `PATH`; image-directory processing does not require them.
1818
- **Windows**: Download from [FFmpeg website](https://ffmpeg.org/download.html) and add to PATH
1919
- **macOS**: `brew install ffmpeg`
2020
- **Linux**: `sudo apt install ffmpeg`
2121

22+
HDR-to-SDR extraction additionally requires an FFmpeg build with the `zscale` filter (`libzimg`). You can verify support with `ffmpeg -filters | grep zscale`. Non-HDR video processing does not require `zscale`.
23+
2224
## Quick Start
2325

2426
### Modern Interface (Default)
@@ -45,9 +47,9 @@ sharp-frames <input> <output> [options]
4547
```
4648

4749
**Input Types:**
48-
- Video files: `.mp4`, `.avi`, `.mov`, `.mkv`, `.wmv`, `.flv`, `.webm`, `.m4v`, etc.
50+
- Video files: `.mp4`, `.avi`, `.mov`, `.mkv`, `.wmv`, `.flv`, `.webm`, `.m4v`, `.3gp`, `.3g2`, `.ogv`, `.ts`, `.mts`, `.m2ts`, `.mpg`, `.mpeg`, `.vob`
4951
- Video directories: Processes all videos in a folder
50-
- Image directories: `.jpg`, `.jpeg`, `.png`, `.bmp`, `.tiff`, `.webp`, etc.
52+
- Image directories: `.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`, `.tiff`, `.webp`, `.ppm`, `.pgm`, `.pbm`
5153

5254
## Selection Methods
5355

@@ -63,10 +65,10 @@ Divides content into batches and selects the sharpest frame from each batch.
6365
--selection-method batched --batch-size 5 --batch-buffer 2
6466
```
6567

66-
### Outlier Removal
68+
### Outlier Detection
6769
Removes unusually blurry frames by comparing each frame to its neighbors.
6870
```bash
69-
--selection-method outlier-removal --outlier-window-size 15 --outlier-sensitivity 50
71+
--selection-method outlier-removal --outlier-window-size 15 --outlier-sensitivity 60
7072
```
7173

7274
## Command Line Options
@@ -79,11 +81,11 @@ Removes unusually blurry frames by comparing each frame to its neighbors.
7981

8082
### Selection Method Parameters
8183
- `--num-frames <int>`: Number of frames to select (best-n, default: 300)
82-
- `--min-buffer <int>`: Minimum gap between selected frames (best-n, default: 3)
84+
- `--min-buffer <int>`: Minimum number of intervening frames between selected frames (best-n, default: 3)
8385
- `--batch-size <int>`: Frames per batch (batched, default: 5)
8486
- `--batch-buffer <int>`: Frames to skip between batches (batched, default: 2)
85-
- `--outlier-window-size <int>`: Neighbor comparison window (outlier-removal, default: 15)
86-
- `--outlier-sensitivity <int>`: Removal aggressiveness 0-100 (outlier-removal, default: 50)
87+
- `--outlier-window-size <int>`: Local comparison window, minimum 5 (outlier-removal, default: 15)
88+
- `--outlier-sensitivity <int>`: Detection sensitivity 0-100 (outlier-removal, default: 60)
8789

8890
## Examples
8991

@@ -125,23 +127,28 @@ sharp-frames photos selected --selection-method outlier-removal --outlier-sensit
125127

126128
## Requirements
127129

128-
- Python 3.7 or higher
129-
- Dependencies installed automatically: `opencv-python`, `numpy`, `tqdm`, `textual`
130-
- FFmpeg (for video processing only)
130+
- Python 3.10 or higher
131+
- Dependencies installed automatically: `opencv-python`, `numpy`, `tqdm`,
132+
`textual`, `textual-image`
133+
- FFmpeg and FFprobe (for video processing only)
134+
- FFmpeg `zscale`/`libzimg` support (for HDR-to-SDR processing only)
131135

132136
## How It Works
133137

134138
1. **Validation**: Checks input paths, file formats, and system dependencies
135139
2. **Extraction**: Videos are extracted to frames at specified FPS using FFmpeg
136-
3. **Analysis**: Calculates sharpness scores using Laplacian variance in parallel
137-
4. **Selection**: Applies chosen algorithm to select the best frames/images
140+
3. **Analysis**: Normalizes analysis resolution, lightly denoises each image,
141+
and combines Laplacian variance with Tenengrad focus scoring in parallel.
142+
Unreadable inputs are excluded and reported.
143+
4. **Selection**: Applies the chosen source-aware algorithm to select the best
144+
naturally ordered frames/images.
138145
5. **Output**: Saves selected content with metadata including scores and parameters
139146

140147
## Output
141148

142149
- Selected frames/images with descriptive filenames
143150
- `selected_metadata.json` with processing details, parameters, and sharpness scores
144-
- Preserves original formats for image directory input
151+
- Transcodes selected images to the configured output format (`jpg` by default)
145152
- Automatic output directory creation with permission validation
146153

147154
## Help & Support

‎RELEASE_NOTES.md‎

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,35 @@
1-
# Sharp Frames v0.2.0 Release Notes
1+
# Sharp Frames v0.4.0 Release Notes
22

3-
## New Features
3+
## Highlights
44

5-
### Textual Interface (Default)
6-
- Replaces command-line prompts with step-by-step wizard
7-
- Real-time input validation and error feedback
8-
- Enhanced error messages with specific guidance
5+
- Explore the complete analyzed frame set in a scrollable timeline — click any bar to preview that frame directly in the terminal.
6+
- iPhone and HDR sources (BT.2020, HLG, PQ) are detected and converted to sRGB automatically.
7+
- Get more reliable selections from resolution-normalized focus scoring, trend-aware outlier detection, and improved temporal distribution.
8+
- Preview and execution now share the same selection rules, so displayed counts and chosen frames agree.
99

10-
### Video Directory Processing
11-
- Process all videos in a folder with a single command
12-
- Automatically detects and processes supported video formats
13-
- Maintains individual processing settings for each video
10+
## Interface Improvements
1411

15-
### Usage Changes
16-
```bash
17-
# New default behavior
18-
sharp-frames # Launches textual interface
19-
20-
# Existing functionality unchanged
21-
sharp-frames input.mp4 output/ # Direct processing
22-
sharp-frames video_folder/ output/ # Process all videos in folder
23-
sharp-frames --interactive # Legacy prompts
24-
```
25-
26-
## Technical Changes
12+
- Full-frame selection timeline with click-to-inspect, horizontal scrolling, and keyboard navigation (arrows, PgUp/PgDn through selected frames, Ctrl+PgUp/PgDn paging, Home/End).
13+
- Inline frame preview rendered through Sixel or Kitty terminal graphics, with an external-viewer fallback (press `O`).
14+
- Responsive layout keeps the preview and chart visible on short terminals (down to 80×24) while preserving the spacious layout on large ones.
15+
- Start Over returns to the first setup step with a clean configuration, and Cancel exits the application.
16+
- Clearer configuration controls and validation feedback.
17+
- More actionable dependency and processing errors across supported platforms.
2718

28-
### Added
29-
- Path validation with existence/permission checking
30-
- Numeric field validation with range checking
31-
- Thread-safe subprocess management
32-
- UI component testing
33-
- Enhanced error analysis and reporting
19+
## Reliability and Compatibility
3420

35-
### Fixed
36-
- Configuration parameter mapping
37-
- Resource cleanup (temp files, subprocesses)
38-
- Error message specificity
21+
- HDR and wide-gamut color spaces are converted to sRGB/BT.709 through FFmpeg `zscale`, with a clear error for unsupported BT.2020 constant-luminance sources.
22+
- Hardened FFmpeg and FFprobe cancellation, timeouts, output draining, and temporary-directory cleanup.
23+
- Unreadable images are excluded and reported instead of silently receiving valid-looking scores.
24+
- Image exports preserve alpha and handle format conversion, partial failures, metadata accuracy, and case-insensitive filename collisions.
25+
- CI covers Linux, macOS, and Windows on Python 3.10, 3.11, 3.12, and 3.13, plus the minimum supported Textual version.
3926

40-
## Breaking Changes
41-
- `sharp-frames` without arguments now launches UI instead of showing help
42-
- Use `sharp-frames --help` for command-line help
27+
## Upgrade
4328

44-
## Installation
4529
```bash
4630
pip install --upgrade sharp-frames
4731
# or
4832
pipx upgrade sharp-frames
4933
```
5034

51-
## Dependencies
52-
- Added: `textual>=0.41.0`
53-
- All existing dependencies unchanged
35+
New dependencies (`textual-image`, `Pillow`) install automatically. FFmpeg and FFprobe remain required for video processing and must be available on `PATH`; HDR-to-SDR conversion additionally requires FFmpeg built with `zscale`/`libzimg` support.

0 commit comments

Comments
 (0)