Skip to content

ericfortis/final-cut-pro-scene-detect

Repository files navigation

fcpscene

Final Cut Pro Scene Detector

This program finds scene changes in videos and generates a Final Cut Pro project with cuts at those scene changes, using either compound or normal clips.

Image

That example processed a video with five cuts, so the timeline has six compound clips.

Image

Motivation

I wanted to increase the frame rate of old videos using Final Cut’s Optical Flow (Machine Learning) interpolation and I faced two main problems. First, it messes up scene changes by adding a transition — even if they are bladed. Second, it needs hundreds of gigabytes of disk space.

Third minor problem

Changing frame rate in FCP messes up clip boundaries, but that’s solvable pre-encoding in ProRes. By the way, FCP doesn’t support changing frame rate, but we can create a new project with the desired frame rate and paste the old project timeline there.

To solve those problems we need to send individual clips to Apple Compressor, and let it process the frame rate change and interpolation. But how?

First, we’d have to tediously cut the timeline, and then manually wrap each clip in its own compound clip so we can batch send them to Compressor.

fcpscene automates that process.

Before Installing

I haven’t confirmed it myself, but DaVinci Resolve Studio (the paid version) may be a viable alternative.

Installation

fcpscene is installed via Homebrew.

  1. Install Homebrew
  2. In the Terminal app type:
brew tap ericfortis/fcpscene
brew install fcpscene

Launch it by typing:

fcpscene --gui

Optionally, install the fcpscene.app droplet.

Image

In Finder (not in the Terminal), Go → Go to Folder and type /opt/homebrew/opt/fcpscene/

Then move fcpscene.app to your Applications folder.

Before Running

1. Create an event called "fcpscene" in your Library

Details This is only needed for compound clips. Without that event you won’t see them in FCP Browser View, which is where you need to select them for batch sending to Compressor.

Otherwise, you have two options:

  1. Load the project again. The first load creates the fcpscene event.
  2. Or, Select All compound clips in the timeline, and ClipReference New Parent Clip. But that appends the word "copy" to their names.

2. Place your video in your 📂Home or 📂Movies directory

Details Your video file should be in a directory Final Cut Pro can access — your 📂Home and 📂Movies directories are allowed by default. Otherwise, grant Full-Disk Access to Final Cut Pro — without it, Final Cut will crash when importing the project. For example, that will happen if your video is in your ⚠️Desktop, ⚠️Documents, or any other TCC-protected folder, regardless of where the .fcpxml file is.

Running

The fcpscene.app is a droplet, which means you can drag a video file onto it, or right-click the video file and select Open Withfcpscene.app

A 15-minute 4K 60fps video takes about a minute to run on a 14-core M4. You’ll see the detected cut times as it runs — if you hit "Stop", you can still export a Final Cut Pro project file with the cuts found so far.

The Sensitivity should be around 65 to 90%. Start with 85% and increase it if it’s missing cuts. Pair it with Min Scene Seconds so you can have a high sensitivity while ignoring false positives. Those options have no effect on the processing speed.

You can delete the exported .fcpxml after the project is loaded in Final Cut.


Command-Line Program

The fcpscene command line program has more features than the GUI app. Also, it’s convenient for batch processing videos.

Details

Usage Example

fcpscene ~/Movies/my-video.mp4

That example generates an ~/Movies/my-video.fcpxml project.

Tip: If you don’t want to type the video file path, just drag the file into the Terminal — it will paste the path for you.


Options

For the full list of options, type: fcpscene --help


Output Filename

Default: <video-dir>/<video-name>.fcpxml (i.e., in the same directory the video is in)

fcpscene my-video.mp4 --output my-project.fcpxml

Sensitivity

Range: 0-100, Default: 88

This value sets the frame difference percentage used to detect scene changes.

fcpscene --sensitivity 70 my-video.mp4

Min Scene Seconds

Default: 0.6

