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

141 lines
7.0 KiB
Markdown

# Create-Scenes.ps1
Detects scene changes in a video with ffmpeg and extracts each scene as a separate clip file. Each scene is created by calling [Create-Clip.ps1](Create-Clip.md) with the scene's frame range, which in turn calls [Clone-Video.ps1](Clone-Video.md).
The clips are saved next to the source video, named from the source filename and the scene number: `P01.mp4` produces `P01-Scene-01.mp4`, `P01-Scene-02.mp4`, and so on. A `.skip` marker stays last: `P01.skip.mp4` produces `P01-Scene-01.skip.mp4`.
## Parameters
- **`-Video`** (required): Path to the input video file. Can be absolute or relative to current directory. If the file does not exist, the script tries appending `.mp4`, `.webm` and `.mkv` in turn, so `P01` resolves to `P01.mp4` when that file exists.
- **`-Scene`** (optional): Scene-change threshold between `0` and `1.0`. Lower values are more sensitive and produce more scenes. Default: `0.3`.
- **`-Suffix`** (optional): Suffix for the clip filenames. Must contain one printf-style number placeholder, which is replaced by the scene number starting at 1. Default: `-Scene-%02d`. See [Suffix Placeholders](#suffix-placeholders).
- **`-List`** (optional): Only displays the scene list. No clip is created and no existing file is deleted.
- **Extra parameters**: Any parameter accepted by `Create-Clip.ps1` and `Clone-Video.ps1` (e.g. `-Size`, `-FPS`, `-NoAudio`, `-Audio`, `-CRF`, `-Metadata`, `-Reverse`, `-LTX`) is forwarded to every clip. The parameters `-Video`, `-Frames`, `-Suffix` and `-Target` are managed by this script and must not be repeated.
Refer to [Clone-Video.ps1](Clone-Video.md) for a full description of the encoding parameters.
## Requirements
- `ffmpeg` and `ffprobe` must be in the `PATH`.
- `Create-Clip.ps1` must be in the same directory as `Create-Scenes.ps1`.
## How It Works
1. **Detection**: ffmpeg runs the `scene` score filter with the `-Scene` threshold and reports the timestamp of each detected change.
2. **Frame conversion**: each timestamp becomes a 0-based frame index using the video's frame rate and start time. Indices at or before frame 0, or at or after the last frame, are ignored.
3. **Scene list**: scene 1 starts at frame 0, and each detected change starts a new scene. Each scene ends one frame before the next change, and the last scene ends at the last frame. With no detected change, the whole video is one scene.
4. **Scene list display**: the list is always printed, including with `-List`, `-WhatIf` and `-Confirm`.
5. **Cleanup**: unless `-List` is given, files from a previous run are deleted (see [Replacing Existing Clips](#replacing-existing-clips)).
6. **Clip creation**: one `Create-Clip.ps1` call per scene, with frames `start-end` and the scene suffix.
Example scene list for a video with two hard cuts at frames 30 and 60:
```text
Index StartFrame EndFrame Frames StartTime EndTime Suffix
----- ---------- -------- ------ --------- ------- ------
1 0 29 30 0.00 0.97 -Scene-01
2 30 59 30 1.00 1.97 -Scene-02
3 60 89 30 2.00 2.97 -Scene-03
```
`StartTime` and `EndTime` are in seconds, computed as frame index divided by frame rate.
## Scene Threshold
`-Scene` is passed to ffmpeg's `scene` score. The score measures how much a frame differs from the previous one, from `0` to `1`:
- `0.3` (default): a reasonable starting point for ordinary footage.
- Lower values (e.g. `0.1`) detect gradual changes, such as slow camera moves, and produce more scenes.
- Higher values (e.g. `0.6`) only detect hard cuts.
- `1.0`: detects nothing, so the whole video becomes one scene.
## Suffix Placeholders
The first printf-style placeholder in `-Suffix` is replaced by the scene number. The number is zero-padded to the width given in the placeholder:
| Placeholder | Scene 1 | Scene 12 |
| --- | --- | --- |
| `%d` | `1` | `12` |
| `%02d` | `01` | `12` |
| `%003d` | `001` | `012` |
| `%03d` | `001` | `012` |
Other text in the suffix is used as written, so `-Suffix "-Shot-%03d"` produces `P01-Shot-001.mp4`. A suffix without a placeholder, such as `-Suffix "-Scene"`, is rejected. A literal `%%` is not supported.
## Replacing Existing Clips
Before the new clips are created, the script deletes earlier clips of the same source. A file is deleted when all of these match:
- It is in the same directory as the source video.
- Its name is the source's base name, then the suffix pattern (any number in place of the placeholder), then `.skip` only if the source had one, then the source's extension.
- It is not the source video itself.
Matching is case-insensitive. Files that do not match are never touched. Existing clips are always replaced, so you do not need to delete them first.
| Source | Matches | Does not match |
| --- | --- | --- |
| `P01.mp4` | `P01-Scene-01.mp4`, `P01-Scene-12.mp4` | `P01-Scene-01.skip.mp4`, `P01-Other.mp4` |
| `P01.skip.mp4` | `P01-Scene-01.skip.mp4` | `P01-Scene-01.mp4` |
Because the deletion happens before the first clip is created, a second run with a higher `-Scene` value removes the extra clips from the first run.
## Examples
**List the scenes without creating anything:**
```powershell
.\Create-Scenes.ps1 -Video P01.mp4 -Scene 0.4 -List
```
**Create one clip per scene:**
```powershell
.\Create-Scenes.ps1 -Video P01.mp4
# Creates: P01-Scene-01.mp4, P01-Scene-02.mp4, ...
```
**Scale and remove audio from every clip:**
```powershell
.\Create-Scenes.ps1 -Video P01 -Scene 0.3 -Size 720p -NoAudio
```
**Custom suffix:**
```powershell
.\Create-Scenes.ps1 -Video P01.mp4 -Suffix "-Shot-%03d"
# Creates: P01-Shot-001.mp4, P01-Shot-002.mp4, ...
```
**Source with a `.skip` marker:**
```powershell
.\Create-Scenes.ps1 -Video P01.skip.mp4
# Creates: P01-Scene-01.skip.mp4, P01-Scene-02.skip.mp4, ...
```
**Higher-quality clips:**
```powershell
.\Create-Scenes.ps1 -Video P01.mp4 -CRF 18
```
## Safe Execution
This script supports `-WhatIf` and `-Confirm`. Both apply to the deletion of old clips and to the creation of new ones, and are forwarded to `Create-Clip.ps1`.
- **`-WhatIf`**: Shows the scene list, the files that would be deleted, and the clips that would be created. Nothing is changed on disk.
- **`-Confirm`**: Prompts before each deletion and each clip creation.
```powershell
.\Create-Scenes.ps1 -Video P01.mp4 -WhatIf
```
## Notes
- Frame indices are computed as `timestamp * frame rate`. This is exact for constant-frame-rate videos. With variable frame rate, a scene boundary can be off by one frame.
- Clips are encoded by `Clone-Video.ps1`, so each clip keeps the source's resolution, frame rate and audio unless extra parameters change them.
- Clips are written next to the source video, not to the current directory.
- Scene detection is based on visual change only. A cut between two very similar shots may not be detected, and a fast camera move may be detected as a cut. Adjust `-Scene` to suit the footage.
- Each clip is created with `Create-Clip.ps1`, so a failed clip is reported as a warning and the other scenes are still created. At the end, the script reports how many scenes failed.