Switch branches/tags
Nothing to show
Find file History
Pull request Compare This branch is 24 commits ahead, 520 commits behind ReaTeam:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
..
Failed to load latest commit information.
example
schema
.gitignore
README.md
__init__.py
beaunus_clip_splicer_tools.py
setup.py

README.md

Clip Splicer

Motivation

I make CDs for an English language school. A single track in a typical project usually comprised a few instructions followed by a lot of words, each with spaces for repeats and pauses to allow listeners to practice. When I first started doing this, my process was something like this:

Setup

  1. Obtain a script of the entire CD project.
    • The script would define the layout of each track. Something like this:
      • [Instruction 1A], Cat, Dog, Elephant, ...
  2. Create a skeleton REAPER session file that contained Empty MIDI Items for each of the components that would eventually be recorded in the project.
  3. Name the Empty MIDI Items according to the word that would eventually be recorded.
  4. Put regions and markers on all the components and tracks.

At this point, I had a skeleton of what the final project would look like.

Recording

  1. Setup microphones to record each vocalist.
  2. Use the Region/Marker Manager to move through the project. Filtering for components that included the vocalist that I was recording.
  3. Record each clip in the position that it was intended.

At this point, I had recorded clips whose starting positions were in the proper place. There were a few problems that still needed to be addressed.

  • The beginnings and endings of the clips had silent moments that needed to be edited out.
  • The lengths of the recorded clips was not the same as the length of the EMPTY MIDI Item that held its place.

Editing

For every single clip in the project:

  1. Manually trim the silence at the beginning and end of the clip.
  2. Using global ripple editing, move the following components to the right, so they began where the previous component ended.

As you may guess, that could take a very long time if there were hundreds or thousands of individual clips to edit.

However, at this point, the session was ready to be mixed for audio.

Revisions

Revision requests often came in the form of:

  • Please make the pauses after all the instructions a bit longer.
  • Please re-record the word "cat" and replace all instances with the new recording.

Although revisions weren't terribly difficult to do, the amount of editing was still similar to the original amount of editing. Also, on a not-so-fast machine, editing files within a mixing session was often sluggish, with all the plugins running. Some sessions include gigabytes of .wav files loaded into memory. Some files appeared multiple times within the session.

Enter Clip Splicer.

Overview

Clip Splicer is used to automatically assemble components into a REAPER project.

The components are defined by a simple JSON file that can be created by hand, or by machine. For example, here's what a basic Clip Splicer JSON file might look like:

{
  "title": "Simple Clip Splicer Example.",
  "components": [
  {
    "type": "REGION",
    "name": "Simple example",
    "components": [
      {
        "type": "MEDIA ITEM",
        "track": "Person1",
        "name": "Word1",
        "filename": "P1-W1.wav"
      },
      {
        "type": "MEDIA ITEM",
        "name": "Pause after clip.",
        "length": 2
      }
    ]
  }]
}

The above example would generate a REAPER session that looks something like this:

→Regions→
            |- - - - - - - -  A region named "REGION: Simple example" - - - - - - -|
→Timeline→
↓Tracks↓
Person1   | |- -  Media Item: "P1-W1.wav"  - - -|
SILENCE   |                                      |-  Empty Media Item (length 2s) -|

Notice:

  • Regions are created to contain their components.
  • Media Items are aligned in sequence, regardless of length.
  • Media Items are put on the proper track.

Workflow

Import the specification into a REAPER session.

  1. Run the script Script: beaunus_Import_reaper_clip_splicer_json.py
  2. Select a .json file that contains a REAPER Clip Splicer specification.
    • If you are having trouble importing your JSON file, try validating your JSON file with schema/ClipSplicerSchema.json
  3. Examine the generated missing file report to see what needs to be recorded.
  • The report can be found in the same folder as the .json file.

Record the clips

  1. If the missing file report is simple enough to manually trim each clip, simply record the clips without a lyrics track.
  2. If you want to automated the trimming process:
  3. Import the missing file report into a lyrics track in a REAPER session.
  4. Convert the lyrics to markers.
    • beaunus_Add markers for lyrics in selected items.lua
  5. Set a reasonable tempo. In fact a super slow tempo will allow lots of time between clips.
  6. Record the clips in order.
    • You can easily navigate through the clip areas by using the marker manager.

Trim and save the clips

Performances should be loudness normalized to -23LUFS.

If you have used a lyrics track:

  1. Split the performance using dynamic split.
  2. Trim silence at the beginnings and ends of clips.
  3. Name the takes according to the marker that cuts them.
    • beaunus_Name item takes by last marker to cut item.lua
  4. Select the recorded, trimmed, items.
  5. Render items

After all the clips have been recorded, you can again 'Import the specification into a REAPER session.'

A closer look at the JSON object

Clip Splicer attempts to model the data as simply as possible. Refer to http://www.json.org for some inspiration.

Keep in mind that anything in your REAPER session that should be ordered needs to be within an array in the JSON file. In the above example, the main REGION ("Simple example") is the only REGION in the specification's components. A Clip Splicer specification requires at least one component in the "components" member.

