OpenScrub 1.0.3__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscrub-1.0.3 → openscrub-1.0.4}/PKG-INFO +34 -3
- {openscrub-1.0.3 → openscrub-1.0.4}/README.md +33 -2
- {openscrub-1.0.3 → openscrub-1.0.4}/openscrub.py +1 -1
- openscrub-1.0.4/openscrub_setup.py +219 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/pyproject.toml +3 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/.gitignore +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/LICENSE +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/install.py +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/openscrub_web.py +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/plate_models.json +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/requirements.txt +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/test_openscrub.py +0 -0
- {openscrub-1.0.3 → openscrub-1.0.4}/zones_ui.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenScrub
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Local, GPU-accelerated redaction for video and screen recordings — blur, black-box, or mosaic faces, names, and any regex-matchable PII, with human review.
|
|
5
5
|
Project-URL: Homepage, https://github.com/austinmabry/OpenScrub
|
|
6
6
|
Project-URL: Repository, https://github.com/austinmabry/OpenScrub
|
|
@@ -349,18 +349,49 @@ gives you two commands: `openscrub` (the CLI engine) and `openscrub-web`
|
|
|
349
349
|
(the web interface). The YuNet face model (~230 KB) downloads
|
|
350
350
|
automatically on first run.
|
|
351
351
|
|
|
352
|
+
### Fresh Windows 11 PC — complete setup (copy-paste)
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
winget install -e --id Python.Python.3.12
|
|
356
|
+
```
|
|
357
|
+
Close and reopen the terminal (so PATH updates), then:
|
|
358
|
+
```
|
|
359
|
+
pip install OpenScrub
|
|
360
|
+
openscrub-setup
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
`openscrub-setup` detects what's missing and installs Tesseract and FFmpeg
|
|
364
|
+
for you via winget (asking first; `--yes` to skip prompts, `--check` to
|
|
365
|
+
only report). Prefer manual control? The equivalent commands:
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
winget install -e --id UB-Mannheim.TesseractOCR
|
|
369
|
+
winget install -e --id Gyan.FFmpeg
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Fresh Linux (Debian/Ubuntu)
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
sudo apt install python3-pip
|
|
376
|
+
pip install OpenScrub
|
|
377
|
+
openscrub-setup # offers: sudo apt install tesseract-ocr ffmpeg
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Then run `openscrub-web` and open the URL it prints.
|
|
381
|
+
|
|
352
382
|
Two system tools are **not** pip-installable and must be present for full
|
|
353
383
|
functionality:
|
|
354
384
|
|
|
355
385
|
1. **Tesseract OCR** — required for every text category (names, SSNs,
|
|
356
386
|
emails, …). Face and plate detection work without it; text detection
|
|
357
387
|
does not.
|
|
358
|
-
- Windows:
|
|
388
|
+
- Windows: `winget install -e --id UB-Mannheim.TesseractOCR`
|
|
389
|
+
(or the installer from https://github.com/UB-Mannheim/tesseract/wiki)
|
|
359
390
|
- Linux: `sudo apt install tesseract-ocr`
|
|
360
391
|
2. **ffmpeg** (ffprobe ships with it) — strongly recommended: audio
|
|
361
392
|
passthrough, H.264 output, and VFR screen-recording normalization all
|
|
362
393
|
depend on it.
|
|
363
|
-
- Windows: `winget install
|
|
394
|
+
- Windows: `winget install -e --id Gyan.FFmpeg`
|
|
364
395
|
- Linux: `sudo apt install ffmpeg`
|
|
365
396
|
|
|
366
397
|
Optional extras:
|
|
@@ -117,18 +117,49 @@ gives you two commands: `openscrub` (the CLI engine) and `openscrub-web`
|
|
|
117
117
|
(the web interface). The YuNet face model (~230 KB) downloads
|
|
118
118
|
automatically on first run.
|
|
119
119
|
|
|
120
|
+
### Fresh Windows 11 PC — complete setup (copy-paste)
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
winget install -e --id Python.Python.3.12
|
|
124
|
+
```
|
|
125
|
+
Close and reopen the terminal (so PATH updates), then:
|
|
126
|
+
```
|
|
127
|
+
pip install OpenScrub
|
|
128
|
+
openscrub-setup
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`openscrub-setup` detects what's missing and installs Tesseract and FFmpeg
|
|
132
|
+
for you via winget (asking first; `--yes` to skip prompts, `--check` to
|
|
133
|
+
only report). Prefer manual control? The equivalent commands:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
winget install -e --id UB-Mannheim.TesseractOCR
|
|
137
|
+
winget install -e --id Gyan.FFmpeg
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Fresh Linux (Debian/Ubuntu)
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
sudo apt install python3-pip
|
|
144
|
+
pip install OpenScrub
|
|
145
|
+
openscrub-setup # offers: sudo apt install tesseract-ocr ffmpeg
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Then run `openscrub-web` and open the URL it prints.
|
|
149
|
+
|
|
120
150
|
Two system tools are **not** pip-installable and must be present for full
|
|
121
151
|
functionality:
|
|
122
152
|
|
|
123
153
|
1. **Tesseract OCR** — required for every text category (names, SSNs,
|
|
124
154
|
emails, …). Face and plate detection work without it; text detection
|
|
125
155
|
does not.
|
|
126
|
-
- Windows:
|
|
156
|
+
- Windows: `winget install -e --id UB-Mannheim.TesseractOCR`
|
|
157
|
+
(or the installer from https://github.com/UB-Mannheim/tesseract/wiki)
|
|
127
158
|
- Linux: `sudo apt install tesseract-ocr`
|
|
128
159
|
2. **ffmpeg** (ffprobe ships with it) — strongly recommended: audio
|
|
129
160
|
passthrough, H.264 output, and VFR screen-recording normalization all
|
|
130
161
|
depend on it.
|
|
131
|
-
- Windows: `winget install
|
|
162
|
+
- Windows: `winget install -e --id Gyan.FFmpeg`
|
|
132
163
|
- Linux: `sudo apt install ffmpeg`
|
|
133
164
|
|
|
134
165
|
Optional extras:
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""openscrub-setup — one command to finish a fresh install.
|
|
3
|
+
|
|
4
|
+
`pip install OpenScrub` covers every Python dependency, but two system
|
|
5
|
+
tools live outside pip's world: Tesseract (OCR for all text categories)
|
|
6
|
+
and FFmpeg (audio passthrough, H.264 output, VFR normalization). This
|
|
7
|
+
command detects what's missing and installs it for you — with your
|
|
8
|
+
consent — using winget on Windows or apt on Debian/Ubuntu.
|
|
9
|
+
|
|
10
|
+
openscrub-setup interactive: shows status, asks before installing
|
|
11
|
+
openscrub-setup --check report only, change nothing
|
|
12
|
+
openscrub-setup --yes install anything missing without prompting
|
|
13
|
+
openscrub-setup --with-plates also download the recommended
|
|
14
|
+
license-plate model (SHA-256 verified)
|
|
15
|
+
|
|
16
|
+
Why these aren't bundled into the pip package: they're standalone
|
|
17
|
+
programs, not Python libraries — bundling would exceed PyPI size limits,
|
|
18
|
+
freeze security updates, and (for FFmpeg's H.264 encoder) create a GPL
|
|
19
|
+
licensing conflict with OpenScrub's Apache-2.0 license. Installing them
|
|
20
|
+
at the system level keeps them patched by your package manager.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
import os
|
|
25
|
+
import shutil
|
|
26
|
+
import subprocess
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
GREEN, YELLOW, RED, END = "\033[92m", "\033[93m", "\033[91m", "\033[0m"
|
|
31
|
+
if os.name == "nt":
|
|
32
|
+
os.system("") # enable ANSI colors on Windows 10+ consoles
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _ok(msg): print(f" {GREEN}[ok]{END} {msg}")
|
|
36
|
+
def _miss(msg): print(f" {RED}[missing]{END} {msg}")
|
|
37
|
+
def _note(msg): print(f" {YELLOW}[note]{END} {msg}")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def find_tesseract():
|
|
41
|
+
"""Same search the engine performs: PATH, then known Windows installs."""
|
|
42
|
+
p = shutil.which("tesseract")
|
|
43
|
+
if p:
|
|
44
|
+
return p
|
|
45
|
+
if os.name == "nt":
|
|
46
|
+
try:
|
|
47
|
+
from openscrub import WINDOWS_TESSERACT_PATHS
|
|
48
|
+
except Exception:
|
|
49
|
+
WINDOWS_TESSERACT_PATHS = [
|
|
50
|
+
r"C:\Program Files\Tesseract-OCR\tesseract.exe",
|
|
51
|
+
r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
|
|
52
|
+
os.path.expandvars(
|
|
53
|
+
r"%LOCALAPPDATA%\Programs\Tesseract-OCR\tesseract.exe"),
|
|
54
|
+
]
|
|
55
|
+
for c in WINDOWS_TESSERACT_PATHS:
|
|
56
|
+
if os.path.exists(c):
|
|
57
|
+
return c
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def find_ffmpeg():
|
|
62
|
+
return shutil.which("ffmpeg")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _confirm(question, assume_yes):
|
|
66
|
+
if assume_yes:
|
|
67
|
+
return True
|
|
68
|
+
try:
|
|
69
|
+
return input(f"{question} [y/N] ").strip().lower() == "y"
|
|
70
|
+
except EOFError:
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _run(cmd):
|
|
75
|
+
print(f" $ {' '.join(cmd)}")
|
|
76
|
+
try:
|
|
77
|
+
return subprocess.run(cmd).returncode == 0
|
|
78
|
+
except FileNotFoundError:
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def install_windows(pkg_id, assume_yes):
|
|
83
|
+
if not shutil.which("winget"):
|
|
84
|
+
_note("winget not found (it ships with Windows 10 21H2+ / 11).")
|
|
85
|
+
_note(f"Install manually, or run: winget install -e --id {pkg_id}")
|
|
86
|
+
return False
|
|
87
|
+
if not _confirm(f"Install {pkg_id} via winget now?", assume_yes):
|
|
88
|
+
_note(f"Skipped. Manual command: winget install -e --id {pkg_id}")
|
|
89
|
+
return False
|
|
90
|
+
return _run(["winget", "install", "-e", "--id", pkg_id,
|
|
91
|
+
"--accept-source-agreements", "--accept-package-agreements"])
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def install_apt(packages, assume_yes):
|
|
95
|
+
if not shutil.which("apt-get"):
|
|
96
|
+
_note("No apt available — install via your distro's package manager: "
|
|
97
|
+
+ " ".join(packages))
|
|
98
|
+
return False
|
|
99
|
+
if not _confirm(f"Run 'sudo apt-get install -y {' '.join(packages)}' now?",
|
|
100
|
+
assume_yes):
|
|
101
|
+
_note("Skipped. Manual command: sudo apt-get install -y "
|
|
102
|
+
+ " ".join(packages))
|
|
103
|
+
return False
|
|
104
|
+
return _run(["sudo", "apt-get", "install", "-y"] + packages)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def setup_plates(assume_yes, check_only):
|
|
108
|
+
try:
|
|
109
|
+
import openscrub
|
|
110
|
+
except ImportError:
|
|
111
|
+
_miss("openscrub package not importable — is it installed?")
|
|
112
|
+
return
|
|
113
|
+
models = openscrub.load_plate_registry()
|
|
114
|
+
here = os.path.dirname(os.path.abspath(openscrub.__file__))
|
|
115
|
+
installed = [m["id"] for m in models if os.path.exists(
|
|
116
|
+
os.path.join(here, "models", f"{m['id']}.onnx"))]
|
|
117
|
+
if installed:
|
|
118
|
+
_ok(f"license-plate model installed: {installed[0]}")
|
|
119
|
+
return
|
|
120
|
+
rec = next((m for m in models if m.get("recommended")), None)
|
|
121
|
+
if rec is None:
|
|
122
|
+
_note("no recommended plate model in registry; see PLATES.md")
|
|
123
|
+
return
|
|
124
|
+
_miss(f"license-plate model (optional) — recommended: {rec['label']} "
|
|
125
|
+
f"[{rec.get('license')}]")
|
|
126
|
+
if check_only:
|
|
127
|
+
return
|
|
128
|
+
if not _confirm("Download it now (SHA-256 verified)?", assume_yes):
|
|
129
|
+
_note("Skipped. The web UI's plate panel can download it later.")
|
|
130
|
+
return
|
|
131
|
+
try:
|
|
132
|
+
path = openscrub.download_plate_model(rec)
|
|
133
|
+
_ok(f"plate model saved: {path}")
|
|
134
|
+
except Exception as e:
|
|
135
|
+
_miss(f"plate model download failed: {e}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def main(argv=None):
|
|
139
|
+
ap = argparse.ArgumentParser(
|
|
140
|
+
prog="openscrub-setup",
|
|
141
|
+
description="Detect and install OpenScrub's system prerequisites "
|
|
142
|
+
"(Tesseract OCR, FFmpeg).")
|
|
143
|
+
ap.add_argument("--check", action="store_true",
|
|
144
|
+
help="report status only; install nothing")
|
|
145
|
+
ap.add_argument("--yes", "-y", action="store_true",
|
|
146
|
+
help="install anything missing without prompting")
|
|
147
|
+
ap.add_argument("--with-plates", action="store_true",
|
|
148
|
+
help="also offer the optional license-plate model")
|
|
149
|
+
args = ap.parse_args(argv)
|
|
150
|
+
|
|
151
|
+
print("OpenScrub setup — system prerequisites")
|
|
152
|
+
print("=" * 46)
|
|
153
|
+
|
|
154
|
+
changed = False
|
|
155
|
+
|
|
156
|
+
# Python-side sanity (pip already handled these; verify imports work)
|
|
157
|
+
try:
|
|
158
|
+
import cv2, flask # noqa: F401
|
|
159
|
+
_ok("python dependencies (opencv, flask, ...)")
|
|
160
|
+
except ImportError as e:
|
|
161
|
+
_miss(f"python dependency broken: {e} — try: pip install --force-reinstall OpenScrub")
|
|
162
|
+
|
|
163
|
+
# Tesseract
|
|
164
|
+
t = find_tesseract()
|
|
165
|
+
if t:
|
|
166
|
+
_ok(f"Tesseract OCR: {t}")
|
|
167
|
+
else:
|
|
168
|
+
_miss("Tesseract OCR — required for ALL text categories "
|
|
169
|
+
"(names, SSNs, addresses, ...)")
|
|
170
|
+
if not args.check:
|
|
171
|
+
if os.name == "nt":
|
|
172
|
+
changed |= install_windows("UB-Mannheim.TesseractOCR", args.yes)
|
|
173
|
+
else:
|
|
174
|
+
changed |= install_apt(["tesseract-ocr"], args.yes)
|
|
175
|
+
|
|
176
|
+
# FFmpeg
|
|
177
|
+
f = find_ffmpeg()
|
|
178
|
+
if f:
|
|
179
|
+
_ok(f"FFmpeg: {f}")
|
|
180
|
+
else:
|
|
181
|
+
_miss("FFmpeg — needed for audio passthrough, H.264 output, and "
|
|
182
|
+
"screen-recording (VFR) normalization")
|
|
183
|
+
if not args.check:
|
|
184
|
+
if os.name == "nt":
|
|
185
|
+
changed |= install_windows("Gyan.FFmpeg", args.yes)
|
|
186
|
+
else:
|
|
187
|
+
changed |= install_apt(["ffmpeg"], args.yes)
|
|
188
|
+
|
|
189
|
+
# Optional: spaCy NER model
|
|
190
|
+
try:
|
|
191
|
+
import spacy
|
|
192
|
+
try:
|
|
193
|
+
spacy.load("en_core_web_sm")
|
|
194
|
+
_ok("spaCy NER model (en_core_web_sm)")
|
|
195
|
+
except OSError:
|
|
196
|
+
_miss("spaCy is installed but its model isn't")
|
|
197
|
+
if not args.check and _confirm(
|
|
198
|
+
"Download en_core_web_sm now?", args.yes):
|
|
199
|
+
_run([sys.executable, "-m", "spacy", "download",
|
|
200
|
+
"en_core_web_sm"])
|
|
201
|
+
except ImportError:
|
|
202
|
+
_note('name detection uses heuristics; for better accuracy: '
|
|
203
|
+
'pip install "OpenScrub[ner]" then re-run openscrub-setup')
|
|
204
|
+
|
|
205
|
+
# Optional: plate model
|
|
206
|
+
if args.with_plates:
|
|
207
|
+
setup_plates(args.yes, args.check)
|
|
208
|
+
|
|
209
|
+
print("=" * 46)
|
|
210
|
+
if changed and os.name == "nt":
|
|
211
|
+
_note("winget installs update PATH for NEW terminals only:")
|
|
212
|
+
_note("close this window, open a fresh one, then run: openscrub-web")
|
|
213
|
+
else:
|
|
214
|
+
print("Done. Start the web app with: openscrub-web")
|
|
215
|
+
return 0
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
if __name__ == "__main__":
|
|
219
|
+
sys.exit(main())
|
|
@@ -62,6 +62,7 @@ Issues = "https://github.com/austinmabry/OpenScrub/issues"
|
|
|
62
62
|
# `openscrub` runs the CLI engine; `openscrub-web` starts the web UI.
|
|
63
63
|
openscrub = "openscrub:main"
|
|
64
64
|
openscrub-web = "openscrub_web:main"
|
|
65
|
+
openscrub-setup = "openscrub_setup:main"
|
|
65
66
|
|
|
66
67
|
[tool.hatch.version]
|
|
67
68
|
# Single source of truth: the VERSION = "x.y.z" line in openscrub.py. A release
|
|
@@ -77,12 +78,14 @@ include = [
|
|
|
77
78
|
"openscrub.py",
|
|
78
79
|
"openscrub_web.py",
|
|
79
80
|
"zones_ui.py",
|
|
81
|
+
"openscrub_setup.py",
|
|
80
82
|
]
|
|
81
83
|
|
|
82
84
|
[tool.hatch.build.targets.sdist]
|
|
83
85
|
include = [
|
|
84
86
|
"plate_models.json",
|
|
85
87
|
"openscrub.py",
|
|
88
|
+
"openscrub_setup.py",
|
|
86
89
|
"openscrub_web.py",
|
|
87
90
|
"zones_ui.py",
|
|
88
91
|
"install.py",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|