Undefined is not an object in after effects extendscript - extendscript

I have a script where i upload lot of aeps and merge them
I am using the following code
var aepFile = "local location of aep";
var importOpts = new ImportOptions(File(aepFile));
var aeFolder = app.project.importFile(importOpts);
for (var n = 1; n <= aeFolder.numItems; n++) {
app.layers.add(aeFolder.item(n));
}
The problem is at some point of time the error shows that undefined is not an object
it is referencing the aeFolder variable I checked , it is imported , but we can't get the data right . Maybe it's not synchronous ? No , because it runs perfectly the next time , Please help
Edit:
it points out that aeFolder is undefined , the index are 1 based, not 0 based.
Yes I can reproduce the error in a different project.
Might this happen if the RAM is low?

There are several points where this could go wrong.
What is importOpts?
Has aeFolder.numItems 0 based or 1 based index?
Can you reproduce the error in a separate project?
var aeFolder = app.project.importFile(importOpts);
for (var n = 1; n <= aeFolder.numItems; n++) {
app.layers.add(aeFolder.item(n));
}
Can you please provide an example project for us to test it.
Or more context to reproduce this error

Related

Async progress tracking of compute-heavy node process via DB

I have a compute-intensive, not-very quick, Node.js program. In order to provide some feedback about what it's doing, I'd like to update the status in a DB table to show what's going on.
A heavily stripped down example is shown.
Example PG declaration for the table:
sophia=> create table tracking(progress integer);
CREATE TABLE
sophia=> insert into tracking values(0);
INSERT 0 1
Node code:
const { Pool, Client, types } = require('pg')
// See https://node-postgres.com/api/pool
const db = new Pool({
host: process.env.DB_ENDPOINT,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
port: process.env.DB_PORT
})
for (let i = 0; i < 10; i++) {
// Do compute-intensive stuff
for (let j = 0; j < 1000000000; j++) {}
// Mark progress
console.log('i = ', i)
db.query(`update tracking set progress = ${i} where progress <= ${i} returning progress`).then(res => {
console.log('Progress', res.rows[0].progress)
})
}
The above is significantly simpler that my real code in the following ways:
It's just plain node - the real code runs in Lambda in AWS
This is just churning through busy-loops. The real code has serious business logic in which each step is different but will use certain elements of the previous operation.
The table is a trivial one-row, one-col example. The real one would track multiple elements based on different users, etc.
If these were really fire-and-forget, I'd expect them to update the DB and print the resulting return shortly after the operation was completed with some level of randomness and occasional delay. What I'm actually seeing is that they consistently do no updates at all until after the heavy computing is finished, which renders it useless.
16:17:16:~/ $ node heavy.js
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
Progress 0
Progress 1
Progress undefined
Progress 3
Progress undefined
Progress undefined
Progress 6
Progress undefined
Progress 8
Progress 9
This feels like a problem that must have been solved before. If there's a lib for doing this kind of operation, great. If there's a simple trick for getting the DB operations to trigger shortly after the result, that's fine. If there's some lambda-specific option for this, that'd also be great. Synchronously waiting for the DB at each step is obviously possible but seems really silly.

Update nested variable field in firestore

Suppouse a firestore Database filled with this structure, being Events and Users collections:
Firestore
-Events
-1612483200
-peopleSignedDict
-Alex
-state: 1
-Mark:
-state: 0
-1606172400
-peopleSignedDict
-Users
-1zyXSMMlGiaUusUNLQWAxfsI4pM2
-name: Alex
-4zyXSMMlGiaUusUNLQWAxfsI4pM2
-name: Mark
I'm using Node.js and trying to update Events.1612483200.peopleSignedDict.Alex.state to change the state from 1 to 0. To achieve it I'm trying to do:
var randomName = getRandomDBName();
db.collection('Events').doc('1612483200').set({
'peopleSignedDict.'+randomName+'.state': 0
});
But ofc my IDE (PhpStorm) yells at me telling that this syntax is not valid, which should be the correct syntax to approach this?
There's a few way to do this.
My favorite is to first construct the key in a separate variable, and then use that in the collection:
let randomName = getRandomDBName();
let updates = {};
updates['peopleSignedDict.'+randomName+'.state'] = 0;
db.collection('Events').doc('1612483200').update(updates);
But a common (and shorter) alternative is:
let randomName = getRandomDBName();
db.collection('Events').doc('1612483200').update({
[`peopleSignedDict.${randomName}.state`]: 0;
});
I'm actually not sure if the [] are needed in that last snippet, so if you have problems with it, try it without them and let me know.

How can I send selected comps in After Effects to AME via extendscript?

