This message from before was a pop-up in OctoPrint. I suspect exit 4 would cause the same.
Working on this in my head (got a lot of driving to do in the next few hours on the back roads - good time to think!). I want to clarify a couple things before I start writing a script.
-
I get that the {input} info is tokenized. So is it like a wildcard, with one filename, or is it a list of filenames? My understanding is that it's probably possible to replace the %d found in one example with a wildcard, which would mean that data is one filename that ffmpeg would expand on its own.
-
Is there any way to trigger this script from within OctoPrint other than printing something and having it trigger at the end of the print?
As for the %d - that is a wild card used inside ffmpeg to convert a series of stills into a movie. Since the {output} is supplied by OctoPrint it is for ffmpeg. But the move/copy shell commands use bash and therefore do not "glob" on the %d but need the * as multiple file wild card.
As for #2 - no. Doesn't mean you can't just run the script from the command line... You will probably have to get some files for it to work on.
I'm wondering if this is possible. At a glance, it looks like it might be possible to do this in the form of another plugin. My reason for wanting that is because there are times I'd be upgrading or moving from one Pi to another and would backup the OctoPrint configuration. I don't want to also have to remember to copy over script files and so on.
The catch is, as of now, I think this would still need an executable or script included somehow.
I'm thinking of a 2nd plugin, "Delayed Timelapse Generator." Would a plugin be able to read the ffmpeg path and the other settings for the Timelapse function in OctoPrint? And maybe edit them?
It could read the settings from Timelapse and import them. It would also add a button, "Render pending timelapse videos." If it could edit timelapse settings, it would read the settings like ffmpeg path and the ffmpeg options. Then it could replace the ffmpeg path with a path to a harmless command like pwd. So when the print was done, the timelapse stills would be there, but nothing would happen (other than calling a command that does a quick return). But there would be a button on the UI now, so when it's pressed, this new plugin would render any outstanding timelapses. It might even include a checklist, so the user can specify which outstanding timelapses to render and which to delete.
I place all my scripts in the .octoprint/scripts/ directory. OctoPrint happily backs them up with the rest.
{input}
is just a single string with the %d token. You might be able to use bash parameter expansion or sed to replace %d
with *
?
You can always "print" something simple like a 2x2x2mm cube without any filament. With a .2mm layer height that should give you about 10 snapshots to process.
I just enable the virtual printer for testing to avoid wasting filament and cancel the print after 30ish seconds and on a timed snapshot timelapse that gets enough to validate bash script.
test.sh
#!/usr/bin/bash
mkdir $2
echo $1 >> /home/pi/output.txt
exit 0
I tried echoing $2 to the same file and it throws errors for some reason, but mkdir seems to work fine. It creates a folder named what the output filename would be in the timelpase folder, notice the fail added to the end because it was rendered after cancel.
result in output.txt
/home/pi/.octoprint/timelapse/tmp/Shape-Box_PLA+_205_20240911003725-%d.jpg
-sseof
not sure what that last bit -sseof bit is.
one thing I did learn, once the process returns without error the snapshots are deleted automatically from the tmp folder.
appears this is tied to the timelapse post-roll setting, and it appends to the "ffmpeg command line" automatically, even if the value is 0. so you would have to account for that as well.
@jneilliii: Just a thought here - actually three (asking you since you have experience writing plugins):
-
What is the original OctoPrint written in? Python? I can see the info on writing plugins that those are in Python.
-
I like minimal changes or interference with existing code, but I'm thinking that it might be possible to write a plugin that would use the ffmpeg path and read the ffmepg command line arguments and use them in the plugin, while changing the ffmpeg command line in the main settings to not run ffmepg (or run it with "--help," so it runs and does nothing). Then use the info from the command line arguments to know how to run it, and add a button so one click of the button would render one or all pending timelapses (or render ones checked off in a list). Any thoughts on that?
-
I'm thinking I've seen other people ask about this issue and that what would fix it would be a checkbox on the Timelapse settings page, "Render Timelapse on command, not after print completion," and adding a button, "Render Timelapses" on the main control page. How involved and indepth would writing code like that and submitting it as a feature be? I've done a lot of coding, but I'm self-taught and have done very little work where I had to work directly with a group of programmers. (I've submitted to FOSS projects, but that was before 2010 and, in those cases, I wrote my stuff, sent it in, and let them decide and just got out of the way. Some stuff was accepted, some was not.)
mix of python, knockout, and jinja templating.
based on the other recent discovery about the files being deleted after completion not sure how well that would work unless you were to forcibly cause an error on your ffmpeg command. of course, anything is probably doable, but the shell script approach seems to be working for me in my testing (see below).
I haven't really looked to in-depth on the timelapse code, but seems like it would be fairly minimal changes to implement in core.
I'm also self-taught programming and can tell you that your experience interacting with the primary OctoPrint developer to be easy to work with. Just make sure to read over the contribution guidelines, so that you're submitting PRs against the right branch, etc. I agree this has been a feature request on the books for some time.
updated test.sh...
#!/usr/bin/bash
mkdir $2
clipped_string=${1:0:-11}
cp $clipped_string*.jpg $2
the above will strip the end of the input token string using bash shell parameter expansion , create a directory in timelapse folder named based on the timelapse job, and then copy the files from tmp to that location.
EDIT: the only downside is that because the file ends up in the timelapse folder it is listed in the rendered tielapses section but because it's a folder, you can view it or download, etc...
this wouldn't be an issue if you were sending it elsewhere though...
Besides my edit above, one other thing I noticed is that {output}
is actually naming the file preceded by .
, making it hidden until the rendering process is completed, but again not relevant unless you decide to use it in your script. The folder was getting renamed removing the leading .
on render completion.
Quick update...going to bed now...I swear, fun hack though.
test.sh
#!/usr/bin/bash
touch $2
clipped_string=${1:0:-11}
destination_folder=/home/pi/${2:31}
mkdir $destination_folder
cp $clipped_string*.jpg $destination_folder
creates an empty file based on {output}
, makes a directory in user's home folder based on just the timelapse filename (could be substituted of course to your nas/smb share), copies the files into that folder. if your username is different you would have to adjust the offset (31) for $destination_folder.
the idea of the empty file allows for OctoPrint's process of renaming hidden filename and acts as kind of a placeholder where you can send the rendered output back, or replace empty file with symlink to nas share, etc.
FWIW, rendering timelapses later instead of immediately has been added via a PR earlier this year, it just was too late for inclusion in 1.10.x and thus will only be available from 1.11.0 forward:
And the only thing missing to enable plugins to take control of the render process would be a hook to override the default render code, for which I'd love to see a PR Then plugins could implement that hook and take care of rendering timelapses somewhere else.
Rendering elsewhere would be nice!
I'm not sure I read all the infromation properly, but it looks like this will allow a setting to only render for cancelled prints. That can be quite useful. What I didn't see was an alternative for rendering. In other words, it seemed like the choice was to render or just not render in OctoPrint unless doing it by hand later.
Am I missing something?
Not quite, looking at the code changes...
# Determines whether rendering the timelapse should be done automatically after the print is finished. # This can be done always, only after successful prints, only after failed prints, or never. renderAfterPrint: always
So this will do part of what I want, which means no point in doing a plugin that chagnes the Timelapse settings to not do it on completion.
But it looks to me like a plugin that lets you click a button and render one or more pending timelapses would work.
That raises a few questions - asking now in case anyone knows this or has figured this out. Are the still images stored with names that mark the job and time it is run? Or would a timelapse image from one job possibly be written over another earlier job? Or is it possible they could get mixed in together? I'm thinking that unless the images are stored in a directory or all have a matching timestamp or job ID in the name (like "Vent_Faceplate-PLA-2024-0918-1351-.jpeg") it would be hard to go back and track which images belong to which print job.
It also occurs to me that if the images are there but there's nothing to render it later, that they are not being deleted. (Or are they completed if it's successful and no timelapse is generated?)
I've looked into the plugin dev info to some extent, but have a lot more to go. I'm wondering if a plugin can somehow at least read the path to ffmpeg from OctoPrint and the command line used. If it could also alter them, that'd help a lot.
The more I think about this, it's nice that there's work to keep timelapses from rendering on job completion, but it seems like this solution creates more issues that would still need to be solved. One is what happens to the images after the print? If they're deleted, what if, after looking over the print, the user wants to render a timelapse to check on it? Conversely, what if the timelapse is not rendered and the images are not deleted?
Yes, each 'job' is a Part-Start_time-image format.No way you could mix them up, unless you stored them off instance and started the same identical named parts on two printers within 1 second of each other and stored them in the same directory and not under the printer's name like sane people would do .... just cause you where trying to mess it up.
File size - sorry - Image size will limit how long to keep unprocessed shots around. Large/high resolution images chew up disk space really fast.
I was thinking if I offloaded them, I'd store them in a folder named to match the printer, so this would be no issue.
What I'm not clear about is auto-deletion. I think we established that, under current circumstances, when the timelapse is rendered, the stills are deleted. So if the print is cancelled and a timelapse is rendered, I would expect the stills to be deleted when that's done. But what if a timelapse is not rendered? Are the images auto-deleted anyway?
Of course, writing anything to render the timelapse later would have to include auto-deletion when the rendering is done.
At this point, and I'm very slow at planning something ilke this out before I write it, I'm taking this new feature under consideration, but I still can't decide the best way to do what I want. I can see several options:
-
Write a plugin that renders timelapses on command (when a button is pressed). The issue, for me, is that I haven't written an interface in HTML since 2005 or before. I remember nothing of CSS and know very little advanced HTML. I think a plugin that renders timelapses on command needs to be started with a button, then present a list of all unrendered timelapses and allow the user to select one or more and either delete them or render them. It's been so long jsut presenting a list with checkboxes to select an item is going to take me a while to learn. The backend work on that - reading the files to find out what timelapses are unrendered, deleting them when, rendering, and so on, is easy. I just haven't done HTML programming in so long, that'd take me a good while. (Unless there are routines in an OctoPrint API that lets me do that.)
-
Render off-system - good in many ways, but I like the idea of doing as much as possible on the current system, so it's just a matter of installing one plugin and it's done. Rendering off system means code that works on Linux, Mac, and Windows (and possiblly other systems) and it means having to install a plugin on the OctoPrint system and install it on the other system.
From my point of view, I see issues with either of these methods and haven't figured out which way I'd like to go. I've also wondered if it's possible to setup a delay, so rendering won't start until the printer has been idle for a set time. This gives someone time to start a new print after one is done without having to wait for rendering.
That's built in - unrendered timelapses have a button next to them to allow to render them on demand (after successful rendition, the source files will be deleted):
So setting it to never automatically render a timelapse will give you full manual control over the process, with the caveat that a clean-up process is in place that will delete unrendered timelapse files after 7 days (by default - this can be configured through webcam.cleanTmpAfterDays
however and you could just as well set it to 365 to have a full year).
A good suggestion, I'll look into adding that for 1.11.0.