# Create-ShortClip.ps1 Creates a short clip video file from a 16:9 video file with dynamic cropping, padding, and optional overlay. ## Synopsis Transforms landscape videos into portrait (9:16) or square (1:1) format clips by: 1. Extracting frames with optional vertical padding 2. Applying horizontal cropping with smooth transitions between keyframes 3. Optionally overlaying a PNG image with transparency 4. Encoding the final video with preserved quality settings The output filename is automatically generated by appending `-ShortClip` before the file extension. ## Parameters - **`-Video`** (required): Path to input video file (absolute or relative) - **`-Plan`** (required): Path to INI plan file defining clip specifications and cropping behavior - **`-Images`** (optional): Path to output PNG images file pattern. If not provided, frames are saved in subdirectory 'Frames' with video filename and 4-digit frame numbers - **`-Keep`**: Preserve temporary and frames directories after processing - **`-Render`**: Skip frame extraction/cropping and only create video from existing frames - **`-Color`** (optional): Override INI file Color value for padding color name or RGB value (default: `black`) - Named colors: `black`, `white`, `red`, `blue`, etc. - Hex format: `#RRGGBB` (e.g., `#1a1a1a`) - FFmpeg format: `0xRRGGBB` - **`-Overlay`** (optional): Override INI file Overlay value for path to PNG file with transparency to overlay on each cropped frame - **`-Smoothing`** (optional): Override INI file Smoothing value (`None`, `Up`, `Center`, `Down`) - **`-Speed`** (optional): Override INI file Speed value (minimum: 1) - **`-WhatIf`**: Simulate the operation without actually creating files. Shows what would be done. - **`-Confirm`**: Prompt for confirmation before each state-changing operation (frame extraction, cropping, video creation). ## Plan File Format (INI) ### [Clip] Section Defines output video specifications: - **`Format`**: Output aspect ratio (default: `Portrait`) - `Portrait`: 9:16 aspect ratio - `Square`: 1:1 aspect ratio - **`Height`**: Vertical height in pixels (default: `1920`). Width is computed based on format - **`Padding`**: Vertical padding position when input height < output height (default: `Center`) - `Top`: All padding at top - `Bottom`: All padding at bottom - `Center`: Padding split evenly top and bottom - `None`: No padding; scale video to fill output height and crop horizontally to match format width - **'Color'**: Padding color name or RGB value (default: `black`) - Named colors: `black`, `white`, `red`, `blue`, etc. - Hex format: `#RRGGBB` (e.g., `#1a1a1a`) - FFmpeg format: `0xRRGGBB` - **`Overlay`**: Path to PNG file with transparency to overlay on each cropped frame - **`Audio`**: Copy audio from input video (default: `Yes`) - `Yes`: Include audio - `No`: Video only - **`Position`**: Reference point for numeric cropping offset values (default: `Center`) - `Left`: Numeric values represent absolute pixel offset from left edge - `Center`: Numeric values represent pixel offset from center (value - output_width/2) - `Right`: Numeric values represent pixel offset from right edge (value - output_width) - **`Smoothing`**: Mode for adjusting cropping transition length to control speed (default: `None`) - `None`: No smoothing, use calculated interpolation as-is - `Up`: Extend transition by incrementing upper frame until speed limit is met - `Center`: Extend transition by adjusting frame closest to center until speed limit is met - `Down`: Extend transition by decrementing lower frame until speed limit is met - **`Speed`**: Maximum cropping transition speed in pixels per frame (default: `10`, minimum: `1`) - Controls how fast the crop position can change between frames - If interpolated speed exceeds this value, smoothing extends the transition ### [Cropping] Section Defines horizontal cropping keyframes with automatic interpolation: **Format:** `frame_number=position` **Position values:** Each keyframe value is resolved to a **Left offset**: the X coordinate (in input-frame pixels) of the left edge of the crop window. The crop window has width `output_width` (or the intermediate width when downscaling). - `Left`: Crop from left edge (Left offset = 0) - `Center`: Crop from center (Left offset = (input_width - output_width) / 2) - `Right`: Crop from right edge (Left offset = input_width - output_width) - `number`: Absolute pixel offset, interpreted according to the `Position` setting in the `[Clip]` section (see `Position`). Result is clamped to `[0, input_width - output_width]`. From the Left offset, the script also derives: - **Center offset** = Left offset + output_width / 2 (X coordinate of the crop window's center) - **Right offset** = Left offset + output_width (X coordinate of the crop window's right edge) All three values are printed in the cropping offsets table at runtime to help diagnose framing. **Behavior:** - Frame numbers must be in ascending order - Intermediate frames are automatically interpolated with smooth transitions - Frames after the last keyframe use the last defined offset - If section is empty or missing, defaults to `0=Center` **Example:** ```ini [Cropping] 0=Left 84=Left 85=Right 140=Right 159=Left ``` This creates: - Frames 0-84: Crop from left - Frame 84→85: Quick transition from left to right - Frames 85-140: Crop from right - Frames 140-159: Smooth pan from right to left - Frames 159+: Crop from left ## Examples **Basic portrait clip:** ```powershell .\Create-ShortClip.ps1 -Video input.mp4 -Plan plan.ini # Creates: input-ShortClip.mp4 (9:16 format) ``` **Square format with white padding:** ```ini # plan.ini [Clip] Format=Square Height=1920 Padding=Center Audio=Yes [Cropping] 0=Center ``` ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Color white ``` **With overlay graphic:** ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Overlay border.png # Applies border.png (with transparency) over each cropped frame ``` **No padding (scale to fill height):** ```ini # plan.ini [Clip] Format=Portrait Height=1920 Padding=None ``` ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini # Scales video to fill 1920px height, crops horizontally to 1080px width # No vertical padding bars added ``` **Keep frames for inspection:** ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Keep # Preserves Frames/ directory for review ``` **Re-render with different encoding:** ```powershell # First run: extract and crop frames .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Keep # Modify encoding settings in script, then re-render .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Render # Skips extraction/cropping, only creates video from existing frames ``` **Custom output location:** ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Images "C:\Output\frames\frame-%04d.png" ``` **Custom padding color:** ```powershell # Dark gray padding .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Color #1a1a1a # Navy blue padding .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Color navy ``` **Position parameter with numeric values:** ```ini # plan.ini - Input: 1920x1088, Output: 1080x1920 [Clip] Format=Portrait Position=Center [Cropping] 0=960 ``` With `Position=Center` and output width 1080: - Numeric value 960 is adjusted: 960 - (1080/2) = 960 - 540 = 420 - Final offset: 420 pixels from left edge (centered in 1920px input) With `Position=Left`: - Numeric value 960 is used directly: 960 pixels from left edge With `Position=Right` and output width 1080: - Numeric value 960 is adjusted: 960 - 1080 = -120 → clamped to 0 **Simulate without making changes:** ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -WhatIf # Displays what would be done (cropping offsets, frame extraction, video creation) without actually processing ``` **Prompt before each operation:** ```powershell .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Confirm # Will prompt for confirmation before frame extraction, each cropping operation, and video creation ``` **Smoothing fast transitions:** ```ini # plan.ini - Control transition speed [Clip] Format=Portrait Smoothing=Center Speed=5 [Cropping] 0=Left 10=Right ``` Without smoothing, frames 0-10 would transition at 84 pixels/frame (too fast). With `Smoothing=Center` and `Speed=5`, the transition extends to more frames, keeping speed ≤ 5 pixels/frame. **Override INI settings via command-line:** ```powershell # Override smoothing settings from command line .\Create-ShortClip.ps1 -Video video.mp4 -Plan plan.ini -Smoothing Up -Speed 3 # Uses Up smoothing and speed limit of 3, ignoring INI file values ``` ## Cropping Interpolation Example Input: 1920x1088 video → Output: 1080x1920 (Portrait) ```ini [Cropping] 0=Left 10=200 50=Center 91=Right ``` **Calculated Left offsets:** - **Frame 0**: 0 (Left) - **Frames 1-9**: Linear interpolation from 0 to 200 - Frame 1: 20, Frame 2: 40, ..., Frame 9: 180 - **Frame 10**: 200 - **Frames 11-49**: Linear interpolation from 200 to 420 (Center = (1920-1080)/2) - Frame 11: 194.5, Frame 12: 189, ..., Frame 49: 425.5 - **Frame 50**: 420 (Center) - **Frames 51-90**: Linear interpolation from 420 to 840 (Right = 1920-1080) - Frame 51: 430.5, Frame 52: 441, ..., Frame 90: 829.5 - **Frame 91**: 840 (Right) - **Frames 92+**: 840 (last known value) All fractional values are rounded to nearest pixel. **Runtime output** prints Left, Center (= Left + 540), and Right (= Left + 1080) offsets only at frames where the Left offset changes: ```text Frame Left Center Right ---------------------------------------- 0 0 540 1080 1 20 560 1100 2 40 580 1120 ... 10 200 740 1280 ... 50 420 960 1500 ... 91 840 1380 1920 ``` ## Quality Preservation The script automatically preserves video quality from the input: - Detects and uses same codec (H.264 → libx264, H.265 → libx265) - Preserves pixel format - Uses input bitrate when available - Falls back to CRF 8 (near-lossless) for VBR/CRF-encoded inputs - Audio encoded as AAC at 192k bitrate ## Processing Workflow 1. **Validation**: Check video and plan file existence 2. **Analysis**: Extract video metadata (dimensions, frame count, FPS, codec) 3. **Offset Calculation**: Compute per-frame cropping offsets with interpolation and optional smoothing 4. **Frame Extraction**: Extract all frames with vertical padding applied 5. **Cropping**: Apply horizontal crop to each frame based on computed offsets 6. **Overlay** (optional): Apply PNG overlay during cropping step 7. **Encoding**: Create output video from processed frames 8. **Cleanup**: Remove temporary directories (unless `-Keep` specified) > With `-WhatIf`, the workflow shows all planned operations without executing them. ## Existing Files and Folders - **Default `-Images`** (the `Frames` folder next to the video): files directly in `Frames` are deleted before extraction. Subfolders are not touched. With `-Render`, nothing is deleted, because the existing frames are the input. - **Explicit `-Images`**: existing frames that match the `-Images` pattern are deleted before extraction. The `Frames` folder is not used or deleted. - **Output video**: an existing file at the output path is overwritten. - **Temporary extraction directory** (in the system temporary folder): always removed when the run ends. - **`Frames` folder** (default `-Images` only): removed after the video is created, unless `-Keep` is given. ## Notes - Requires `ffmpeg` and `ffprobe` in system PATH - Frame numbers in INI file are 0-based - Overlay PNG should match output dimensions (width × height) - Transparent areas in overlay allow video content to show through - Use `-Render` to quickly re-encode with different settings without reprocessing frames - Use `-WhatIf` to preview the full workflow (cropping offsets, frame operations, video creation) before committing to a full run - Use `-Confirm` to be prompted before each state-changing operation - `Smoothing` only takes effect when the interpolated speed between two keyframes exceeds the `Speed` limit; otherwise offsets are used unchanged