There are two types of Clip Splicer objects:

  1. REGION - Used as a wrapper to surround internal components.
  2. MEDIA ITEM - Used to represent an audio file or a period of silence.

One of the powerful features of Clip Splicer is that REGIONs can be nested. For example, imagine this:

  • You are creating a single project that should contain 5 discs (as in CDs).
  • Each disc has a few dozen tracks (as in tracks on a CD).
  • Each track has two sections:
    • An instructions section.
    • A content section.
  • Each section has many clips and silences.

In the above example, there are discs, tracks, sections, instructions, and contents. For all of those cases, ordering is important. When you are navigating your REAPER session, you also want to be able to quickly move through the Region/Marker Manager to get to all of the elements' positions. When you want to render your project to it's final form, you also want to be able to render all of the tracks as individual .wav files, and put them into properly named folders for each of the discs.

This can all be done by nesting REGIONs within each other. Just give all of the REGIONs an appropriate name. For example:

  • "DISC - Disc 01"
  • "TRACK - Track 00"

When Clip Splicer creates your REAPER project, all of the REGIONs will be named. You can filter the REGIONs that you want in the Region / Marker Manager.

Here's a slightly more complex Clip Splicer JSON file example:

{
  "type": "REGION",
  "name": "Slightly more complex example project.",
  "components": [
    {
      "type": "REGION",
      "name": "DISC - Disc 01",
      "components": [
        {
          "type": "REGION",
          "name": "TRACK - Track 00",
          "components": [
            {
              "type": "REGION",
              "name": "Instructions",
              "components": [
                {
                  "type": "MEDIA ITEM",
                  "filename": "Instruction 01.wav"
                },
                {
                  "type": "MEDIA ITEM",
                  "filename": "Instruction 02.wav"
                }
              ]
            },
            {
              "type": "REGION",
              "name": "Content",
              "components": [
                {
                  "type": "MEDIA ITEM",
                  "filename": "Content 01.wav"
                },
                {
                  "type": "MEDIA ITEM",
                  "filename": "Content 02.wav"
                }
              ]
            }
          ]
        },
        {
          "type": "REGION",
          "name": "TRACK - Track 01",
          "components": [ ... ]
        }
      ]
    },
    {
      "type": "REGION",
      "name": "DISC - Disc 02",
      "components": [ ... ]
    }
  ]
}

JSON objects

There are only 2 basic JSON object types:

  • REGION
  • MEDIA ITEM

REGION

A REGION is used to wrap and contain a series of components.

Here are the valid members of a REGION object:

  • type (string) (required) : This must be "REGION" in order to be interpreted properly.
  • name (string) (optional) : If defined, the REAPER Region will be named "[name]"
  • track (string) (optional) : If specified, all components will be added to this track, unless overridden. If not, the inherited track will be used. If there is no inherited track, a track with no name will be used.
  • path (string) (optional) : If specified, all components' paths will be relative to this path. If not, the inherited path will be used. If there is no inherited path, the root path will be used. The root path is the location of the JSON file itself.
  • components (array) (optional) : If defined, the objects within the array will be interpreted and imported into this REGION. If empty or undefined, the REGION will have length 0.

Here's an example REGION with all the bells and whistles:

{
  "type": "REGION",
  "name": "Super Duper Region",
  "track": "Cowbell",
  "path": "clips/percussion/cowbell/",
  "components": [...]
}

For REGION objects, Clip Splicer will:

  1. Start a REAPER region at the beginning of the object.
  2. Render all of the components within the object in their proper sequence.
  3. End the REAPER region at the end of the last component.

MEDIA ITEM

A MEDIA ITEM is used to represent an audio file or period of silence.

Here are the valid member of a MEDIA ITEM object:

  • type (string) (required) : This must be "MEDIA ITEM" in order to be interpreted properly.
  • name (string) (optional) : If defined, the REAPER Media Item will be named "[name]".
  • track (string) (optional) : If specified, this REAPER Media Item will be added to this track. If not, the inherited track will be used. If there is no inherited track, a track with no name will be used.
  • filename (string) (optional) : If specified, Clip Splicer will look for a file with the specified filename, relative to the path, and place it in the REAPER Media Item. If not, an empty REAPER Media Item will be used.
  • length (number) (optional) : If specified, the REAPER Media Item will use the specified length (in seconds). If not, the file's original length will be used. If the specified length is shorter than the file's length, the end of the file will be truncated. If the specified length is longer than the file's length, the audio will be looped to reach the length.
  • mute (true/false) (optional) : If true, the REAPER Media Item will be muted.

Here's an example MEDIA ITEM with all the bells and whistles.

{
  "type": "MEDIA ITEM",
  "name": "Super Duper Item",
  "track": "Aux. Percussion",
  "filename": "TheFever.wav",
  "length": 1000,
  "mute": true
}

path

If an object specifies a path, all internal components within that REGION will inherit the specified path. Internal components can extend their parent's path by specifying a new path.