Ignores scene changes that are shorter than the value. This is handy for having a high-sensitivity while avoiding false-positives.

fcpscene --min-scene-seconds 2 my-video.mp4

Proxy Width

Default: 320

Lower values speed up analysis. This sets the temporary width used to scale down the video during processing (without modifying the original file).

fcpscene --proxy-width 240 my-video.mp4

Mode

Choices:

  • clips: Normal clips (default)
  • compound-clips: Wraps each clip in its own compound clip
  • markers: Only add markers
  • files: Export scenes as individual video files
  • count: Print scene changes count (no file is saved)
  • list: Print scene changes times (no file is saved)
fcpscene --mode markers my-video.mp4

Quiet

Do not print video summary and progress.

fcpscene --quiet my-video.mp4

Export Scenes as Files

Creates a folder named after the video (without the extension) in the same directory and saves the clips there.

fcpscene --mode files my-video.mp4

Batch Processing


Generating FCPXML

In the Terminal, you can type a snippet like this to run fcpscene on all the .mp4 videos in your 📂~/Movies directory excluding subdirectories.

cd ~/Movies
for vid in *.mp4; do
  caffeinate fcpscene "$vid"
done

Typing caffeinate is optional. It’s a macOS built-in program that prevents the computer from sleeping while it’s running a task.

Also, keep your computer in a well-ventilated area. fcpscene uses ffmpeg under the hood, which will max out your CPU cores 🔥.


Counting cuts

I use this command to check if there are stray frames in single-scene files. For example, when retiming with Machine Learning in Compressor, some end up with a random frame. So with this script I can print videos with cuts and their count.

cd ~/Movies/video_foo
for f in *.mov; do
  n_cuts=$(fcpscene --quiet --min-scene-seconds 0 --mode count "$f")
  if [[ $n_cuts != 0 ]]; then
    echo "$f" "$n_cuts"
  fi
done

Example output:

video_foo_018.mov 1
video_foo_064.mov 2
video_foo_073.mov 2

Listing cuts

Same as above but printing cut times

cd ~/Movies/video_foo
for f in *.mov; do
  cuts=$(fcpscene -q -mss 0 --mode list "$f")
  if [[ $cuts ]]; then
    echo "$f" "$cuts"
  fi
done
video_foo_018.mov 0.0166667
video_foo_064.mov 0.866667 2.066667
video_foo_073.mov 0.866667 2.066667

Final Cut Pro Tips

Batch Export Compound Clips
  1. Select the all the Compound Clips you want to export. Image

  2. FileShare N Clips Image


Joining Clips In iMovie there’s (Cmd+J), but in Final Cut we don’t _join_ clips, we _delete_ cuts.
  1. Pick the Trim Tool (T)
  2. Select both edges by clicking between two clips
  3. Hit Delete

Alternatively, you can drag each clip edge until it touches the adjacent one to remove the cut.

Image


Batch Clip Rename
  1. Select the clips you want to rename
  2. Window → Show in Workspace → Inspector (Cmd+4)
  3. Go to the ⓘ Info Inspector Tab (Ctrl+Tab)
  4. Type a name

Image


Alternative Tools

Davinci Resolve Studio

In Davinci Resolve Studio, the paid version, you can run scene detection and export to Final Cut Pro.

Different Approach

Instead of cutting the timeline, there are many tools for splitting the video into small videos.

Kdenlive (for programmers)

Caveats: There are many 1-frame-off cuts due to rounding errors. Especially with non-integer frame rates such as 29.97

  • Drop the video into the Project Bin → Right-click → Clip Jobs → Automatic Scene Split
  • Expand the video on the Project Bin → Select all sequences → Drop them to the timeline
  • File → OpenTimelineIO Export
  • Convert the .otio to .fcpxml with this Python adapter

Acknowledgments

License

MIT © 2025 Eric Fortis

About

Creates a Final Cut Pro project with a timeline cut at the scene changes of a video

Resources

License

Stars

Watchers

Forks