|
| 1 | +# Deployment |
| 2 | + |
| 3 | +The deployment folder contains Windows-oriented packaging and batch-processing helpers. The scripts use repo-relative defaults and can be run from any clone path. |
| 4 | + |
| 5 | +## Scripts |
| 6 | + |
| 7 | +- `Scripts\Publish-Core.ps1` publishes the .NET app as a self-contained Windows x64 single-file executable. |
| 8 | +- `Scripts\Stage-Payload.ps1` stages the published executable, configs, and starter dictionary under `Deployment\artifacts\staging\LocalProfanityCensor`. |
| 9 | +- `Scripts\Invoke-CensorMediaBatch.ps1` processes a media folder safely with shared state, lock files, retries, local work folders, and a holding output folder. |
| 10 | +- `Scripts\Setup-AI.ps1` creates a Python virtual environment with `faster-whisper`, `demucs`, and optional replacement-mode packages. |
| 11 | +- `Scripts\Build-Msi.ps1` builds the WiX installer from the staged payload. |
| 12 | + |
| 13 | +## Safe Batch Mode |
| 14 | + |
| 15 | +Start with holding mode. It leaves source files untouched and writes cleaned MKV files to a separate folder. MKV is the target output container because it can embed the original media streams, the clean censored audio track, and generated subtitle tracks together. |
| 16 | + |
| 17 | +```powershell |
| 18 | +pwsh .\Deployment\Scripts\Publish-Core.ps1 |
| 19 | +pwsh .\Deployment\Scripts\Stage-Payload.ps1 |
| 20 | +
|
| 21 | +pwsh .\Deployment\Scripts\Invoke-CensorMediaBatch.ps1 ` |
| 22 | + -InputRoot "D:\Media\Incoming" ` |
| 23 | + -HoldingRoot "D:\Media\CensoredHolding" ` |
| 24 | + -MaxFilesPerRun 1 |
| 25 | +``` |
| 26 | + |
| 27 | +Only use `-ReplaceOriginal` after you have validated output quality on your own media. Replacement mode archives the original to `-ArchiveRoot` before moving the cleaned MKV into the source folder. |
| 28 | + |
| 29 | +## AI Runtime |
| 30 | + |
| 31 | +The batch runner uses `CENSOR_MEDIA_PYTHON` or `-MediaPythonPath` to locate a Python environment with the AI packages installed. It uses `CENSOR_MEDIA_HF_HOME` or `-HuggingFaceCacheRoot` for the Hugging Face model cache. |
| 32 | + |
| 33 | +Model weights are not bundled in the installer. See `models\README.md` and `scripts\Download-FasterWhisperModel.ps1`. |
| 34 | + |
| 35 | +For the normal mute/beep/duck path, run setup with `-SkipOpenVoice`. Only omit that switch when you are intentionally testing prototype replacement audio. |
| 36 | + |
| 37 | +## State And Locks |
| 38 | + |
| 39 | +By default, state is stored under `<HoldingRoot>\.state`. Each source-relative media file gets its own JSON state file and lock file so multiple workers can safely share the same input and holding folders. |
| 40 | + |
| 41 | +The runner skips completed jobs when the source file size and timestamp still match. Failed jobs retry according to `-MaxAttempts` and `-RetryDelayMinutes`. |
| 42 | + |
| 43 | +## Output Behavior |
| 44 | + |
| 45 | +Default behavior is safe for testing: |
| 46 | + |
| 47 | +- Originals stay in place. |
| 48 | +- Cleaned output goes to the holding folder. |
| 49 | +- Original audio remains the default audio track. |
| 50 | +- Existing original subtitles remain default. |
| 51 | +- If no retained normal subtitle exists, a generated normal subtitle can be embedded into the output MKV. |
| 52 | +- A generated censored subtitle can be embedded as a selectable clean subtitle option. |
| 53 | +- Censored audio and generated subtitles are added as selectable options. |
| 54 | +- Files with no detected profanity and no subtitle changes can be marked complete without writing a new MKV. |
| 55 | + |
| 56 | +## Useful Parameters |
| 57 | + |
| 58 | +- `-InputRoot`: source media folder to scan recursively. |
| 59 | +- `-HoldingRoot`: holding folder for completed MKV outputs in safe mode. |
| 60 | +- `-StateRoot`: shared JSON state and lock folder. Defaults to `<HoldingRoot>\.state`. |
| 61 | +- `-ArchiveRoot`: original-file archive folder used by `-ReplaceOriginal`. |
| 62 | +- `-LocalWorkRoot`: machine-local working directory. Defaults to `%TEMP%\LocalProfanityCensorBatch`. |
| 63 | +- `-MaxFilesPerRun`: limit for one pass. `0` means no explicit limit. |
| 64 | +- `-Repeat`: keep scanning after each pass. |
| 65 | +- `-DryRun`: pass `--dry-run` to the censor process and do not move a final output. |
| 66 | +- `-KeepWork`: preserve local work folders and pass `--keep-work` to the censor process. |
| 67 | +- `-RunSetupAI`: run `Scripts\Setup-AI.ps1` before scanning. |
| 68 | +- `-MediaPythonPath`: explicitly set the Python runtime used by ASR/Demucs. |
| 69 | +- `-HuggingFaceCacheRoot`: explicitly set the Hugging Face cache root used by ASR models. |
0 commit comments