I've been trying to figure this out for the past day or two with minimal results. Essentially what I want to do is send my selected comps in After Effects to Adobe Media Encoder via script, and using information about them (substrings of their comp name, width, etc - all of which I already have known and figured out), and specify the appropriate AME preset based on the conditions met. The current two methods that I've found won't work for what I'm trying to do:
https://www.youtube.com/watch?v=K8_KWS3Gs80
https://blogs.adobe.com/creativecloud/new-changed-after-effects-cc-2014/?segment=dva
Both of these options more or less rely on the output module/render queue, (with the first option allowing sending it to AME without specifying preset) which, at least to my knowledge, won't allow h.264 file-types anymore (unless you can somehow trick render queue with a created set of settings prior to pushing queue to AME?).
Another option that I've found involves using BridgeTalk to bypass the output module/render queue and go directly to AME...BUT, that primarily involves specifying a file (rather than the currently selected comps), and requires ONLY having a single comp (to be rendered) at the root level of the project: https://community.adobe.com/t5/after-effects/app-project-renderqueue-queueiname-true/td-p/10551189?page=1
Now as far as code goes, here's the relevant, non-working portion of code:
function render_comps(){
var mySelectedItems = [];
for (var i = 1; i <= app.project.numItems; i++){
if (app.project.item(i).selected)
mySelectedItems[mySelectedItems.length] = app.project.item(i);
}
for (var i = 0; i < mySelectedItems.length; i++){
var mySelection = mySelectedItems[i];
//~ front = app.getFrontend();
//~ front.addItemToBatch(mySelection);
//~ enc = eHost.createEncoderForFormat("H.264");
//~ flag = enc.loadPreset("HD 1080i 25");
//app.getFrontend().addItemToBatch(mySelection);
var bt = new BridgeTalk();
bt.appName = "ame";
bt.target = "ame";
//var message = "alert('Hello')";
//bt.body = message;
bt.body="app.getFrontend().addCompToBatch(mySelection)";
bt.send();
}
}
Which encapsulates a number of different attempts and things that I've tried.
I've spent about 4-5 hours trying to scour the internet and various resources but so far have come up short. Thanks in advance for the help!

NotesException: Unknown or unsupported object type in Vector

I'm trying to add new names to the address book programmatically but I'm getting the following error:
[TypeError] Exception occurred calling method NotesDocument.replaceItemValue(string, Array)
Unknown or unsupported object type in Vector
Code snippet below:
var addressBook = session.getDatabase("","names.nsf");
var gView:NotesView = addressBook.getView("($VIMGroups)");
var gDoc:NotesDocument = gView.getDocumentByKey("groupName", true);
var newg:java.util.Vector = [];
var mems:java.util.Vector = new Array(gDoc.getItemValue('Members'));
newg.push(mems);
var newNames:java.util.Vector = new Array(getComponent("NewMems").getValue());
newg.push(newNames);
gDoc.replaceItemValue("Members", newg);
gDoc.save();
Adding a single user works fine, but then it does not save users in the required canonical format below:
CN=John Doe/O=Org
Instead it is saved in the original format below:
John Doe/Org
I look forward to your suggestions. Thanks.
You can't store an Array in a field. Make newg a java.util.Vector instead and integrate with that.
For OpenNTF Domino API the team wrote a lot of code to auto-convert to Vectors, which may cover Arrays.
Don't use an Array (which is a JS thing). Initialize it as a Vector.
var newg:java.util.Vector = new java.util.Vectory();
Then look up the Vector methods to see how to add to that vector. Not sure if you will have to convert the names using the Name method but I would store them as "CN=Joe Smith/O=Test Org" to be sure you got the right format.
I was able to solve the issue using a forloop to loop through the list and push it into a newly created array. Using the forloop seems to make the difference.
var newg = [];
var group = new Array(getComponent("NewMems").getValue()), lenGA = group.length;
for(i = 0; i < lenGA; i++){
newg.push(group[i]);
}
gDoc.replaceItemValue("Members", newg);
gDoc.save();
An explanation about this behaviour will be appreciated.

Converting a PGN to a list of FEN strings in nodejs (chess notations)

