# still images
'output_pictures': False,
- 'emulate_motion': False,
'snapshot_interval': 0,
'picture_filename': '',
'snapshot_filename': '',
+ 'quality': max(1, int(ui['image_quality'])),
'@preserve_pictures': int(ui['preserve_pictures']),
+ # movies
+ 'ffmpeg_output_movies': False,
+ 'movie_filename': ui['movie_file_name'],
+ 'ffmpeg_bps': 44000, # a quality of about 85% for 320x240x2fps
+ 'max_movie_time': ui['max_movie_length'],
+ '@preserve_movies': int(ui['preserve_movies']),
+
# motion detection
'@motion_detection': ui['motion_detection'],
+ 'emulate_motion': False,
'text_changes': ui['show_frame_changes'],
'locate_motion_mode': ui['show_frame_changes'],
'noise_tune': ui['auto_noise_detect'],
'post_capture': int(ui['post_capture']),
'minimum_motion_frames': int(ui['minimum_motion_frames']),
- # movies
- 'ffmpeg_output_movies': ui['motion_movies'],
- 'movie_filename': ui['movie_file_name'],
- 'ffmpeg_bps': 44000, # a quality of about 85% for 320x240x2fps
- 'max_movie_time': ui['max_movie_length'],
- '@preserve_movies': int(ui['preserve_movies']),
-
# working schedule
'@working_schedule': '',
data['emulate_motion'] = True
data['picture_filename'] = ui['image_file_name']
- data['quality'] = max(1, int(ui['image_quality']))
-
+ if ui['movies']:
+ data['ffmpeg_output_movies'] = True
+ recording_mode = ui['recording_mode']
+ if recording_mode == 'motion-triggered':
+ data['emulate_motion'] = False
+
+ elif recording_mode == 'continuous':
+ data['emulate_motion'] = True
+
if proto == 'v4l2':
- max_val = data['width'] * data['height'] * data['framerate'] / 3
+ max_val = data['width'] * data['height'] * data['framerate']
- else: # always assume a netcam image size of 640x480, since we have no means to know it at this point
- max_val = 640 * 480 * data['framerate'] / 3
-
+ else: # assume a netcam image size of 640x480, since we have no means to know it at this point
+ max_val = 640 * 480 * data['framerate']
+
max_val = min(max_val, 9999999)
-
- data['ffmpeg_bps'] = int(ui['movie_quality']) * max_val / 100
+
+ data['ffmpeg_bps'] = int(int(ui['movie_quality']) * max_val / 100)
# working schedule
if ui['working_schedule']:
'still_images': False,
'capture_mode': 'motion-triggered',
'image_file_name': '%Y-%m-%d/%H-%M-%S',
- 'image_quality': 85,
+ 'image_quality': data['quality'],
'snapshot_interval': 0,
'preserve_pictures': data['@preserve_pictures'],
+ # movies
+ 'movies': False,
+ 'recording_mode': 'motion-triggered',
+ 'movie_file_name': data['movie_filename'],
+ 'max_movie_length': data['max_movie_time'],
+ 'preserve_movies': data['@preserve_movies'],
+
# motion detection
'motion_detection': data['@motion_detection'],
'show_frame_changes': data['text_changes'] or data['locate_motion_mode'],
'post_capture': int(data['post_capture']),
'minimum_motion_frames': int(data['minimum_motion_frames']),
- # motion movies
- 'motion_movies': data['ffmpeg_output_movies'],
- 'movie_file_name': data['movie_filename'],
- 'max_movie_length': data['max_movie_time'],
- 'preserve_movies': data['@preserve_movies'],
-
# motion notifications
'email_notifications_enabled': False,
'web_hook_notifications_enabled': False,
snapshot_interval = data['snapshot_interval']
snapshot_filename = data['snapshot_filename']
- if (((emulate_motion or output_pictures) and picture_filename) or
- (snapshot_interval and snapshot_filename)):
-
- ui['still_images'] = True
+ ui['still_images'] = (((emulate_motion or output_pictures) and picture_filename) or
+ (snapshot_interval and snapshot_filename))
- if emulate_motion:
- ui['capture_mode'] = 'all-frames'
+ if emulate_motion:
+ ui['capture_mode'] = 'all-frames'
+ if picture_filename:
ui['image_file_name'] = picture_filename
-
- elif snapshot_interval:
- ui['capture_mode'] = 'interval-snapshots'
+
+ elif snapshot_interval:
+ ui['capture_mode'] = 'interval-snapshots'
+ ui['snapshot_interval'] = snapshot_interval
+ if snapshot_filename:
ui['image_file_name'] = snapshot_filename
- ui['snapshot_interval'] = snapshot_interval
-
- elif output_pictures:
- ui['capture_mode'] = 'motion-triggered'
- ui['image_file_name'] = picture_filename
-
- ui['image_quality'] = data['quality']
+
+ elif output_pictures:
+ ui['capture_mode'] = 'motion-triggered'
+ if picture_filename:
+ ui['image_file_name'] = picture_filename
+
+ if data['ffmpeg_output_movies']:
+ ui['movies'] = True
+
+ if emulate_motion:
+ ui['recording_mode'] = 'continuous'
+ else:
+ ui['recording_mode'] = 'motion-triggered'
+
ffmpeg_bps = data['ffmpeg_bps']
if ffmpeg_bps is not None:
if utils.v4l2_camera(data):
- max_val = data['width'] * data['height'] * data['framerate'] / 3
+ max_val = data['width'] * data['height'] * data['framerate']
else: # net camera
- max_val = 640 * 480 * data['framerate'] / 3
+ max_val = 640 * 480 * data['framerate']
max_val = min(max_val, 9999999)
}
/* ui elements that enable/disable other ui elements */
- $('#motionEyeSwitch').change(updateConfigUi);
- $('#showAdvancedSwitch').change(updateConfigUi);
- $('#storageDeviceSelect').change(updateConfigUi);
- $('#resolutionSelect').change(updateConfigUi);
- $('#leftTextSelect').change(updateConfigUi);
- $('#rightTextSelect').change(updateConfigUi);
- $('#captureModeSelect').change(updateConfigUi);
- $('#autoNoiseDetectSwitch').change(updateConfigUi);
- $('#videoDeviceSwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#textOverlaySwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#videoStreamingSwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#streamingServerResizeSwitch').change(updateConfigUi);
- $('#stillImagesSwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#preservePicturesSelect').change(updateConfigUi);
- $('#motionDetectionSwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#motionMoviesSwitch').change(checkMinimizeSection).change(updateConfigUi);
- $('#preserveMoviesSelect').change(updateConfigUi);
- $('#emailNotificationsSwitch').change(updateConfigUi);
- $('#webHookNotificationsSwitch').change(updateConfigUi);
- $('#commandNotificationsSwitch').change(updateConfigUi);
- $('#workingScheduleSwitch').change(checkMinimizeSection).change(updateConfigUi);
-
- $('#mondayEnabledSwitch').change(updateConfigUi);
- $('#tuesdayEnabledSwitch').change(updateConfigUi);
- $('#wednesdayEnabledSwitch').change(updateConfigUi);
- $('#thursdayEnabledSwitch').change(updateConfigUi);
- $('#fridayEnabledSwitch').change(updateConfigUi);
- $('#saturdayEnabledSwitch').change(updateConfigUi);
- $('#sundayEnabledSwitch').change(updateConfigUi);
+ $('#motionEyeSwitch').change(updateConfigUI);
+ $('#showAdvancedSwitch').change(updateConfigUI);
+ $('#storageDeviceSelect').change(updateConfigUI);
+ $('#resolutionSelect').change(updateConfigUI);
+ $('#leftTextSelect').change(updateConfigUI);
+ $('#rightTextSelect').change(updateConfigUI);
+ $('#captureModeSelect').change(updateConfigUI);
+ $('#autoNoiseDetectSwitch').change(updateConfigUI);
+ $('#videoDeviceSwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#textOverlaySwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#videoStreamingSwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#streamingServerResizeSwitch').change(updateConfigUI);
+ $('#stillImagesSwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#preservePicturesSelect').change(updateConfigUI);
+ $('#moviesSwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#motionDetectionSwitch').change(checkMinimizeSection).change(updateConfigUI);
+ $('#preserveMoviesSelect').change(updateConfigUI);
+ $('#emailNotificationsSwitch').change(updateConfigUI);
+ $('#webHookNotificationsSwitch').change(updateConfigUI);
+ $('#commandNotificationsSwitch').change(updateConfigUI);
+ $('#workingScheduleSwitch').change(checkMinimizeSection).change(updateConfigUI);
+
+ $('#mondayEnabledSwitch').change(updateConfigUI);
+ $('#tuesdayEnabledSwitch').change(updateConfigUI);
+ $('#wednesdayEnabledSwitch').change(updateConfigUI);
+ $('#thursdayEnabledSwitch').change(updateConfigUI);
+ $('#fridayEnabledSwitch').change(updateConfigUI);
+ $('#saturdayEnabledSwitch').change(updateConfigUI);
+ $('#sundayEnabledSwitch').change(updateConfigUI);
/* minimizable sections */
$('span.minimize').click(function () {
}
}
- updateConfigUi();
+ updateConfigUI();
});
$('a.settings-section-title').click(function () {
seenDependNames[depend] = true;
var control = $('#' + depend + 'Entry, #' + depend + 'Select, #' + depend + 'Slider, #' + depend + 'Switch');
- control.change(updateConfigUi);
+ control.change(updateConfigUI);
});
});
});
/* streaming framerate must be >= device framerate */
- $('#framerateSlider').change(function (val) {
+ $('#framerateSlider').change(function () {
var value = Number($('#framerateSlider').val());
var streamingValue = Number($('#streamingFramerateSlider').val());
}
});
+ /* capture mode and recording mode are not completely independent:
+ * all frames capture mode implies continuous recording (and vice-versa) */
+ $('#captureModeSelect').change(function (val) {
+ if ($('#captureModeSelect').val() == 'all-frames') {
+ $('#recordingModeSelect').val('continuous');
+ }
+ else {
+ if ($('#recordingModeSelect').val() == 'continuous') {
+ $('#recordingModeSelect').val('motion-triggered');
+ }
+ }
+
+ updateConfigUI();
+ });
+ $('#recordingModeSelect').change(function (val) {
+ if ($('#recordingModeSelect').val() == 'continuous') {
+ $('#captureModeSelect').val('all-frames');
+ }
+ else {
+ if ($('#captureModeSelect').val() == 'all-frames') {
+ $('#captureModeSelect').val('motion-triggered');
+ }
+ }
+
+ updateConfigUI();
+ });
+
/* preview controls */
$('#brightnessSlider').change(function () {pushPreview('brightness');});
$('#contrastSlider').change(function () {pushPreview('contrast');});
$('div.page-container').addClass('stretched');
$('div.settings-top-bar').addClass('open').removeClass('closed');
- updateConfigUi();
+ updateConfigUI();
}
function closeSettings() {
return $('div.settings').hasClass('open');
}
-function updateConfigUi() {
+function updateConfigUI() {
var objs = $('tr.settings-item, div.advanced-setting, table.advanced-setting, div.settings-section-title, table.settings, ' +
'div.check-box.camera-config, div.check-box.main-config');
$('#picturesLifetimeEntry').parents('tr:eq(0)').each(markHideLogic);
}
+ /* movies switch */
+ if (!$('#moviesSwitch').get(0).checked) {
+ $('#moviesSwitch').parent().next('table.settings').find('tr.settings-item').each(markHideLogic);
+ }
+
+ /* preserve movies */
+ if ($('#preserveMoviesSelect').val() != '-1') {
+ $('#moviesLifetimeEntry').parents('tr:eq(0)').each(markHideLogic);
+ }
+
/* motion detection switch */
if (!$('#motionDetectionSwitch').get(0).checked) {
$('#motionDetectionSwitch').parent().next('table.settings').find('tr.settings-item').each(markHideLogic);
- /* hide the entire motion movies section */
- $('#motionMoviesSwitch').parent().each(markHideLogic);
- $('#motionMoviesSwitch').parent().next('table.settings').each(markHideLogic);
-
/* hide the entire notifications section */
$('#emailNotificationsSwitch').parents('table.settings').prev().each(markHideLogic);
$('#emailNotificationsSwitch').parents('table.settings').each(markHideLogic);
$('#workingScheduleSwitch').parent().next('table.settings').each(markHideLogic);
}
- /* motion movies switch */
- if (!$('#motionMoviesSwitch').get(0).checked) {
- $('#motionMoviesSwitch').parent().next('table.settings').find('tr.settings-item').each(markHideLogic);
- }
-
- /* preserve movies */
- if ($('#preserveMoviesSelect').val() != '-1') {
- $('#moviesLifetimeEntry').parents('tr:eq(0)').each(markHideLogic);
- }
-
/* event notifications */
if (!$('#emailNotificationsSwitch').get(0).checked) {
$('#emailAddressesEntry').parents('tr:eq(0)').each(markHideLogic);
markHideIfNull('_' + name, id);
});
- updateConfigUi();
+ updateConfigUI();
}
function cameraUi2Dict() {
'snapshot_interval': $('#snapshotIntervalEntry').val(),
'preserve_pictures': $('#preservePicturesSelect').val() >= 0 ? $('#preservePicturesSelect').val() : $('#picturesLifetimeEntry').val(),
+ /* movies */
+ 'movies': $('#moviesSwitch')[0].checked,
+ 'movie_file_name': $('#movieFileNameEntry').val(),
+ 'movie_quality': $('#movieQualitySlider').val(),
+ 'recording_mode': $('#recordingModeSelect').val(),
+ 'max_movie_length': $('#maxMovieLengthEntry').val(),
+ 'preserve_movies': $('#preserveMoviesSelect').val() >= 0 ? $('#preserveMoviesSelect').val() : $('#moviesLifetimeEntry').val(),
+
/* motion detection */
'motion_detection': $('#motionDetectionSwitch')[0].checked,
'show_frame_changes': $('#showFrameChangesSwitch')[0].checked,
'post_capture': $('#postCaptureEntry').val(),
'minimum_motion_frames': $('#minimumMotionFramesEntry').val(),
- /* motion movies */
- 'motion_movies': $('#motionMoviesSwitch')[0].checked,
- 'movie_file_name': $('#movieFileNameEntry').val(),
- 'movie_quality': $('#movieQualitySlider').val(),
- 'max_movie_length': $('#maxMovieLengthEntry').val(),
- 'preserve_movies': $('#preserveMoviesSelect').val() >= 0 ? $('#preserveMoviesSelect').val() : $('#moviesLifetimeEntry').val(),
-
/* motion notifications */
'email_notifications_enabled': $('#emailNotificationsSwitch')[0].checked,
'email_notifications_addresses': $('#emailAddressesEntry').val(),
$('#videoDeviceSwitch')[0].error = true;
$('#videoDeviceSwitch')[0].checked = true; /* so that the user can explicitly disable the camera */
- updateConfigUi();
+ updateConfigUI();
return;
}
markHideIfNull('preserve_pictures', 'preservePicturesSelect');
$('#picturesLifetimeEntry').val(dict['preserve_pictures']); markHideIfNull('preserve_pictures', 'picturesLifetimeEntry');
+ /* movies */
+ $('#moviesSwitch')[0].checked = dict['movies']; markHideIfNull('movies', 'moviesSwitch');
+ $('#movieFileNameEntry').val(dict['movie_file_name']); markHideIfNull('movie_file_name', 'movieFileNameEntry');
+ $('#movieQualitySlider').val(dict['movie_quality']); markHideIfNull('movie_quality', 'movieQualitySlider');
+ $('#recordingModeSelect').val(dict['recording_mode']); markHideIfNull('recording_mode', 'recordingModeSelect');
+ $('#maxMovieLengthEntry').val(dict['max_movie_length']); markHideIfNull('max_movie_length', 'maxMovieLengthEntry');
+ $('#preserveMoviesSelect').val(dict['preserve_movies']);
+ if ($('#preserveMoviesSelect').val() == null) {
+ $('#preserveMoviesSelect').val('-1');
+ }
+ markHideIfNull('preserve_movies', 'preserveMoviesSelect');
+ $('#moviesLifetimeEntry').val(dict['preserve_movies']); markHideIfNull('preserve_movies', 'moviesLifetimeEntry');
+
/* motion detection */
$('#motionDetectionSwitch')[0].checked = dict['motion_detection']; markHideIfNull('motion_detection', 'motionDetectionSwitch');
$('#showFrameChangesSwitch')[0].checked = dict['show_frame_changes']; markHideIfNull('show_frame_changes', 'showFrameChangesSwitch');
$('#postCaptureEntry').val(dict['post_capture']); markHideIfNull('post_capture', 'postCaptureEntry');
$('#minimumMotionFramesEntry').val(dict['minimum_motion_frames']); markHideIfNull('minimum_motion_frames', 'minimumMotionFramesEntry');
- /* motion movies */
- $('#motionMoviesSwitch')[0].checked = dict['motion_movies']; markHideIfNull('motion_movies', 'motionMoviesSwitch');
- $('#movieFileNameEntry').val(dict['movie_file_name']); markHideIfNull('movie_file_name', 'movieFileNameEntry');
- $('#movieQualitySlider').val(dict['movie_quality']); markHideIfNull('movie_quality', 'movieQualitySlider');
- $('#maxMovieLengthEntry').val(dict['max_movie_length']); markHideIfNull('max_movie_length', 'maxMovieLengthEntry');
- $('#preserveMoviesSelect').val(dict['preserve_movies']);
- if ($('#preserveMoviesSelect').val() == null) {
- $('#preserveMoviesSelect').val('-1');
- }
- markHideIfNull('preserve_movies', 'preserveMoviesSelect');
- $('#moviesLifetimeEntry').val(dict['preserve_movies']); markHideIfNull('preserve_movies', 'moviesLifetimeEntry');
-
/* motion notifications */
$('#emailNotificationsSwitch')[0].checked = dict['email_notifications_enabled']; markHideIfNull('email_notifications_enabled', 'emailNotificationsSwitch');
$('#emailAddressesEntry').val(dict['email_notifications_addresses']);
markHideIfNull('_' + name, id);
});
- updateConfigUi();
+ updateConfigUI();
}
}
}
- updateConfigUi();
+ updateConfigUI();
}
else { /* normal user */
if (!cameras.length) {
<div class="page">
<div class="settings closed">
<div class="settings-container">
+
+ <!-- General Settings -->
<div class="settings-section-title">
<input type="checkbox" class="styled section general main-config" id="motionEyeSwitch">
<span class="help-mark" title="general settings, not related to any camera">?</span>
</tr>
</table>
+ <!-- Additional Main Sections -->
{% for section in main_sections.values() %}
{% if section.get('label') and section.get('configs') %}
<div class="settings-section-title {% if section['advanced'] %}advanced-setting{% endif %}">
<td colspan="100"><div class="settings-item-separator" style="margin: 0px 0px 1.5em 0px;"></div></td>
</tr>
+ <!-- Video Device -->
<div class="settings-section-title">
<input type="checkbox" class="styled section device camera-config" id="videoDeviceSwitch">
<span class="help-mark" title="enable this if you want to use this camera device">?</span>
{% endfor %}
</table>
+ <!-- File Storage -->
<div class="settings-section-title advanced-setting">
<span class="help-mark" title="choose where and how your media files are saved">?</span>
<a class="settings-section-title">File Storage</a>
{% endfor %}
</table>
+ <!-- Text Overlay -->
<div class="settings-section-title advanced-setting">
<input type="checkbox" class="styled section text-overlay camera-config" id="textOverlaySwitch">
<span class="help-mark" title="choose what information is displayed on the captured frames">?</span>
{% endfor %}
</table>
+ <!-- Video Streaming -->
<div class="settings-section-title" minimize-switch-independent="true">
<input type="checkbox" class="styled section streaming camera-config" id="videoStreamingSwitch">
<span class="help-mark" title="enable this if you want video streaming for this camera">?</span>
{% endfor %}
</table>
+ <!-- Still Images -->
<div class="settings-section-title">
<input type="checkbox" class="styled section still-images camera-config" id="stillImagesSwitch">
<span class="help-mark" title="enable this if you want to capture still images (pictures)">?</span>
<option value="all-frames">All Frames</option>
</select>
</td>
- <td><span class="help-mark" title="sets the image capture mode: Motion Triggered = an image captured whenever motion is detected, Automated Snapshots = an image captured every x seconds, All Frames = saves each frame into an image file">?</span></td>
+ <td><span class="help-mark" title="sets the image capture mode: Motion Triggered = an image captured whenever motion is detected, Interval Snapshots = an image captured every x seconds, All Frames = saves each frame to an image file">?</span></td>
</tr>
<tr class="settings-item advanced-setting" min="1" max="86400" required="true">
<td class="settings-item-label"><span class="settings-item-label">Snapshot Interval</span></td>
<td class="settings-item-value"><input type="text" class="styled number still-images camera-config" id="snapshotIntervalEntry"><span class="settings-item-unit">seconds</span></td>
- <td><span class="help-mark" title="sets the interval (in seconds) for the automated snapshots">?</span></td>
+ <td><span class="help-mark" title="sets the interval (in seconds) for the snapshots">?</span></td>
</tr>
<tr class="settings-item">
<td class="settings-item-label"><span class="settings-item-label">Preserve Pictures</span></td>
<option value="-1">Custom</option>
</select>
</td>
- <td><span class="help-mark" title="images older than the specified duration are automatically deleted to free storage space">?</span></td>
+ <td><span class="help-mark" title="images older than the specified duration are automatically deleted to free up storage space">?</span></td>
</tr>
<tr class="settings-item" min="1" max="3650" required="true">
<td class="settings-item-label"><span class="settings-item-label">Pictures Lifetime</span></td>
{% endfor %}
</table>
+ <!-- Movies -->
+ <div class="settings-section-title">
+ <input type="checkbox" class="styled section movies camera-config" id="moviesSwitch">
+ <span class="help-mark" title="enable this if you want to record movies">?</span>
+ <a class="settings-section-title">Movies</a>
+ <span class="minimize"></span>
+ </div>
+ <table class="settings">
+ <tr class="settings-item advanced-setting" required="true" strip="true">
+ <td class="settings-item-label"><span class="settings-item-label">Movie File Name</span></td>
+ <td class="settings-item-value"><input type="text" class="styled movies camera-config" id="movieFileNameEntry" placeholder="file name pattern..."></td>
+ <td><span class="help-mark" title="sets the name pattern for the movie (MPEG) files; the following special tokens are accepted: %Y = year, %m = month, %d = date, %H = hour, %M = minute, %S = second, %q = frame number, / = subfolder">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting" min="0" max="100" snap="2" ticksnum="5" decimals="0" unit="%">
+ <td class="settings-item-label"><span class="settings-item-label">Movie Quality</span></td>
+ <td class="settings-item-value"><input type="text" class="range styled movies camera-config" id="movieQualitySlider"></td>
+ <td><span class="help-mark" title="sets the MPEG video quality (higher values produce a better video quality but require more storage space)">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Recording Mode</span></td>
+ <td class="settings-item-value">
+ <select class="styled movies camera-config" id="recordingModeSelect">
+ <option value="motion-triggered">Motion Triggered</option>
+ <option value="continuous">Continuous Recording</option>
+ </select>
+ </td>
+ <td><span class="help-mark" title="sets the recording mode: Motion Triggered = a new movie created whenever motion is detected, Continuous Recording = one big movie file">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting" min="0" max="86400" required="true">
+ <td class="settings-item-label"><span class="settings-item-label">Maximum Movie Length</span></td>
+ <td class="settings-item-value"><input type="text" class="number styled movies camera-config" id="maxMovieLengthEntry"><span class="settings-item-unit">seconds</span></td>
+ <td><span class="help-mark" title="sets the maximum length of movies, in seconds; if the motion event lasts longer, a new movie file is created; use 0 for unlimited length">?</span></td>
+ </tr>
+ <tr class="settings-item">
+ <td class="settings-item-label"><span class="settings-item-label">Preserve Movies</span></td>
+ <td class="settings-item-value">
+ <select class="styled movies camera-config" id="preserveMoviesSelect">
+ <option value="1">For One Day</option>
+ <option value="7">For One Week</option>
+ <option value="30">For One Month</option>
+ <option value="365">For One Year</option>
+ <option value="0">Forever</option>
+ <option value="-1">Custom</option>
+ </select>
+ </td>
+ <td><span class="help-mark" title="movies older than the specified duration are automatically deleted to free up storage space">?</span></td>
+ </tr>
+ <tr class="settings-item" min="1" max="3650" required="true">
+ <td class="settings-item-label"><span class="settings-item-label">Movies Lifetime</span></td>
+ <td class="settings-item-value"><input type="text" class="styled number movies camera-config" id="moviesLifetimeEntry"><span class="settings-item-unit">days</span></td>
+ <td><span class="help-mark" title="sets the number of days after which the movies will be deleted automatically">?</span></td>
+ </tr>
+ {% for config in camera_sections.get('movies', {}).get('configs', []) %}
+ {{config_item(config)}}
+ {% endfor %}
+ </table>
+
+ <!-- Motion Detection -->
<div class="settings-section-title advanced-setting">
<input type="checkbox" class="styled section motion-detection camera-config" id="motionDetectionSwitch">
<span class="help-mark" title="enable this to use and configure the motion detection mechanism">?</span>
{% endfor %}
</table>
- <div class="settings-section-title">
- <input type="checkbox" class="styled section motion-movies camera-config" id="motionMoviesSwitch">
- <span class="help-mark" title="enable this if you want to record motion movies">?</span>
- <a class="settings-section-title">Motion Movies</a>
- <span class="minimize"></span>
- </div>
- <table class="settings">
- <tr class="settings-item advanced-setting" required="true" strip="true">
- <td class="settings-item-label"><span class="settings-item-label">Movie File Name</span></td>
- <td class="settings-item-value"><input type="text" class="styled motion-movies camera-config" id="movieFileNameEntry" placeholder="file name pattern..."></td>
- <td><span class="help-mark" title="sets the name pattern for the movie (MPEG) files; the following special tokens are accepted: %Y = year, %m = month, %d = date, %H = hour, %M = minute, %S = second, %q = frame number, / = subfolder">?</span></td>
- </tr>
- <tr class="settings-item advanced-setting" min="0" max="100" snap="2" ticksnum="5" decimals="0" unit="%">
- <td class="settings-item-label"><span class="settings-item-label">Movie Quality</span></td>
- <td class="settings-item-value"><input type="text" class="range styled motion-movies camera-config" id="movieQualitySlider"></td>
- <td><span class="help-mark" title="sets the MPEG video quality (higher values produce a better video quality but require more storage space)">?</span></td>
- </tr>
- <tr class="settings-item advanced-setting" min="0" max="86400" required="true">
- <td class="settings-item-label"><span class="settings-item-label">Maximum Movie Length</span></td>
- <td class="settings-item-value"><input type="text" class="number styled motion-movies camera-config" id="maxMovieLengthEntry"><span class="settings-item-unit">seconds</span></td>
- <td><span class="help-mark" title="sets the maximum length of motion movies, in seconds; if the motion event lasts longer, a new movie file is created; use 0 for infinite length">?</span></td>
- </tr>
- <tr class="settings-item">
- <td class="settings-item-label"><span class="settings-item-label">Preserve Movies</span></td>
- <td class="settings-item-value">
- <select class="styled motion-movies camera-config" id="preserveMoviesSelect">
- <option value="1">For One Day</option>
- <option value="7">For One Week</option>
- <option value="30">For One Month</option>
- <option value="365">For One Year</option>
- <option value="0">Forever</option>
- <option value="-1">Custom</option>
- </select>
- </td>
- <td><span class="help-mark" title="movies older than the specified duration are automatically deleted to free storage space">?</span></td>
- </tr>
- <tr class="settings-item" min="1" max="3650" required="true">
- <td class="settings-item-label"><span class="settings-item-label">Movies Lifetime</span></td>
- <td class="settings-item-value"><input type="text" class="styled number motion-movies camera-config" id="moviesLifetimeEntry"><span class="settings-item-unit">days</span></td>
- <td><span class="help-mark" title="sets the number of days after which the movies will be deleted automatically">?</span></td>
- </tr>
- {% for config in camera_sections.get('motion-movies', {}).get('configs', []) %}
- {{config_item(config)}}
- {% endfor %}
- </table>
+ <!-- Motion Notifications -->
<div class="settings-section-title advanced-setting">
<span class="help-mark" title="enable this if you want to be notified when motion is detected">?</span>
<a class="settings-section-title">Motion Notifications</a>
{% endfor %}
</table>
+ <!-- Working Schedule -->
<div class="settings-section-title">
<input type="checkbox" class="styled section working-schedule camera-config" id="workingScheduleSwitch">
<span class="help-mark" title="enable this if you want to define a weekly working schedule for motion detection">?</span>
{% endfor %}
</table>
+ <!-- Additional Camera Sections -->
{% for section in camera_sections.values() %}
{% if section.get('label') and section.get('configs') %}
<div class="settings-section-title {% if section['advanced'] %}advanced-setting{% endif %}">