Skip to main content
Inspiring
December 28, 2024
Answered

Expression help for video frames script

  • December 28, 2024
  • 2 replies
  • 2918 views

Hello,

I had a requirement of having a text layer with an expression that displayed the video name and the frame number of that video. So I searched around and with the help of ChatGPT I came up with an expression. (P.s I'm uploading my file with the expression because it's a little lengthy). But at random times the expression seems to bug out. The error comes as 

"Error : Error : this layer has no source".

 

For some reason I found that this issue doesn't happen if I don't keep any other layers below the text layer with the expression. Like if I keep any shape layer it doesn't work. I only need to have video layers below it. But is there any workaround to this. I'm uploading my file and the error. Hopefully I can get a solution. 

Correct answer Dan Ebberts
txt = ""; // Initialize the text output var currentTime = time; // Current time in the composition // Loop through all layers after the current text layer for (var i = index+1 ; i <= thisComp.numLayers; i++) { var L = thisComp.layer(i);   var K = L.property;   //txt += i + ";" // Check if the layer is active, visible, and within the time range if (L.active && L.inPoint <= currentTime && L.outPoint > currentTime) { // Check if the layer is a video layer and has a label if (L.hasVideo && L.active && L.hasAudio) { txt += "Layer: " + L.name;       var frameDuration = L.sourceTime();       var localTime = currentTime - L.startTime; // Time relative to the layer       var frameNumber = Math.floor(30* frameDuration);       frameInfo = " - (Frame: " + frameNumber + ")\n";       txt += frameInfo; } } } txt; // Return the output text

I think if you add the hasAudio test to what I posted before, it will ignore shapes, solids, text, nulls, etc:

txt = "";
for (i = index+1; i <= thisComp.numLayers; i++){
  L = thisComp.layer(i);
  try{
    src=L.source;
  }catch(e){
    continue; // skip this layer if no source
  }
  if (L.hasVideo && L.active && L.hasAudio){
    t0 = L.sourceTime(L.startTime);
    f = Math.round((L.sourceTime(time) - t0)/src.frameDuration);
    txt += (txt != "" ? " ; " : "") + "Frame: " + f + " (" + src.name + ")";
  }
}
txt

2 replies

Dan Ebberts
Community Expert
Community Expert
December 28, 2024

I think your expression could probably be simplified greatly, but I'm not clear on what it's supposed to do. What exactly is the text layer supposed to display? You mention "the video name and frame number of that video", but which video?

JohnK159Author
Inspiring
December 28, 2024

Hello. Sorry for not phrasing properly. So I have lots of renders from my team. And I do composting. So I have lots of videos which I can't share (Company T.O.S). So when I add video layers below the text layer in the composition, the text layer with the expression, should display the video name of all the layers below at the given time, the frame number of that video footage. But my problem is, the expression gives out error, if I add a shape layer, or an image layer or an audio layer or a solid layer. So I wanted something in the expression that will bifurcate, and like only detect video footage layers and nothing else. I want the expression to go through all the layers at any given point of time in the composition, and parse information of the video footages underneath, and their frame number. Not the frame number of the composition, but the frame number of that footage layer. (P.s for example if the video is 500 frames long and if I've imported and have used frames 250-300, as and when the time slider is hovering over that particular video layer, the text layer above should parse 250, 251 or whatever the frame is). I did manage to achieve it, but for some reasons it's also detecting shape layers and image layers and solid layer. So what happens is, since a shape layer can be extended to as much as you want, due to the expression on the text layer, it says "Shape layer 1 : Frame - Infinity". I want this text layer to be always there so that when I export this composition and send it to my supervisor, he can check it and based on that text layer, he adds changes that "So and so video, whatever number of that video render is, at frame number , so and so is wrong. Please check". For sort of debugging. I hope this helps? ☺️

Dan Ebberts
Community Expert
Community Expert
December 28, 2024

I think it would be something like this:

txt = "";
for (i = index+1; i <= thisComp.numLayers; i++){
  L = thisComp.layer(i);
  try{
    src=L.source;
  }catch(e){
    continue; // skip this layer if no source
  }
  if (L.hasVideo && L.active){
    f = Math.round(L.sourceTime(time)/src.frameDuration);
    txt += (txt != "" ? " ; " : "") + "Frame: " + f + " (" + src.name + ")";
  }
}
txt
Mylenium
Legend
December 28, 2024

It helps to understand the difference between a script and an expression. Your code doesn't make any sense for an expression. The name of a layer can easily be retrieved just with

 

thisComp.layer("XYZ").name

 

or if it needs to reference the actual source video

 

thisComp.layer("XYZ").source.name

 

Conversely, the frame of a source video can be retrieved using

 

timeToFrames(thisComp.layer("XYZ").sourceTime)

 

It would be a good idea to actually read the help to even ask the right questions when using CrapGPT.

 

https://helpx.adobe.com/after-effects/using/expression-language-reference.html

 

Mylenium