inlife / nexrender

📹 Data-driven render automation for After Effects
https://www.nexrender.com
MIT License
1.63k stars 325 forks source link

Source data from JSON or SRT from inside script #304

Closed LazerJesus closed 4 years ago

LazerJesus commented 4 years ago

Hi, i am loading a script as an asset. said script reads a text/srt file that i copy to the workfolder in a prerender job.

      {
        type: "script",
        src: `http://localhost:${port}/assets/${subtitleScript}`,
      },
    ],
    actions: {
      prerender: [
        {
          module: "@nexrender/action-copy",
          input: process.cwd() + `/assets/${subtitleSRT}`,
          output: "sub.srt",
        },
      ],

(i disabled the postrender check in action-copy)

when run, the job throws

aerender ERROR: Error executing script: /Users/finnfrotscher/code/nex/test1/tmp/98W0llgzRff0q-ciUBZ50/nexrender-98W0llgzRff0q-ciUBZ50-script.jsx
TypeError: undefined is not an object
aerender ERROR: Runtime error in After Effects.

how can i see which line failed? what is your prefered way to access data from an external source into a script?

LazerJesus commented 4 years ago

does the script have access to a logging while rendering inside aerender?

inlife commented 4 years ago

The easiest way to figure out where the error happens would probably be to use ExtendScript Toolkit/Debugger. Just make sure to prevent nexrender from removing that folder via --skip-cleanup, and then open temporary project, and try to debug it manually.

As far as I know, there is no easy way to access logging from internal scripting. I might be wrong on this one tho.

LazerJesus commented 4 years ago

i am doing that. yesterday, the generated script would not run when passed to aerender but when run inside the debugger, there was no issue. Anyway i resolved that. coming back to the original question: how do i load a json or srt file into the temp folder? is this prerender copy pattern the only way?

inlife commented 4 years ago

Hm, that actually brings up a good question, nexrender lacks an asset type to just put a simple file same way as it does for image/video/audio files. Would that approach work for you (adding json/srt file as a nexrender job asset)?

LazerJesus commented 4 years ago

how would I access that asset? if the asset is copied to the temp folder and i could read it from my script with a simple fs.read, that would work for me. but all that would change is that i move the

prerender: [{
       module: "@nexrender/action-copy",
       input: process.cwd() + `/assets/${subtitleSRT}`,
       output: "sub.srt" },

to

assets: [{
        type: "script",
        src: `http://localhost:${port}/assets/${subtitleSRT}` },

Is that necessary?

more advanced parsing out of the box might be cool, but i dont see how that might be implemented.

LazerJesus commented 4 years ago

my current solution is to read my Script in job.js, += the content of the the SRT and src: base64,${script+srt} it.

LazerJesus commented 4 years ago

A way to import type static would be super nice. i propose:

{
  type: "static",
  src: `file, http, base64`,
  name: "globalVariableName"
}

where the file content is stored in globalVariableName as plain text. or if we add another key parser, we could supply a parser module that is called with the plain text and returns an object, which is then stored in globalVariableName

inlife commented 4 years ago

@FinnFrotscher where that globalVariableName would exist? is it a scripting variable or what is that?

LazerJesus commented 4 years ago

its a variable that is added at the beginning of the generated jsx script nexrender-${id}-script.jsx as far as i understand, all the scripts i add as assets are bundled into this script. by adding it as a variable in the beginning of the generated script, my custom scripts should be able to access the variable at runtime.

inlife commented 4 years ago

I see. So you would be able to access the "content" of that custom data inside of the scripting env. I'll think about it a bit more, but overall, yeah, I don't see a reason why not add something like that! :)

LazerJesus commented 4 years ago

i see another strategy. its also possible to copy the specified file to the tmp directory and provide a global function to access its contents. a global function

readDataFile(name){
   return fs.readSync(tmpPath + name)
}

tbh, i dont have any prefered strategy and as long as i have a way to solve the problem, i am good. i am overall impressed with the quality of the code! thank you :)

inlife commented 4 years ago

Sure, I'll think about a fitting solution

i am overall impressed with the quality of the code! thank you :)

Oh thanks, that very nice to hear 😄

maxtkacz commented 4 years ago

@FinnFrotscher Hey Finn, any chance you’d be willing to share your SRT parsing script? I’ve had mixed success with expression based parsing functions (and performance was shoddy) and would rather not reinvent the wheel. Let me know :) thanks!

mackenly commented 4 years ago

+1 on what @maxtkacz said. It's has been very difficult to get anything to work or find a solution.

LazerJesus commented 4 years ago

hey, i cant pass on my script, sadly. but my general approach was to avoid expressions completely and build a custom .jsx script. I tried multiple ways of loading the srt file's text content. passing it to NX as a string and deciding it inside ae turned out to work the best. then i set keyframes for the text property. subtitleLayer.property("Source Text").setValueAtTime is the magic function

mackenly commented 4 years ago

@FinnFrotscher That's 100% understandable. Thank you!

inlife commented 4 years ago

A new static asset type was introduced in 1.14.0, please share your feedback