I'm building a chess-related application using nodejs. I've been trying to use chess.js as much as I can but I think I've hit a roadblock in terms of functionality. Before extending that functionality, I wanted to make sure that there wasn't another tool that can do what I need.
I'm looking for a way to convert a PGN string into a list of FEN moves. I was hoping to use load_pgn() in chess.js to load the moves into the object and then loop over each move and invoke the fen() function to output the current FEN. However, chess.js doesn't seem to have a way to walk through the moves in a game. Unless I'm missing something.
I'd rather not have to get into parsing strings, but will if I have to. Any suggestions?
Solution:
also see efirvida's answer below for a solution
Something like this (untested) seems to work. The function accepts a Chess object created with chess.js that already has a PGN loaded into it.
function getMovesAsFENs(chessObj) {
var moves = chessObj.history();
var newGame = new Chess();
var fens = [];
for (var i = 0; i < moves.length; i++) {
newGame.move(moves[i]);
fens.push(newGame.fen());
}
return fens;
}
Take a look to the github page .load_pgn link
var chess = new Chess();
pgn = ['[Event "Casual Game"]',
'[Site "Berlin GER"]',
'[Date "1852.??.??"]',
'[EventDate "?"]',
'[Round "?"]',
'[Result "1-0"]',
'[White "Adolf Anderssen"]',
'[Black "Jean Dufresne"]',
'[ECO "C52"]',
'[WhiteElo "?"]',
'[BlackElo "?"]',
'[PlyCount "47"]',
'',
'1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.b4 Bxb4 5.c3 Ba5 6.d4 exd4 7.O-O',
'd3 8.Qb3 Qf6 9.e5 Qg6 10.Re1 Nge7 11.Ba3 b5 12.Qxb5 Rb8 13.Qa4',
'Bb6 14.Nbd2 Bb7 15.Ne4 Qf5 16.Bxd3 Qh5 17.Nf6+ gxf6 18.exf6',
'Rg8 19.Rad1 Qxf3 20.Rxe7+ Nxe7 21.Qxd7+ Kxd7 22.Bf5+ Ke8',
'23.Bd7+ Kf8 24.Bxe7# 1-0'];
chess.load_pgn(pgn.join('\n'));
// -> true
chess.fen()
// -> 1r3kr1/pbpBBp1p/1b3P2/8/8/2P2q2/P4PPP/3R2K1 b - - 0 24
something like
moves = chess.history();
var chess1 = new Chess();
for (move in moves){
chess1.move(move);
fen = chess1.fen()
}
(Not really an answer; just a comment that needs extra formatting.)
Your getMovesAsFENs function might also be written as:
function getMovesAsFENs(chessObj) {
return chessObj.history().map(function(move) {
chessObj.move(move);
return chessObj.fen();
});
}
Perhaps it doesn't matter to you, but this appeals to my sense of neatness.
Here is an end to end answer with some ES6 sugar added in:
const Chess = require('chess.js').Chess;
const chess1 = new Chess();
const chess2 = new Chess();
const startPos = chess2.fen();
const pgn = `1.e4 c5 0-1`;
chess1.load_pgn(pgn);
let fens = chess1.history().map(move => {
chess2.move(move);
return chess2.fen();
});
//the above technique will not capture the fen of the starting position. therefore:
fens = [startPos, ...fens];
//double checking everything
fens.forEach(fen => console.log(fen));
"However, chess.js doesn't seem to have a way to walk through the
moves in a game. Unless I'm missing something.".
You are right (as I have read the entire library multiple times by now). And everything that needs to see back into the history is basically undoing and then redoing the moves, without some sort of real navigation integrated (it is an interesting choice to have it solved this way, with the pros of it being lighting fast for some tasks, but with the cons of being a real pain for other seemingly easier tasks like the one you need).
Disclaimer (I wrote the following tool), I have been creating a tool (isepic-chess.js) for the past 5+ years, something similar to chess.js and I think it's slowly getting there... The library stores the moves history in an object with information like (fen, from_square, to_square, san, etc.), and also have some kind of "cursor" with the move index and some move-navigation helpers.
So with isepic-chess.js you can just call the board method board.fenHistoryExport() to get the FEN list after you parse the PGN game:
var example_pgn = `[Event "m1 London"]
[Site "?"]
[Date "1861.07.??"]
[Round "9"]
[White "Kolisch, Ignatz"]
[Black "Anderssen, Adolf"]
[Result "0-1"]
[Annotator "JvR"]
[SetUp "1"]
[FEN "5r1k/pp4pp/3r3q/8/3PpP1P/1P2NbP1/PB1Q3K/R7 b - - 0 30"]
[PlyCount "13"]
[EventDate "1861.??.??"]
30... Rxf4 $1 {Anderssen starts fireworks.} 31. Qe1 (31.gxf4 $2 Qxh4+ 32.Kg1
Rg6+) 31... Rg6 (31...Rxh4+ $1 32.gxh4 Rg6 $1) 32. Bc1 (32.Ng2 $1) 32... Rxh4+
$1 33. gxh4 Qf4+ 34. Kh3 Bg2+ $1 35. Nxg2 Qf3+ 36. Kh2 Qxg2# { Anderssen won
the match by this mate (+4, =2, -3).} 0-1`;
var board = Ic.initBoard({
pgn : example_pgn
});
console.log(board.fenHistoryExport());
There is a more complete node.js example in the README.md with the const {Ic} = require("isepic-chess"); import thingy to have it running in node.js.

Resources