donmccurdy / glTF-Transform

glTF 2.0 SDK for JavaScript and TypeScript, on Web and Node.js.
https://gltf-transform.dev
MIT License
1.42k stars 150 forks source link

Accepting standard input and output with CLI #1172

Open TyLindberg opened 1 year ago

TyLindberg commented 1 year ago

Is your feature request related to a problem? Please describe. When thinking about composing multiple glTF-Transform CLI commands together, my understanding is that right now you would need to output the result from a previous command to a temporary file in order to use it in the next command. For those looking to build simple glTF pipelines using the glTF-Transform CLI, it could greatly simplify the process if commands could accept standard input or output in some way.

Describe the solution you'd like I'm very open to thoughts here, but I was thinking that using - to represent standard input or output would be a clean way to both follow convention and be minimally disruptive to the CLI. I believe it would be forced to assume - was a glb file input or output, but for the use case of stringing together commands I think that would be totally acceptable. Below is an example of what a simple glTF-Transform CLI pipeline would look like with this convention.

gltf-transform unweld input.glb - | gltf-transform tangents - - | gltf-transform weld - output.glb

For optimization pipeline scenarios, this would cover the case where users want more fine-grained access than the optimize CLi utility offers.

Additionally, in order for this to work, all CLI log output would need to be logged to stderr. This may already by the case with the CLI, but would need confirmation.

Describe alternatives you've considered I've also considered scenarios such as passing a --stdin or --stdout flag. However, with the input and output files being required positional arguments at this point in time, I think that would be a more disruptive change than the solution proposed above.

Additional context If there is interest/value in adding this, then I'd be happy to take a look into what it would take to get added in. Also, if I'm totally missing the mark and there is a simpler way to build a CLI pipeline, I'd be happy to hear that as well!

donmccurdy commented 1 year ago

The closest option available today would be creating a new command in a CLI config file. Then you'd execute the custom CLI pipeline with something like:

gltf-transform mycustomcommand in.glb out.glb --config path/to/config.mjs

Using a config file has the extra benefit of supporting custom glTF extensions, if needed.

I've looked a bit into chaining CLI commands before, and originally it felt unworkable because I would've needed to replace or fork caporal.js (https://github.com/mattallty/Caporal.js). I've since had to fork it anyway (https://github.com/donmccurdy/Caporal.js), so modifications there wouldn't be out of the question.

The other consideration might be performance. Serializing/deserializing the file to stdout for each command will cost a bit of time, and starting each node.js process can be 300-600ms too. So a syntax that keeps everything within one node.js process would run much faster.

Finally, if you're running a web application with an existing build step, there are options to bring glTF Transform into that with plugins for Vite or Rollup: https://github.com/nytimes/rd-bundler-3d-plugins

Related:

TyLindberg commented 12 months ago

These are some awesome points, and I didn't realize there was the capability to create custom commands.

I definitely hear you on performance, which would lead me to say that such a solution wouldn't be recommended in a production environment.

I suppose the use case that comes into my head would be writing quick scripts to process glTF files on one's local computer. For instance, writing a bash script to process a directory of glb files using multiple glTF-Transform commands. Without chaining or a custom command, this process would be pretty cumbersome to manage the intermediate files between each step. The reason I would lean towards command chaining is that it does not require the user to understand the JS API of glTF-Transform, and hence someone with less familiarity could more easily derive benefit.

I do also wonder if there would be a possible way to chain multiple cli commands within one call to gltf-transform. Something like

gltf-transform unweld input.glb - THEN tangents - - THEN weld - output.glb

Seems a bit tricky of surface level, but would potentially allow avoidance of multiple node.js startups.

donmccurdy commented 11 months ago

In theory I'm fine with chaining through stdout or chaining with a single call, either way. The second would give better performance, and I suspect it's easier to implement on Caporal.js, but I'm not sure... if someone would like to have a look at either of these ideas, please do! I think my main concern would just be making sure it's a stable and simple enough implementation and doesn't add a lot to maintenance cost. Throwing out Caporal.js would be a big cost.

Meanwhile config files are common enough if you're working with things like Vite, Babel, Webpack, Rollup, etc., that I don't think it's a huge burden to have a config file for your 3D asset pipeline, and that does not increase project maintenance cost (a big plus for me! 😅).

TyLindberg commented 11 months ago

Yup, this totally makes sense to me. When I get a free moment I'll take a look and see what it might take to get such a system working. I'll update this thread with what I find.