7 Replies Latest reply on Jan 12, 2010 3:56 AM by Mylenium

    Replacing layer with different length source item

    Redsandro Level 1

      I was wondering if it was possible.

       

      You know, you've a layer with a lot of keyframed data and you replace your proxy footage with the real thing by alt-dragging.

       

      Now imagine your replacement is a lot shorter. Manually moving all keyframes is a pain, especially if your composition is a 50 frame thing where the previous footage for the layer was a few minutes.

       

      Is there a trick to offset all effects and keyframes by the same amount at once to fix the difference?

        • 1. Re: Replacing layer with different length source item
          Mylenium Most Valuable Participant

          Hold down Alt while dragging keyframes to scale them in time.

           

          Mylenium

          • 2. Re: Replacing layer with different length source item
            Redsandro Level 1

            Thanks, but I don't mean scaling. I mean offsetting everything with frame-accuracy if for example you are replacing a full-length proxy with a shorter lossless footage item.

             

            I have been working on a script to do that but I didn't finish it because I thought something like this might be obvious enough for a way to do it in the program without scripting.

            • 3. Re: Replacing layer with different length source item
              Mylenium Most Valuable Participant

              I'm not sure I understand you. What do you not get when scaling/ slip-sliding the keyframes?

               

              Mylenium

              • 4. Re: Replacing layer with different length source item
                Redsandro Level 1

                Let me exaggerate a bit for the sake of round numbers.

                 

                Imagine I have 20 roto-masks on the last 50 frames of a 5000 frame video in a 50-frame-long composition.
                Next, I have a video of those last 50 frames in other quality, and I replace the footage item for that layer.
                Now, 20*50=1000 keyframes are 4050 frames too far from the start of the layer, and the start of the layer is 4050 frames before the start of the composition.

                 

                So either I have to move the layer to the right 50 frames and the keyframes to the left 50 frames for 4050/50=81 times because you cannot drag for more than the length of the composition at a time, or I must resize the comp to 5000 frames, zoom way out, drag the frames, zoom in to see if I placed them exactly at the start, zoom way out again, move the layer to the end of the composition minus 50 frames, zoom way back in again to see if I moved it to the exact point, and finally resize the composition back to 50 frames.

                 

                See why this is annoying?

                • 5. Re: Replacing layer with different length source item
                  Mylenium Most Valuable Participant

                  I see. You want this to be based on the key's time, not the layer's in-point. Would in that case not simple copy&paste work? --> Reveal keyframes, hit K to go to the first one, Ctrl+A to select all, copy to clipboard. Now replace footage. Use [ to move in-point to CTI. Again reveal now wrong keys, Ctrl+A, delete, paste keys from clipboard. The only requirement is to not move the CTI during al lthis, as it will be the temporal anchor and insertion point for the keys.

                   

                  Mylenium

                  • 6. Re: Replacing layer with different length source item
                    Redsandro Level 1

                    Thanks, that works, apart from some shortcutkeys behaving differently on my system.
                    But I also need to reinstate inpoint and outpoint to the max prior to replacing, for the replacement will otherwise be 1 frame in to out.
                    Also, my footage has handles so I need to move the CTI to x (length of handle) frames before the start of the comp to move the layer there, and move the CLI back for pasting the frames.

                     

                     

                     

                    So although in the end this works, I'd rather automate this task to make this go faster and to iliminate the risk of making an error that messes with hours of rotoscoping work.

                     

                     

                     

                    I've created this script, but so far it skips all MASK PATH keyframes. Do you know what's so different about Mask PropertyGroups that makes them get skipped in my if (prop.canVaryOverTime && prop.numKeys > 0) switch?

                     

                     


                     

                     

                    /**********
                      *      Offset Keyframes
                      **********
                      *      Filename:       Rs - Offset Keyframes.jsx
                      *      Written by:     Redsandro - http://www.rednet.nl/en/
                      *      Date:           2010/01/11
                      *      Last updated:   2010/01/12
                      **********
                      *
                      *      Description:
                      *
                      *      Offset all keyframes of a layer for fixing different-length replacement
                      *
                      **********/




                    clearOutput();

                    var myComp = app.project.activeItem;
                    var errors = new Array();

                    if (myComp == null || !(myComp instanceof CompItem)) {
                             alert("No composition selected.");
                    }
                    else if (myComp.selectedLayers.length == 0) {
                             alert("Select one or more layers to offset keyframes of.");
                    }
                    else {
                             // Vars
                             var selLays = myComp.selectedLayers
                             var fDuration = myComp.frameDuration;
                             var propsCount = 0;
                             var offsetCount = 25;
                             offsetCount = parseInt(prompt("Offset keys how many frames? (New footage less handle (1 minute), keys go backwards (-1500).)", offsetCount));
                             var offset = offsetCount * fDuration;
                             if (offset == 0) exit;

                             app.beginUndoGroup("Rs - Offset Keyframes");

                             // Walk layers
                             for (var l = 0; l < selLays.length; l++) { // Layers Zero based!
                                     // Vars
                                     var lay = selLays[l];

                                     // Walk props
                                     propOffset(lay, offset)
                             }

                             app.endUndoGroup();
                    }

                    function propOffset(pGroup, offset) {
                             for (var p = 1; p <= pGroup.numProperties; p++) { // Properties NON-Zerobased
                                     var prop = pGroup.property(p);
                                     if (prop instanceof PropertyGroup)
                                             propOffset(prop, offset);
                                     else if (prop instanceof Property) {
                                             //alert(prop.name);
                                             if (prop.canVaryOverTime && prop.numKeys > 0) {
                                                     // walk keyframes
                                                     for (var k = 1; k <= prop.numKeys; k++) { // NON-Zerobased
                                                             // Walk forewards or backwards
                                                             if (offset > 0) // Start with last key if keys are moving forward
                                                                     k = prop.numKeys - k + 1;
                                                             //var key = prop(k);
                                                             // clone key
                                                             var time = prop.keyTime(k);
                                                             prop.setValueAtTime(time+offset, prop.valueAtTime(time, false));
                                                             prop.removeKey(k);
                                                     }
                                             }
                                     }
                                     else if (p.name = "Marker") {
                                             //SELFNOTE: Something with markers.. I hardly use them.
                                             // Scripting guide p. ~99.
                                             // PseudoCode:
                                             // foreach something:
                                             // p.setValueAtTime(OldTime+offset, OldMarkerValue);
                                             // p.removeMarker(oldTime);
                                     }
                             }
                    }

                    • 7. Re: Replacing layer with different length source item
                      Mylenium Most Valuable Participant

                      Mask paths are second level props which you do not seem to cover in your code (can't stare at this for hours, I am at work and have things to do... )

                       

                      Mylenium