Merge branch 'Mikk36-devel' into devel
This commit is contained in:
commit
141725d002
8 changed files with 88 additions and 34 deletions
|
|
@ -90,6 +90,7 @@
|
|||
* Added a link to scroll to the end of the terminal log (useful for when autoscroll is disabled)
|
||||
* Added a link to select all current contents of the terminal log for easy copy-pasting
|
||||
* Added a display of how many lines are displayed, how many are filtered and how many are available in total
|
||||
* Frame rate for timelapses can now be configured per timelapse ([#782](https://github.com/foosel/OctoPrint/pull/782))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ __copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms
|
|||
|
||||
import os
|
||||
|
||||
from flask import request, jsonify, url_for
|
||||
from flask import request, jsonify, url_for, make_response
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
import octoprint.timelapse
|
||||
|
|
@ -30,9 +30,11 @@ def getTimelapseData():
|
|||
if timelapse is not None and isinstance(timelapse, octoprint.timelapse.ZTimelapse):
|
||||
config["type"] = "zchange"
|
||||
config["postRoll"] = timelapse.postRoll()
|
||||
config["fps"] = timelapse.fps()
|
||||
elif timelapse is not None and isinstance(timelapse, octoprint.timelapse.TimedTimelapse):
|
||||
config["type"] = "timed"
|
||||
config["postRoll"] = timelapse.postRoll()
|
||||
config["fps"] = timelapse.fps()
|
||||
config.update({
|
||||
"interval": timelapse.interval()
|
||||
})
|
||||
|
|
@ -70,26 +72,46 @@ def setTimelapseConfig():
|
|||
config = {
|
||||
"type": request.values["type"],
|
||||
"postRoll": 0,
|
||||
"fps": 25,
|
||||
"options": {}
|
||||
}
|
||||
|
||||
|
||||
if "postRoll" in request.values:
|
||||
try:
|
||||
config["postRoll"] = int(request.values["postRoll"])
|
||||
postRoll = int(request.values["postRoll"])
|
||||
except ValueError:
|
||||
pass
|
||||
return make_response("Invalid value for postRoll: %r" % request.values["postRoll"], 400)
|
||||
else:
|
||||
if postRoll >= 0:
|
||||
config["postRoll"] = postRoll
|
||||
else:
|
||||
return make_response("Invalid value for postRoll: %d" % postRoll, 400)
|
||||
|
||||
if "fps" in request.values:
|
||||
try:
|
||||
fps = int(request.values["fps"])
|
||||
except ValueError:
|
||||
return make_response("Invalid value for fps: %r" % request.values["fps"], 400)
|
||||
else:
|
||||
if fps > 0:
|
||||
config["fps"] = fps
|
||||
else:
|
||||
return make_response("Invalid value for fps: %d" % fps, 400)
|
||||
|
||||
if "interval" in request.values:
|
||||
interval = 10
|
||||
config["options"] = {
|
||||
"interval": 10
|
||||
}
|
||||
|
||||
try:
|
||||
interval = int(request.values["interval"])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
config["options"] = {
|
||||
"interval": interval
|
||||
}
|
||||
return make_response("Invalid value for interval: %r" % request.values["interval"])
|
||||
else:
|
||||
if interval > 0:
|
||||
config["options"]["interval"] = interval
|
||||
else:
|
||||
return make_response("Invalid value for interval: %d" % interval)
|
||||
|
||||
if admin_permission.can() and "save" in request.values and request.values["save"] in valid_boolean_trues:
|
||||
octoprint.timelapse.configureTimelapse(config, True)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ default_settings = {
|
|||
"timelapse": {
|
||||
"type": "off",
|
||||
"options": {},
|
||||
"postRoll": 0
|
||||
"postRoll": 0,
|
||||
"fps": 25
|
||||
}
|
||||
},
|
||||
"gcodeViewer": {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -4,9 +4,14 @@ $(function() {
|
|||
|
||||
self.loginState = parameters[0];
|
||||
|
||||
self.defaultFps = 25;
|
||||
self.defaultPostRoll = 0;
|
||||
self.defaultInterval = 10;
|
||||
|
||||
self.timelapseType = ko.observable(undefined);
|
||||
self.timelapseTimedInterval = ko.observable(undefined);
|
||||
self.timelapsePostRoll = ko.observable(undefined);
|
||||
self.timelapseTimedInterval = ko.observable(self.defaultInterval);
|
||||
self.timelapsePostRoll = ko.observable(self.defaultPostRoll);
|
||||
self.timelapseFps = ko.observable(self.defaultFps);
|
||||
|
||||
self.persist = ko.observable(false);
|
||||
self.isDirty = ko.observable(false);
|
||||
|
|
@ -42,6 +47,9 @@ $(function() {
|
|||
self.timelapsePostRoll.subscribe(function(newValue) {
|
||||
self.isDirty(true);
|
||||
});
|
||||
self.timelapseFps.subscribe(function(newValue) {
|
||||
self.isDirty(true);
|
||||
});
|
||||
|
||||
// initialize list helper
|
||||
self.listHelper = new ItemListHelper(
|
||||
|
|
@ -91,15 +99,23 @@ $(function() {
|
|||
self.listHelper.updateItems(response.files);
|
||||
|
||||
if (config.type == "timed") {
|
||||
if (response.config.interval != undefined && response.config.interval > 0) {
|
||||
self.timelapseTimedInterval(response.config.interval);
|
||||
}
|
||||
if (response.config.postRoll != undefined && response.config.postRoll >= 0) {
|
||||
self.timelapsePostRoll(response.config.postRoll);
|
||||
if (config.interval != undefined && config.interval > 0) {
|
||||
self.timelapseTimedInterval(config.interval);
|
||||
}
|
||||
} else {
|
||||
self.timelapseTimedInterval(undefined);
|
||||
self.timelapsePostRoll(undefined);
|
||||
self.timelapseTimedInterval(self.defaultInterval);
|
||||
}
|
||||
|
||||
if (config.postRoll != undefined && config.postRoll >= 0) {
|
||||
self.timelapsePostRoll(config.postRoll);
|
||||
} else {
|
||||
self.timelapsePostRoll(self.defaultPostRoll);
|
||||
}
|
||||
|
||||
if (config.fps != undefined && config.fps > 0) {
|
||||
self.timelapseFps(config.fps);
|
||||
} else {
|
||||
self.timelapseFps(self.defaultFps);
|
||||
}
|
||||
|
||||
self.persist(false);
|
||||
|
|
@ -137,6 +153,7 @@ $(function() {
|
|||
var payload = {
|
||||
"type": self.timelapseType(),
|
||||
"postRoll": self.timelapsePostRoll(),
|
||||
"fps": self.timelapseFps(),
|
||||
"save": self.persist()
|
||||
};
|
||||
|
||||
|
|
@ -167,4 +184,4 @@ $(function() {
|
|||
["loginStateViewModel"],
|
||||
"#timelapse"
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ table {
|
|||
}
|
||||
|
||||
#temp_newTemp, #temp_newBedTemp, #speed_innerWall, #speed_outerWall, #speed_fill, #speed_support,
|
||||
#webcam_timelapse_interval, #webcam_timelapse_postRoll {
|
||||
#webcam_timelapse_interval, #webcam_timelapse_postRoll, #webcam_timelapse_fps {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@
|
|||
<option value="timed">{{ _('Timed') }}</option>
|
||||
</select>
|
||||
|
||||
<label for="webcam_timelapse_fps">{{ _('Timelapse frame rate (in frames per second)') }}</label>
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-mini" id="webcam_timelapse_fps" data-bind="value: timelapseFps, valueUpdate: 'afterkeydown', enable: isOperational() && !isPrinting() && loginState.isUser() && timelapseTypeSelected()">
|
||||
<span class="add-on">{{ _('fps') }}</span>
|
||||
</div>
|
||||
|
||||
<label for="webcam_timelapse_postRoll">{{ _('Timelapse post roll (in rendered seconds)') }}</label>
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-mini" id="webcam_timelapse_postRoll" data-bind="value: timelapsePostRoll, valueUpdate: 'afterkeydown', enable: isOperational() && !isPrinting() && loginState.isUser() && timelapseTypeSelected()">
|
||||
|
|
|
|||
|
|
@ -76,18 +76,22 @@ def configureTimelapse(config=None, persist=False):
|
|||
type = config["type"]
|
||||
|
||||
postRoll = 0
|
||||
if "postRoll" in config:
|
||||
if "postRoll" in config and config["postRoll"] >= 0:
|
||||
postRoll = config["postRoll"]
|
||||
|
||||
fps = 25
|
||||
if "fps" in config and config["fps"] > 0:
|
||||
fps = config["fps"]
|
||||
|
||||
if type is None or "off" == type:
|
||||
current = None
|
||||
elif "zchange" == type:
|
||||
current = ZTimelapse(postRoll=postRoll)
|
||||
current = ZTimelapse(postRoll=postRoll, fps=fps)
|
||||
elif "timed" == type:
|
||||
interval = 10
|
||||
if "options" in config and "interval" in config["options"]:
|
||||
if "options" in config and "interval" in config["options"] and config["options"]["interval"] > 0:
|
||||
interval = config["options"]["interval"]
|
||||
current = TimedTimelapse(postRoll=postRoll, interval=interval)
|
||||
current = TimedTimelapse(postRoll=postRoll, interval=interval, fps=fps)
|
||||
|
||||
notifyCallbacks(current)
|
||||
|
||||
|
|
@ -97,7 +101,7 @@ def configureTimelapse(config=None, persist=False):
|
|||
|
||||
|
||||
class Timelapse(object):
|
||||
def __init__(self, postRoll=0):
|
||||
def __init__(self, postRoll=0, fps=25):
|
||||
self._logger = logging.getLogger(__name__)
|
||||
self._imageNumber = None
|
||||
self._inTimelapse = False
|
||||
|
|
@ -111,7 +115,7 @@ class Timelapse(object):
|
|||
self._movieDir = settings().getBaseFolder("timelapse")
|
||||
self._snapshotUrl = settings().get(["webcam", "snapshot"])
|
||||
|
||||
self._fps = 25
|
||||
self._fps = fps
|
||||
|
||||
self._renderThread = None
|
||||
self._captureMutex = threading.Lock()
|
||||
|
|
@ -127,6 +131,9 @@ class Timelapse(object):
|
|||
def postRoll(self):
|
||||
return self._postRoll
|
||||
|
||||
def fps(self):
|
||||
return self._fps
|
||||
|
||||
def unload(self):
|
||||
if self._inTimelapse:
|
||||
self.stopTimelapse(doCreateMovie=False)
|
||||
|
|
@ -267,7 +274,7 @@ class Timelapse(object):
|
|||
|
||||
# prepare ffmpeg command
|
||||
command = [
|
||||
ffmpeg, '-loglevel', 'error', '-i', input, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', str(self._fps), '-y', '-b:v', bitrate,
|
||||
ffmpeg, '-framerate', str(self._fps), '-loglevel', 'error', '-i', input, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', str(self._fps), '-y', '-b', bitrate,
|
||||
'-f', 'vob']
|
||||
|
||||
filters = []
|
||||
|
|
@ -335,8 +342,8 @@ class Timelapse(object):
|
|||
|
||||
|
||||
class ZTimelapse(Timelapse):
|
||||
def __init__(self, postRoll=0):
|
||||
Timelapse.__init__(self, postRoll=postRoll)
|
||||
def __init__(self, postRoll=0, fps=25):
|
||||
Timelapse.__init__(self, postRoll=postRoll, fps=fps)
|
||||
self._logger.debug("ZTimelapse initialized")
|
||||
|
||||
def eventSubscriptions(self):
|
||||
|
|
@ -370,8 +377,8 @@ class ZTimelapse(Timelapse):
|
|||
|
||||
|
||||
class TimedTimelapse(Timelapse):
|
||||
def __init__(self, postRoll=0, interval=1):
|
||||
Timelapse.__init__(self, postRoll=postRoll)
|
||||
def __init__(self, postRoll=0, interval=1, fps=25):
|
||||
Timelapse.__init__(self, postRoll=postRoll, fps=fps)
|
||||
self._interval = interval
|
||||
if self._interval < 1:
|
||||
self._interval = 1 # force minimum interval of 1s
|
||||
|
|
|
|||
Loading…
Reference in a new issue