# destrobe
**CLI tool for reducing video strobing and flicker**
A cross-platform Python CLI that reduces strobing/flicker in videos while preserving audio and sync. Designed to be simple, fast, and safe-by-default for photosensitivity concerns.
## ⚠️ Important Safety Notice
**destrobe reduces flashing but cannot guarantee complete removal of all photosensitive triggers.** Always preview content first if you have photosensitive epilepsy or similar conditions. Use at your own discretion.
### ⚠️ Example Files Warning
**The example videos in the `examples/` directory contain rapid flashing and strobing effects that may trigger photosensitive epilepsy or seizures.** These files are included specifically to demonstrate destrobe's flicker reduction capabilities on challenging content. **DO NOT VIEW the original files directly if you have photosensitive epilepsy or related conditions.** Only view the processed versions (e.g., `examples/porygon_ULTRA.preview.mp4`) which have had the flashing significantly reduced.
## Quick Start
```bash
# Install with pipx (recommended)
pipx install destrobe
# Basic usage - process a video with default settings
destrobe run input.mp4
# Preview before processing (recommended)
destrobe preview input.mp4
# Batch process a directory
destrobe run /path/to/videos --recursive
# Use stronger filtering
destrobe run input.mp4 --preset strong
```
## Features
- **Three filtering methods**: Temporal median (`median3`), motion-aware smoothing (`ema`), and flash detection/capping (`flashcap`)
- **Safe presets**: `safe`, `balanced`, and `strong` configurations for different needs
- **Audio preservation**: Automatically remux original audio using FFmpeg when available
- **Batch processing**: Process individual files or entire directories recursively
- **Preview mode**: Generate side-by-side comparisons before full processing
- **Quality metrics**: Measure flicker reduction and structural similarity
- **Performance monitoring**: Built-in benchmarking and progress tracking
- **Cross-platform**: Works on macOS, Linux, and Windows
## Installation
### Using pipx (Recommended)
```bash
# Install from PyPI (simplest)
pipx install destrobe
# Or install from GitHub (latest development version)
pipx install git+https://github.com/samjhill/destrobe.git
```
### Using pip
```bash
# Install from PyPI
pip install destrobe
# Or install from GitHub
pip install git+https://github.com/samjhill/destrobe.git
```
### From Source
```bash
git clone https://github.com/samhilll/destrobe.git
cd destrobe
pip install -e .
```
### Requirements
- Python 3.10+
- FFmpeg (optional, for audio remux)
- Dependencies: OpenCV, NumPy, scikit-image, typer, rich, tqdm
## Usage
### Basic Commands
#### Process Videos
```bash
# Process single file
destrobe run video.mp4
# Process multiple files
destrobe run video1.mp4 video2.mkv video3.avi
# Process directory (non-recursive)
destrobe run /path/to/videos
# Process directory recursively
destrobe run /path/to/videos --recursive
```
#### Preview Mode
```bash
# Create 10-second preview starting at 30 seconds
destrobe preview video.mp4
# Custom preview settings
destrobe preview video.mp4 --seconds 15 --start 00:01:30 --method ema
```
#### Analyze Metrics
```bash
# Show flicker metrics
destrobe metrics video.mp4
# Output as JSON
destrobe metrics video.mp4 --json
```
### Filtering Methods
#### `median3` (Default)
Temporal median filter using 3-frame window. Excellent for removing isolated flashes while preserving motion.
```bash
destrobe run video.mp4 --method median3
```
#### `ema` (Exponential Moving Average)
Motion-aware temporal smoothing. Adapts filtering strength based on detected motion.
```bash
destrobe run video.mp4 --method ema --strength 0.7
```
#### `flashcap` (Flash Detection & Capping)
Detects sudden brightness spikes and caps them. Best for content with known flash patterns.
```bash
destrobe run video.mp4 --method flashcap --flash-thresh 0.10
```
### Presets
#### `safe` (Recommended for sensitive viewers)
- Method: `flashcap`
- Strength: 0.7
- Flash threshold: 0.10
```bash
destrobe run video.mp4 --preset safe
```
#### `balanced` (Default)
- Method: `median3`
- Balanced between quality and flicker reduction
```bash
destrobe run video.mp4 --preset balanced
```
#### `strong` (Maximum reduction)
- Method: `ema`
- Strength: 0.75
- More aggressive filtering
```bash
destrobe run video.mp4 --preset strong
```
### Advanced Options
```bash
destrobe run input.mp4 \
--method median3 \
--strength 0.6 \
--flash-thresh 0.12 \
--outdir processed \
--ext .mp4 \
--logfile metrics.jsonl \
--benchmark \
--threads 4 \
--overwrite
```
#### Output Control
- `--outdir`: Output directory (default: `destrobed`)
- `--ext`: Output file extension (default: `.mp4`)
- `--overwrite`: Allow overwriting existing files
- `--no-audio`: Skip audio remux (video only)
#### Performance & Logging
- `--benchmark`: Show processing speed and system info
- `--logfile`: Save detailed metrics to JSONL file
- `--threads`: Number of processing threads
#### Other Options
- `--no-warn`: Skip photosensitivity warning
- `--recursive`: Process directories recursively
## Output
### File Naming
By default, processed files are saved with method suffix:
- `input.mp4` → `destrobed/input.median3.mp4`
- `input.mp4` → `destrobed/input.ema.mp4` (when using EMA)
- `input.mp4` → `destrobed/input.flashcap.mp4` (when using flashcap)
### Console Output
```
→ SailorMoon_EP01.mp4 → destrobed/SailorMoon_EP01.median3.mp4
FI: 0.082 → 0.041 (-50.0%), SSIM: 0.967
Performance: 58.2 fps
```
### Metrics Logging
When using `--logfile`, detailed metrics are saved as JSON Lines:
```json
{
"file": "input.mp4",
"output": "destrobed/input.median3.mp4",
"method": "median3",
"flicker_before": 0.082,
"flicker_after": 0.041,
"ssim": 0.967,
"fps": 58.2,
"duration_s": 132.4,
"audio_remuxed": true
}
```
## Performance
Typical performance on modern hardware:
| Resolution | Method | Apple M1 | Intel i7 | Notes |
|------------|--------|----------|----------|-------|
| 1080p | median3 | ~80 fps | ~60 fps | Real-time+ |
| 1080p | ema | ~90 fps | ~70 fps | Fastest |
| 1080p | flashcap | ~75 fps | ~55 fps | Most thorough |
| 4K | median3 | ~25 fps | ~18 fps | Usable |
Performance can be improved by:
- Using `--threads` to match your CPU cores
- Processing shorter segments for very large files
- Using `ema` method for fastest processing
## Technical Details
### Algorithms
#### Temporal Median Filter (`median3`)
- Uses 3-frame sliding window
- Computes per-pixel median on luminance channel
- Preserves chroma from center frame
- Excellent for isolated flashes, minimal motion blur
#### Exponential Moving Average (`ema`)
- Motion-aware temporal smoothing
- Adapts alpha based on inter-frame motion
- Higher motion = less smoothing (preserves action scenes)
- Good balance of speed and quality
#### Flash Detection & Capping (`flashcap`)
- Detects sudden luminance spikes
- Caps detected flashes by blending with neighbors
- Applies mild temporal smoothing to other frames
- Best for known problematic content
### Quality Metrics
#### Flicker Index (FI)
Median of frame-to-frame luminance deltas. Lower values indicate less flicker.
#### Structural Similarity (SSIM)
Measures how well the processed video preserves the original's structure. Values near 1.0 indicate high quality preservation.
### Audio Handling
- Original audio is preserved via FFmpeg remux when available
- Falls back to video-only output if FFmpeg is missing
- No re-encoding of audio streams (fast and lossless)
## Troubleshooting
### FFmpeg Not Found
```bash
# Install FFmpeg
# macOS
brew install ffmpeg
# Ubuntu/Debian
sudo apt install ffmpeg
# Windows
# Download from https://ffmpeg.org/download.html
```
### Slow Processing
- Use `--threads N` where N is your CPU core count
- Try `ema` method for fastest processing
- Process shorter clips first to test settings
- Consider reducing input resolution for very large files
### Poor Quality Results
- Try different methods: `median3` for flashes, `ema` for general smoothing
- Adjust `--strength` (lower = less filtering)
- Use `--preview` to test settings before full processing
- Check `--flash-thresh` for flashcap method
### Large File Sizes
- Output uses same codec as input when possible
- Use `--ext .mp4` for better compression
- Original audio is copied without re-encoding
## Development
### Running Tests
```bash
# Install development dependencies
pip install -e .[dev]
# Run tests
pytest
# Run with coverage
pytest --cov=destrobe
# Run linting
ruff check .
black --check .
mypy destrobe/
```
### Creating Test Videos
```python
from destrobe.tests.synthetic_video import create_test_video_suite
from pathlib import Path
# Generate test videos
test_videos = create_test_video_suite(Path("test_outputs"))
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass and linting is clean
5. Submit a pull request
## License
MIT License - see [LICENSE](LICENSE) for details.
## Acknowledgments
- Built with OpenCV for video processing
- Uses scikit-image for SSIM computation
- CLI powered by Typer and Rich
- Inspired by the need for accessible video content
## Related Projects
- [VapourSynth](http://www.vapoursynth.com/) - Advanced video processing framework
- [FFmpeg](https://ffmpeg.org/) - Multimedia framework used for audio remux
- [OpenCV](https://opencv.org/) - Computer vision library for video I/O
---
**Remember**: This tool reduces flashes but cannot guarantee complete removal. Always preview content if you have photosensitive conditions.
Raw data
{
"_id": null,
"home_page": null,
"name": "destrobe",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "video, flicker, strobe, photosensitive, epilepsy, accessibility, cli",
"author": null,
"author_email": "Sam Hill <sam@samjhill.com>",
"download_url": "https://files.pythonhosted.org/packages/a0/84/9f5b77c14f93eda21ba77211087a605118bfd862b61a87d200cbe218d4c6/destrobe-1.0.0.tar.gz",
"platform": null,
"description": "# destrobe\n\n**CLI tool for reducing video strobing and flicker**\n\nA cross-platform Python CLI that reduces strobing/flicker in videos while preserving audio and sync. Designed to be simple, fast, and safe-by-default for photosensitivity concerns.\n\n## \u26a0\ufe0f Important Safety Notice\n\n**destrobe reduces flashing but cannot guarantee complete removal of all photosensitive triggers.** Always preview content first if you have photosensitive epilepsy or similar conditions. Use at your own discretion.\n\n### \u26a0\ufe0f Example Files Warning\n\n**The example videos in the `examples/` directory contain rapid flashing and strobing effects that may trigger photosensitive epilepsy or seizures.** These files are included specifically to demonstrate destrobe's flicker reduction capabilities on challenging content. **DO NOT VIEW the original files directly if you have photosensitive epilepsy or related conditions.** Only view the processed versions (e.g., `examples/porygon_ULTRA.preview.mp4`) which have had the flashing significantly reduced.\n\n## Quick Start\n\n```bash\n# Install with pipx (recommended)\npipx install destrobe\n\n# Basic usage - process a video with default settings\ndestrobe run input.mp4\n\n# Preview before processing (recommended)\ndestrobe preview input.mp4\n\n# Batch process a directory\ndestrobe run /path/to/videos --recursive\n\n# Use stronger filtering\ndestrobe run input.mp4 --preset strong\n```\n\n## Features\n\n- **Three filtering methods**: Temporal median (`median3`), motion-aware smoothing (`ema`), and flash detection/capping (`flashcap`)\n- **Safe presets**: `safe`, `balanced`, and `strong` configurations for different needs\n- **Audio preservation**: Automatically remux original audio using FFmpeg when available\n- **Batch processing**: Process individual files or entire directories recursively\n- **Preview mode**: Generate side-by-side comparisons before full processing\n- **Quality metrics**: Measure flicker reduction and structural similarity\n- **Performance monitoring**: Built-in benchmarking and progress tracking\n- **Cross-platform**: Works on macOS, Linux, and Windows\n\n## Installation\n\n### Using pipx (Recommended)\n\n```bash\n# Install from PyPI (simplest)\npipx install destrobe\n\n# Or install from GitHub (latest development version)\npipx install git+https://github.com/samjhill/destrobe.git\n```\n\n### Using pip\n\n```bash\n# Install from PyPI\npip install destrobe\n\n# Or install from GitHub\npip install git+https://github.com/samjhill/destrobe.git\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/samhilll/destrobe.git\ncd destrobe\npip install -e .\n```\n\n### Requirements\n\n- Python 3.10+\n- FFmpeg (optional, for audio remux)\n- Dependencies: OpenCV, NumPy, scikit-image, typer, rich, tqdm\n\n## Usage\n\n### Basic Commands\n\n#### Process Videos\n\n```bash\n# Process single file\ndestrobe run video.mp4\n\n# Process multiple files\ndestrobe run video1.mp4 video2.mkv video3.avi\n\n# Process directory (non-recursive)\ndestrobe run /path/to/videos\n\n# Process directory recursively\ndestrobe run /path/to/videos --recursive\n```\n\n#### Preview Mode\n\n```bash\n# Create 10-second preview starting at 30 seconds\ndestrobe preview video.mp4\n\n# Custom preview settings\ndestrobe preview video.mp4 --seconds 15 --start 00:01:30 --method ema\n```\n\n#### Analyze Metrics\n\n```bash\n# Show flicker metrics\ndestrobe metrics video.mp4\n\n# Output as JSON\ndestrobe metrics video.mp4 --json\n```\n\n### Filtering Methods\n\n#### `median3` (Default)\nTemporal median filter using 3-frame window. Excellent for removing isolated flashes while preserving motion.\n\n```bash\ndestrobe run video.mp4 --method median3\n```\n\n#### `ema` (Exponential Moving Average)\nMotion-aware temporal smoothing. Adapts filtering strength based on detected motion.\n\n```bash\ndestrobe run video.mp4 --method ema --strength 0.7\n```\n\n#### `flashcap` (Flash Detection & Capping)\nDetects sudden brightness spikes and caps them. Best for content with known flash patterns.\n\n```bash\ndestrobe run video.mp4 --method flashcap --flash-thresh 0.10\n```\n\n### Presets\n\n#### `safe` (Recommended for sensitive viewers)\n- Method: `flashcap`\n- Strength: 0.7\n- Flash threshold: 0.10\n\n```bash\ndestrobe run video.mp4 --preset safe\n```\n\n#### `balanced` (Default)\n- Method: `median3`\n- Balanced between quality and flicker reduction\n\n```bash\ndestrobe run video.mp4 --preset balanced\n```\n\n#### `strong` (Maximum reduction)\n- Method: `ema`\n- Strength: 0.75\n- More aggressive filtering\n\n```bash\ndestrobe run video.mp4 --preset strong\n```\n\n### Advanced Options\n\n```bash\ndestrobe run input.mp4 \\\n --method median3 \\\n --strength 0.6 \\\n --flash-thresh 0.12 \\\n --outdir processed \\\n --ext .mp4 \\\n --logfile metrics.jsonl \\\n --benchmark \\\n --threads 4 \\\n --overwrite\n```\n\n#### Output Control\n- `--outdir`: Output directory (default: `destrobed`)\n- `--ext`: Output file extension (default: `.mp4`)\n- `--overwrite`: Allow overwriting existing files\n- `--no-audio`: Skip audio remux (video only)\n\n#### Performance & Logging\n- `--benchmark`: Show processing speed and system info\n- `--logfile`: Save detailed metrics to JSONL file\n- `--threads`: Number of processing threads\n\n#### Other Options\n- `--no-warn`: Skip photosensitivity warning\n- `--recursive`: Process directories recursively\n\n## Output\n\n### File Naming\nBy default, processed files are saved with method suffix:\n- `input.mp4` \u2192 `destrobed/input.median3.mp4`\n- `input.mp4` \u2192 `destrobed/input.ema.mp4` (when using EMA)\n- `input.mp4` \u2192 `destrobed/input.flashcap.mp4` (when using flashcap)\n\n### Console Output\n```\n\u2192 SailorMoon_EP01.mp4 \u2192 destrobed/SailorMoon_EP01.median3.mp4\n FI: 0.082 \u2192 0.041 (-50.0%), SSIM: 0.967\n Performance: 58.2 fps\n```\n\n### Metrics Logging\nWhen using `--logfile`, detailed metrics are saved as JSON Lines:\n\n```json\n{\n \"file\": \"input.mp4\",\n \"output\": \"destrobed/input.median3.mp4\", \n \"method\": \"median3\",\n \"flicker_before\": 0.082,\n \"flicker_after\": 0.041,\n \"ssim\": 0.967,\n \"fps\": 58.2,\n \"duration_s\": 132.4,\n \"audio_remuxed\": true\n}\n```\n\n## Performance\n\nTypical performance on modern hardware:\n\n| Resolution | Method | Apple M1 | Intel i7 | Notes |\n|------------|--------|----------|----------|-------|\n| 1080p | median3 | ~80 fps | ~60 fps | Real-time+ |\n| 1080p | ema | ~90 fps | ~70 fps | Fastest |\n| 1080p | flashcap | ~75 fps | ~55 fps | Most thorough |\n| 4K | median3 | ~25 fps | ~18 fps | Usable |\n\nPerformance can be improved by:\n- Using `--threads` to match your CPU cores\n- Processing shorter segments for very large files\n- Using `ema` method for fastest processing\n\n## Technical Details\n\n### Algorithms\n\n#### Temporal Median Filter (`median3`)\n- Uses 3-frame sliding window\n- Computes per-pixel median on luminance channel\n- Preserves chroma from center frame\n- Excellent for isolated flashes, minimal motion blur\n\n#### Exponential Moving Average (`ema`)\n- Motion-aware temporal smoothing\n- Adapts alpha based on inter-frame motion\n- Higher motion = less smoothing (preserves action scenes)\n- Good balance of speed and quality\n\n#### Flash Detection & Capping (`flashcap`) \n- Detects sudden luminance spikes\n- Caps detected flashes by blending with neighbors\n- Applies mild temporal smoothing to other frames\n- Best for known problematic content\n\n### Quality Metrics\n\n#### Flicker Index (FI)\nMedian of frame-to-frame luminance deltas. Lower values indicate less flicker.\n\n#### Structural Similarity (SSIM)\nMeasures how well the processed video preserves the original's structure. Values near 1.0 indicate high quality preservation.\n\n### Audio Handling\n- Original audio is preserved via FFmpeg remux when available\n- Falls back to video-only output if FFmpeg is missing\n- No re-encoding of audio streams (fast and lossless)\n\n## Troubleshooting\n\n### FFmpeg Not Found\n```bash\n# Install FFmpeg\n# macOS\nbrew install ffmpeg\n\n# Ubuntu/Debian\nsudo apt install ffmpeg\n\n# Windows\n# Download from https://ffmpeg.org/download.html\n```\n\n### Slow Processing\n- Use `--threads N` where N is your CPU core count\n- Try `ema` method for fastest processing\n- Process shorter clips first to test settings\n- Consider reducing input resolution for very large files\n\n### Poor Quality Results\n- Try different methods: `median3` for flashes, `ema` for general smoothing\n- Adjust `--strength` (lower = less filtering)\n- Use `--preview` to test settings before full processing\n- Check `--flash-thresh` for flashcap method\n\n### Large File Sizes\n- Output uses same codec as input when possible\n- Use `--ext .mp4` for better compression\n- Original audio is copied without re-encoding\n\n## Development\n\n### Running Tests\n\n```bash\n# Install development dependencies\npip install -e .[dev]\n\n# Run tests\npytest\n\n# Run with coverage\npytest --cov=destrobe\n\n# Run linting\nruff check .\nblack --check .\nmypy destrobe/\n```\n\n### Creating Test Videos\n\n```python\nfrom destrobe.tests.synthetic_video import create_test_video_suite\nfrom pathlib import Path\n\n# Generate test videos\ntest_videos = create_test_video_suite(Path(\"test_outputs\"))\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Ensure all tests pass and linting is clean\n5. Submit a pull request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Acknowledgments\n\n- Built with OpenCV for video processing\n- Uses scikit-image for SSIM computation\n- CLI powered by Typer and Rich\n- Inspired by the need for accessible video content\n\n## Related Projects\n\n- [VapourSynth](http://www.vapoursynth.com/) - Advanced video processing framework\n- [FFmpeg](https://ffmpeg.org/) - Multimedia framework used for audio remux\n- [OpenCV](https://opencv.org/) - Computer vision library for video I/O\n\n---\n\n**Remember**: This tool reduces flashes but cannot guarantee complete removal. Always preview content if you have photosensitive conditions.\n",
"bugtrack_url": null,
"license": null,
"summary": "Cross-platform CLI tool for reducing video strobing and flicker while preserving audio and sync",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/samhilll/destrobe",
"Issues": "https://github.com/samhilll/destrobe/issues",
"Repository": "https://github.com/samhilll/destrobe"
},
"split_keywords": [
"video",
" flicker",
" strobe",
" photosensitive",
" epilepsy",
" accessibility",
" cli"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "5f6a255453875b2139fbd277e758f817257800a574f8ff191ef10ba16d3650ff",
"md5": "9bab7edc3cfe3f28b350785ebf84ab34",
"sha256": "e926eebb27773664e982b6ee504ce0b78c42ee0130676a386bf1224f7ae7e277"
},
"downloads": -1,
"filename": "destrobe-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9bab7edc3cfe3f28b350785ebf84ab34",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 40128,
"upload_time": "2025-08-16T01:26:07",
"upload_time_iso_8601": "2025-08-16T01:26:07.035213Z",
"url": "https://files.pythonhosted.org/packages/5f/6a/255453875b2139fbd277e758f817257800a574f8ff191ef10ba16d3650ff/destrobe-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "a0849f5b77c14f93eda21ba77211087a605118bfd862b61a87d200cbe218d4c6",
"md5": "649f66a6401376ff82a5c90efa460a25",
"sha256": "20a827bdc003bdc667a024cc010cbea2868b9832ed4194f0930a59b40adac602"
},
"downloads": -1,
"filename": "destrobe-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "649f66a6401376ff82a5c90efa460a25",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 41454,
"upload_time": "2025-08-16T01:26:08",
"upload_time_iso_8601": "2025-08-16T01:26:08.479954Z",
"url": "https://files.pythonhosted.org/packages/a0/84/9f5b77c14f93eda21ba77211087a605118bfd862b61a87d200cbe218d4c6/destrobe-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-16 01:26:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "samhilll",
"github_project": "destrobe",
"github_not_found": true,
"lcname": "destrobe"
}