Files
Video-Processing-Scripts/skill/Create-PillarBox.md
T

255 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Create-PillarBox.ps1
Creates a pillar-boxed (16:9) video file from a source video using ffmpeg, with selectable side-bar effects ranging from solid colors to blurred backgrounds derived from the video itself.
<video controls width="100%"><source src="../../../images/Create-PillarBox.mp4" type="video/mp4"></video>
*The video above was generated using the [Compare-Videos.ps1](Compare-Videos.md) script.*
Each video shows the same source material with a different effect as follows:
| Left side | Right side |
| :-------: | :--------: |
| black | standard |
| gaussian | dark |
## Synopsis
Wraps the source video in a 16:9 frame so it can be played on standard widescreen displays without stretching:
- **Portrait-like sources** (e.g. 9:16, 1:1) get **vertical** bars on the left and right (true pillar-boxing).
- **Sources wider than 16:9** get **horizontal** bars on the top and bottom (letter-boxing).
- **Square (1:1) sources with `-Vertical`** are wrapped in a **9:16 portrait** frame instead, with **horizontal** bars on the top and bottom — for vertical platforms such as Shorts, Reels, or TikTok.
- The source video is scaled to fit the chosen output frame while preserving its aspect ratio, then centered.
- The bars themselves can be solid black/white or filled with a stylised, blurred copy of the video.
## Parameters
- **`-Video`** (required): Path to input video file (`.mp4` extension added if missing)
- **`-Target`** (optional): Path to output video file (`.mp4` extension added if missing). If omitted, defaults to the source filename with the `-Effect` value (lowercased) appended after a dash and saved alongside the source — e.g. `video.mp4` + `-Effect Black` produces `video-black.mp4` next to the source. When `-Vertical` is used, `-vertical` is appended after the effect, just before the extension — e.g. `video-black-vertical.mp4`.
- **`-Effect`** (required): Visual treatment of the side bars. One of `black`, `white`, `silver`, `gray`, `charcoal`, `standard`, `dark`, `gaussian`, or `color:RRGGBB` for an arbitrary hex color (case-insensitive on both the keyword and the hex value). See [Effects](#effects) for a detailed description.
- **`-Vertical`**: Only valid when the source video is square (1:1). Produces a **9:16 portrait** output with the bars on the top and bottom instead of the default 16:9 landscape output with bars on the sides. All other parameters (`-Effect`, `-Size`, `-FPS`, `-Audio`, `-NoAudio`, `-CRF`) behave identically, just applied to a portrait frame. When `-Target` is omitted, the auto-generated filename ends with `-vertical` (e.g. `video-black-vertical.mp4`). Using it with a non-square source throws an error.
- **`-Size`** (optional): Output video size. Possible values: `480p`, `720p`, `1080p`, `HD`, `1440p`, `2K`, `2160p`, `4K`, or custom `width:height`. If not specified, the smallest standard 16:9 size that fully contains the source is chosen automatically. With `-Vertical`, named presets are transposed to portrait (`1080p` → `1080x1920`, `4K` → `2160x3840`); a custom `width:height` is always used exactly as given.
- **`-FPS`** (optional): Frames per second for the output video. Uses the input video's FPS if not specified.
- **`-NoAudio`**: Exclude audio from the output video. Cannot be combined with `-Audio`.
- **`-Audio`** (optional): Path to an alternate audio file to use for the target video. When specified, this audio replaces the source video's audio (re-encoded as AAC 192k, trimmed to the shortest stream).
- **`-CRF`** (optional): Constant Rate Factor for video encoding (`0`-`51`, lower is better quality). When specified, overrides both the source video bitrate and the default `-crf 8` fallback.
## Effects
The `-Effect` parameter controls what fills the area around the source video inside the 16:9 frame. The eight effects fall into two groups:
### Solid colors
These produce flat, uniform bars. They are the cheapest to encode and are best when you want the viewer's eye to ignore the bars completely.
- **`black`** — Solid black bars (`#000000`). Standard television "matted" look. Maximum contrast against the picture; effectively invisible on OLED/dark-room playback.
- **`white`** — Solid white bars (`#FFFFFF`). High-key look suitable for product/light backgrounds, slideshows, and graphic-design contexts.
- **`silver`** — Solid silver bars (`#C0C0C0`). Light neutral gray; softer than `white` while staying bright. Useful when pure white feels too aggressive against the picture.
- **`gray`** — Solid mid gray bars (`#808080`). 50% luminance neutral; sits between dark and bright content without leaning either way. A safe default for mixed/unknown content brightness.
- **`charcoal`** — Solid charcoal bars (`#36454F`). Very dark, slightly blue-tinted gray. Almost as unobtrusive as `black` on OLED but with a more refined look in lit rooms or on LCD screens where pure black can look gray anyway.
- **`color:RRGGBB`** — Solid bars in any hex color you specify. The six hex digits are case-insensitive, so `color:FFFF00`, `color:ffff00`, and `color:FfFf00` all produce the same bright yellow bars. Examples: `color:FFFF00` (yellow), `color:1E90FF` (dodger blue), `color:8B0000` (dark red). Use this when none of the named presets match your branding or scene palette.
### Blurred-background ("ambient") effects
These three effects all use the same fundamental technique: the source video is duplicated; one copy is **scaled to *fill* the 16:9 frame** (so the picture overflows the visible area in one dimension and is cropped) and then **blurred** to become the background. The original, un-blurred picture is then **centered on top** at its true aspect ratio. The result is that the bars are not empty space — they are a soft, motion-synchronised continuation of the video, similar to the "ambient backlight" treatment used on Apple TV and YouTube.
The three effects differ only in **how the background is treated** before the original picture is laid on top:
- **`standard`** — *Soft, neutral, slightly zoomed.*
- **Scaling**: the background copy is scaled to roughly **110%** of the output frame and then cropped, giving the bars a subtle "pushed beyond the edges" feel rather than a flat fit. This avoids hard edges where the cropped border would otherwise sit exactly at the frame edge, and adds a barely-noticeable parallax depth.
- **Blur**: a fast **box blur** of moderate radius. Box blur is computationally cheap; visually the background becomes recognisable smears of color and motion, but with slight box-shaped artefacts on sharp edges if you look closely.
- **Brightness/color**: unchanged. The bars therefore retain the source's full brightness and saturation.
- **What you'll see**: side bars filled with soft, recognisable shapes from the picture — sky color, skin tones, scenery — that move and shift in sync with the video. The center picture pops because it is sharp against a softer surround, but the overall image stays bright.
- **Best for**: most general-purpose playback. Music videos, vlogs, product demos.
- **`dark`** — *Same blur as `standard`, but dimmed.*
- **Scaling**: background fills the frame exactly (no extra zoom).
- **Blur**: same box blur as `standard`.
- **Brightness/color**: brightness is reduced (~ -25%) and saturation is reduced to ~80%, producing a darker, more muted background. The center video is **not** affected — only the bars.
- **What you'll see**: side bars in the same shapes and motion as `standard`, but visibly darker and less colorful, so the eye is drawn more strongly to the original picture in the middle. Good for cinematic or moody content where the bars should "sink into" the screen.
- **Best for**: film clips, dramatic content, dark-room viewing, or any time `standard` feels too bright/distracting.
- **`gaussian`** — *Smooth, premium-looking blur.*
- **Scaling**: background fills the frame exactly (no extra zoom).
- **Blur**: a **Gaussian blur** with a large sigma (~30). Gaussian blur is much more computationally expensive than box blur, but it produces a smoother fall-off with no visible artefacts at any zoom level. Sharp features in the original picture become unrecognisable color clouds.
- **Brightness/color**: unchanged.
- **What you'll see**: side bars that look like a smooth, abstract color wash that clearly comes from the video but where you can no longer make out shapes — only ambient color. Closest to the "broadcast TV" pillar-box look used by streaming services.
- **Best for**: professional/broadcast deliverables, finished cuts where rendering time is acceptable, and any content where the `standard` blur looks too "blocky".
### Quick comparison
| Effect | Background source | Blur type | Brightness | Use when… |
| --- | --- | --- | --- | --- |
| `black` | none (solid `#000000`) | — | — | You want the bars to disappear visually. |
| `white` | none (solid `#FFFFFF`) | — | — | You want a bright, graphic-design feel. |
| `silver` | none (solid `#C0C0C0`) | — | — | You want a light bar that's softer than pure white. |
| `gray` | none (solid `#808080`) | — | — | Neutral 50% gray that doesn't lean light or dark. |
| `charcoal` | none (solid `#36454F`) | — | — | A refined near-black that holds up on LCD/lit rooms. |
| `color:RRGGBB` | none (solid custom hex, case-insensitive) | — | — | You need an arbitrary brand or accent color, e.g. `color:FFFF00`. |
| `standard` | video, ~110% zoom | box blur (fast) | normal | General use; you want context in the bars. |
| `dark` | video | box blur (fast) | dimmed & desaturated | Cinematic look; you want focus on the picture. |
| `gaussian` | video | Gaussian (slow, smooth) | normal | Premium/broadcast look; rendering time is OK. |
## Size selection
When `-Size` is omitted, the script picks the **smallest standard 16:9 preset that holds the source's bounding box** — i.e. the preset's long side must be at least the source's long side **and** its short side at least the source's short side:
- A 1080×1920 portrait source → `1920x1080` (1080p) — vertical bars on either side.
- A 720×1280 portrait source → `1280x720` (720p) — vertical bars on either side.
- A 1080×1080 square source → `1920x1080` (1080p) — vertical bars on either side, source kept at its native 1080×1080.
- A 512×512 square source → `1280x720` (720p) — the 480p frame (854×480) is too short to hold 512 px.
- A 2560×1080 ultra-wide source → `2560x1440` (1440p) — horizontal bars top and bottom.
- A source too large for any preset → an even-rounded custom 16:9 frame that holds the source's bounding box (e.g. 4000×4000 → `7112x4002`).
Checking both sides matters most for square-ish sources: a 1080×1080 source would fit *inside* a 1280×720 frame only by being shrunk to 720×720, so the next preset up is used instead and no resolution is lost.
You can always force a specific size with `-Size 1080p`, `-Size 4K`, or a custom `-Size 1920:1080`.
### With `-Vertical` (square sources)
The same logic applies to a transposed 9:16 frame:
- A 1080×1080 square source → `1080x1920` (1080p transposed) — horizontal bars top and bottom, source kept at 1080×1080.
- A 512×512 square source → `720x1280` (720p transposed) — horizontal bars top and bottom.
- `-Size 1080p` → `1080x1920`, `-Size 720p` → `720x1280`, `-Size 4K` → `2160x3840`.
- A custom `-Size 1080:1920` is used verbatim (no transposition).
## Examples
**Auto-named output (no `-Target` specified):**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Effect black
# Produces video-black.mp4 next to video.mp4
```
```powershell
.\Create-PillarBox.ps1 -Video vlog.mp4 -Effect Gaussian
# Produces vlog-gaussian.mp4 (effect name is always lowercased)
```
**Pillar-box a portrait video with black bars at 1080p:**
```powershell
.\Create-PillarBox.ps1 -Video portrait.mp4 -Target portrait_16x9.mp4 -Effect black -Size 1080p
```
**Turn a square video into a 9:16 vertical video (bars on top and bottom):**
```powershell
.\Create-PillarBox.ps1 -Video square.mp4 -Effect black -Vertical -Size 1080p
# Produces square-black-vertical.mp4 at 1080x1920 with black bars above and below the picture
```
```powershell
.\Create-PillarBox.ps1 -Video square.mp4 -Target reel.mp4 -Effect gaussian -Vertical
# Blurred ambient bars on top and bottom; size derived from the source (1080x1080 -> 1080x1920)
```
**Auto-size, white bars:**
```powershell
.\Create-PillarBox.ps1 -Video clip.mp4 -Target clip_white.mp4 -Effect white
# Output size derived from source dimensions
```
**Custom yellow brand color (auto-named output):**
```powershell
.\Create-PillarBox.ps1 -Video clip.mp4 -Effect color:FFFF00
# Produces clip-color-ffff00.mp4 with solid yellow side bars.
# The hex value is case-insensitive: -Effect color:ffff00 works identically.
```
**Soft ambient blur background (general purpose):**
```powershell
.\Create-PillarBox.ps1 -Video vlog.mp4 -Target vlog_16x9.mp4 -Effect standard -Size 1080p
```
**Cinematic darkened blur:**
```powershell
.\Create-PillarBox.ps1 -Video scene.mp4 -Target scene_16x9.mp4 -Effect dark -Size 1080p
```
**Broadcast-quality Gaussian blur:**
```powershell
.\Create-PillarBox.ps1 -Video music_video.mp4 -Target broadcast.mp4 -Effect gaussian -Size 1080p
```
**Force 4K output:**
```powershell
.\Create-PillarBox.ps1 -Video clip.mp4 -Target clip_4k.mp4 -Effect gaussian -Size 4K
```
**Custom resolution:**
```powershell
.\Create-PillarBox.ps1 -Video clip.mp4 -Target clip.mp4 -Effect black -Size 1920:1080
```
**Replace audio with a soundtrack:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target output.mp4 -Effect standard -Audio soundtrack.mp3
# Source audio is dropped; soundtrack.mp3 replaces it (AAC 192k, trimmed to shortest stream)
```
**Strip audio entirely:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target silent.mp4 -Effect black -NoAudio
```
**Force a specific FPS:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target output.mp4 -Effect standard -FPS 30
```
**Override quality with CRF:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target output.mp4 -Effect gaussian -CRF 18
# CRF 18 instead of default CRF 8 / source bitrate
```
## Safe Execution
This script supports `-WhatIf` and `-Confirm` for safe execution:
- **`-WhatIf`**: Simulate the operation without creating files. Prints the full ffmpeg command that would have been run.
- **`-Confirm`**: Prompt for confirmation before each state-changing operation.
**Simulate without making changes:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target output.mp4 -Effect standard -WhatIf
```
**Prompt before creating files:**
```powershell
.\Create-PillarBox.ps1 -Video video.mp4 -Target output.mp4 -Effect gaussian -Confirm
```
## Quality Preservation
- **Codec**: output is encoded with `libx264` (H.264) using `yuv420p` and the `slow` preset.
- **Bitrate**: priority is `-CRF` (when specified) → source video bitrate (via `-b:v`) → fallback `-crf 8` (near-lossless).
- **Audio**: when present and not replaced/excluded, audio is **stream-copied** with no quality loss. When `-Audio` is used, the replacement audio is re-encoded to AAC 192k.
- **Aspect ratio**: source content is never stretched — only scaled proportionally and padded.
## Notes
- Requires `ffmpeg` and `ffprobe` on the Windows `PATH`.
- Output dimensions are forced to even pixels for `yuv420p` compatibility.
- The `gaussian` effect is noticeably slower to encode than `standard`/`dark`; expect a real-time-or-slower rendering speed at 1080p on typical CPUs.
- The `standard` and `dark` effects use box blur for speed; if you see visible block-like edges in the bars, switch to `gaussian` for a smoother result.
- When the source aspect ratio is already 16:9, all five effects produce a visually identical output (the source fills the frame; the bars have zero size).
- `-Vertical` is rejected for non-square sources: a 16:9 or 9:16 source already has an unambiguous bar orientation, so the switch would only be a source of confusion.