Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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?
Copy link to clipboard
Copied
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? ☺️
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
This might be a little better:
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){
t0 = L.sourceTime(L.startTime);
f = Math.round((L.sourceTime(time) - t0)/src.frameDuration);
txt += (txt != "" ? " ; " : "") + "Frame: " + f + " (" + src.name + ")";
}
}
txt
Copy link to clipboard
Copied
Hello Dan,
Thanks for replying. But this expression was also accepting image layers and shape layers like I said if I kept them below the text layer. So that was giving a problem. I wanted the expression to filter out if possible to not check for image layers, shape layers and solid layers, but unfortunately I wasn't able to come up with anything. I thought about using labels as a way to filter out the layer (Our company has a label system that everyone has to use to have consistency). So I was like okay, I may be able to integrate an expression that filtered the layers below, using "Orange" label that we use for video footages and renders. So only those will be checked. If it has some other label then the expression will ignore it. But unfortunately you can't do it. Or maybe you can but I didn't stumble upon anything like that.
In the end I found a solution to integrate "hasAudio" into the expression. Because only video layers will have audio in them. Image layers, shape layers won't have them. So it filtered out.
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
This is the expression. If you can do tell me if I can change it or is this the best option.
Thanks.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
Okay I'll try right now. Now here's my two questions:-
1) Why does this expression doesn't work if I have a video layer, that I have time reversed. Like I did time reverse layer. So when the time slider comes over such videos it doesn't work. Why is it that.
2)Let's say I have a few videos. And I've done some motion graphics infographics over them. For example I had a scene where there was a character doing some pipeline work on a marine ship. So I had to like mask out the pipe nozzle and do some arrow animation over it to highlight the importance. So usually what I do is when such a thing happens, because there's lots of shape layers, track mattes, etc. So what I do is I pre-comp all of them together. To make the file more organized. Like all the shape layers, track matte and the video footage itself. But now this expression considers the entire pre-comp as one footage and it shows "So&so Pre_Comp Frame :197". I want it to show what footages are inside the pre-comp as well. I know it won't be possible to do it. But I'm asking if it can be done.
Thanks.
Copy link to clipboard
Copied
1) Time reverse seems to work for me (on my expression). It might be off by 1 frame, but I'm not sure about that.
2) That's a lot more complicated. I guess you would have to have a text layer with the expression inside the pre-comp.