forked from j62/ctbrec
Add documentation for the post-processing steps
This commit is contained in:
parent
e4eee063ba
commit
a8b1af848a
|
@ -20,6 +20,7 @@ import ctbrec.Settings.DirectoryStructure;
|
|||
import ctbrec.Settings.ProxyType;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.SiteUI;
|
||||
import ctbrec.ui.SiteUiFactory;
|
||||
import ctbrec.ui.controls.range.DiscreteRange;
|
||||
|
@ -44,6 +45,7 @@ import javafx.beans.property.SimpleStringProperty;
|
|||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TextInputDialog;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
@ -100,6 +102,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
private SimpleIntegerProperty postProcessingThreads;
|
||||
private IgnoreList ignoreList;
|
||||
private PostProcessingStepPanel postProcessingStepPanel;
|
||||
private Button variablesHelpButton;
|
||||
|
||||
public SettingsTab(List<Site> sites, Recorder recorder) {
|
||||
this.sites = sites;
|
||||
|
@ -152,6 +155,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
private void createGui() {
|
||||
postProcessingStepPanel = new PostProcessingStepPanel(config);
|
||||
variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables");
|
||||
ignoreList = new IgnoreList(sites);
|
||||
List<Category> siteCategories = new ArrayList<>();
|
||||
for (Site site : sites) {
|
||||
|
@ -199,6 +203,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Setting.of("Port", port),
|
||||
Setting.of("Path", path, "Leave empty, if you didn't change the servletContext in the server config"),
|
||||
Setting.of("Download Filename", downloadFilename, "File name pattern for downloads"),
|
||||
Setting.of("", variablesHelpButton),
|
||||
Setting.of("Require authentication", requireAuthentication),
|
||||
Setting.of("Use Secure Communication (TLS)", transportLayerSecurity)
|
||||
)
|
||||
|
@ -206,7 +211,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Category.of("Post-Processing",
|
||||
Group.of("Post-Processing",
|
||||
Setting.of("Threads", postProcessingThreads),
|
||||
Setting.of("Steps", postProcessingStepPanel)
|
||||
Setting.of("Steps", postProcessingStepPanel),
|
||||
Setting.of("", createHelpButton("Post-Processing Help", "http://localhost:5689/docs/PostProcessing.md"))
|
||||
)
|
||||
),
|
||||
Category.of("Events & Actions", new ActionSettingsPanel(recorder)),
|
||||
|
@ -246,6 +252,13 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
prefs.getSetting("concurrentRecordings").ifPresent(s -> bindEnabledProperty(s, recordLocal.not()));
|
||||
prefs.getSetting("downloadFilename").ifPresent(s -> bindEnabledProperty(s, recordLocal));
|
||||
postProcessingStepPanel.disableProperty().bind(recordLocal.not());
|
||||
variablesHelpButton.disableProperty().bind(recordLocal);
|
||||
}
|
||||
|
||||
private Button createHelpButton(String text, String url) {
|
||||
Button postProcessingHelpButton = new Button(text);
|
||||
postProcessingHelpButton.setOnAction(e -> DesktopIntegration.open(url));
|
||||
return postProcessingHelpButton;
|
||||
}
|
||||
|
||||
private void bindEnabledProperty(Setting s, BooleanExpression bindTo) {
|
||||
|
|
|
@ -1,79 +1,106 @@
|
|||
#### Post-Processing
|
||||
The post-processing gives you the possibility to run any script / program after a recording has finished. You can use that to convert
|
||||
The post-processing gives you the possibility to execute different actions after a recording has finished. You can use that to convert
|
||||
the files to another format, create preview images, rename / move the file etc.
|
||||
There are example scripts included in the distribution zip (`pp.bat`, `pp.ps1`, `pp.sh`). See also the comments in those files.
|
||||
|
||||
##### Local Recording
|
||||
If you are using the local recording mode, you can set the post-processing script / program on the settings tab under *Recorder* -> *Post-Processing*.
|
||||
ctbrec will call the selected script after the recording has finished with the following parameters:
|
||||
##### Available Steps
|
||||
- **create a copy** - Creates a copy of the original recording. All following post-processing steps are executed on the copy, not on the
|
||||
original recording. This means, that the post-processing can be rerun in case a step failed, because the original recording is still
|
||||
available.
|
||||
- **rename** - Renames the recording with the help of variables. See [Variables](#variables)
|
||||
- **move** - Moves the recording with the help of variables. See [Variables](#variables)
|
||||
- **remux / transcode** - Executes FFmpeg with the given arguments on the recording. This step can be used to convert a recording to
|
||||
MP4 or re-encode it to a different format / resolution. The input and output file don't have to be defined. If the step was successful
|
||||
the input file gets deleted.
|
||||
- **execute script** - Executes a script or program with the given arguments. You can use the [variables](#variables) to define what
|
||||
to pass over to the script.
|
||||
- **delete too short** - Delete a recording, if it is shorter than the given duration. This post-processing step has replaced the
|
||||
setting, which was available in the post-processing category before
|
||||
- **delete original** - This is a companion step for "create a copy". If you use the copy step and all other steps are successful,
|
||||
you probably want to get rid of the original file and just keep the result of the post-processing. That's what this step does.
|
||||
- **remove recording, but keep the files** - Removes the recording from the recordings list, but keeps the files untouched.
|
||||
|
||||
1. directory (absolute path)
|
||||
2. file (absolute path)
|
||||
3. model name
|
||||
4. site name
|
||||
5. unixtime (seconds since 1/1/1970 00:00)
|
||||
#### Planned for future releases
|
||||
- **call a webhook** - call a URL once a recording is finished
|
||||
- **create contactsheet** - create a contact sheet with preview images of the recording
|
||||
- **create timeline thumbnails** - create a small thumbnail for every second or every few seconds, which can be used to very fast
|
||||
scan through a recording
|
||||
|
||||
##### Remote Recording (server)
|
||||
If you are running the server and want to run a post-processing script, you have to edit the [configuration file](/docs/ConfigurationFile.md). Just set the absolute path to an executable script / program for the setting **postProcessing**. Since the recordings look a bit different for the server, the parameters, which are passed to the script are a bit different, too:
|
||||
#### Variables
|
||||
|
||||
1. parent directory (absolute path)
|
||||
2. directory of the recording (absolute path) - this directory contains the segments and the playlist
|
||||
3. model name
|
||||
4. site name
|
||||
5. unixtime (seconds since 1/1/1970 00:00)
|
||||
<a id="variables" />
|
||||
|
||||
##### Example Scripts
|
||||
- **${modelName}** - the name of the recorded model
|
||||
- **${modelDisplayName}** - the name of the recorded model, which is shown on the webpage. Might be the same as
|
||||
${modelName}
|
||||
- **${modelSanitizedName}** - sanitized name of the model. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space
|
||||
- **${siteName}** - the name of the cam site, the model streams on
|
||||
- **${siteSanitizedName}** - sanitized name of the site. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space
|
||||
- **${fileSuffix}** - the file extension of the recording. E.g. ts or mp4. In case of a standard server recording,
|
||||
this will be empty
|
||||
- **${epochSecond}** - timestamp of the recording in seconds since 1970-01-01 (unixtime)
|
||||
- **${modelNotes}** - sanitized model notes. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space
|
||||
- **${recordingNotes}** - sanitized recording notes. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space. Useful for the download of recordings from the server.
|
||||
- **${recordingsDir}** - the base directory of all recordings. Same as Recordings Directory in the Recorder settings
|
||||
section.
|
||||
- **${absolutePath}** - the absolute path in the filesystem to the recording file (or the recording directory in case of
|
||||
a server recording)
|
||||
- **${absoluteParentPath}** - the absolute path to the parent directory of the recording in the filesystem (or the
|
||||
recording dir in case of a server recording)
|
||||
- **${utcDateTime}** and **${localDateTime}** - the timestamp of the recording in the UTC or your local timezone. If no
|
||||
pattern is given, the default ```yyyy-MM-dd_HH-mm-ss``` is used. You can also define your own pattern using the following
|
||||
symbols. For example ```${localDateTime(yyyyMMdd-HHmmss)}``` would lead to 20200928-173605.
|
||||
<table class="table-striped">
|
||||
<thead>
|
||||
<tr><th scope="col">Symbol</th> <th scope="col">Meaning</th> <th scope="col">Presentation</th> <th scope="col">Examples</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr><th scope="row">G</th> <td>era</td> <td>text</td> <td>AD; Anno Domini; A</td>
|
||||
</tr><tr><th scope="row">u</th> <td>year</td> <td>year</td> <td>2004; 04</td>
|
||||
</tr><tr><th scope="row">y</th> <td>year-of-era</td> <td>year</td> <td>2004; 04</td>
|
||||
</tr><tr><th scope="row">D</th> <td>day-of-year</td> <td>number</td> <td>189</td>
|
||||
</tr><tr><th scope="row">M/L</th> <td>month-of-year</td> <td>number/text</td> <td>7; 07; Jul; July; J</td>
|
||||
</tr><tr><th scope="row">d</th> <td>day-of-month</td> <td>number</td> <td>10</td>
|
||||
</tr><tr><th scope="row">g</th> <td>modified-julian-day</td> <td>number</td> <td>2451334</td>
|
||||
|
||||
Server script by @uo0Evx99@mastodon.cloud used on a Raspberry Pi 3 B+ to convert recordigns to mp4 files:
|
||||
```
|
||||
#!/bin/bash
|
||||
</tr><tr><th scope="row">Q/q</th> <td>quarter-of-year</td> <td>number/text</td> <td>3; 03; Q3; 3rd quarter</td>
|
||||
</tr><tr><th scope="row">Y</th> <td>week-based-year</td> <td>year</td> <td>1996; 96</td>
|
||||
</tr><tr><th scope="row">w</th> <td>week-of-week-based-year</td> <td>number</td> <td>27</td>
|
||||
</tr><tr><th scope="row">W</th> <td>week-of-month</td> <td>number</td> <td>4</td>
|
||||
</tr><tr><th scope="row">E</th> <td>day-of-week</td> <td>text</td> <td>Tue; Tuesday; T</td>
|
||||
</tr><tr><th scope="row">e/c</th> <td>localized day-of-week</td> <td>number/text</td> <td>2; 02; Tue; Tuesday; T</td>
|
||||
</tr><tr><th scope="row">F</th> <td>day-of-week-in-month</td> <td>number</td> <td>3</td>
|
||||
|
||||
#
|
||||
#Explanation of the code: It first takes all the .ts files (because sadly the server
|
||||
#doesnt save the video in 1 big file instead) and creates one big .ts file in the same
|
||||
#folder called "all".
|
||||
#
|
||||
#Then it uses ffmpeg to re-encode the .ts file to .mp4 while just copying the audio
|
||||
#and video codec to reduce the encoding time. It also uses the -movflags faststart so
|
||||
#the video can be played back instantly when viewing online (e.g. with Plex)
|
||||
#That re-encoded file is being stored in the folder /home/pi/hdd/plex/"MODEL NAME"/
|
||||
#with the name "CURRENT TIME"-"MODEL NAME".mp4
|
||||
#
|
||||
#Then it deletes the folder in which all the .ts files were, because we dont need
|
||||
#those anymore as we have our .mp4 file re-encoded already and ready to use/stream.
|
||||
#
|
||||
#This script has been used on a Raspberry Pi 3 B+
|
||||
#
|
||||
</tr><tr><th scope="row">a</th> <td>am-pm-of-day</td> <td>text</td> <td>PM</td>
|
||||
</tr><tr><th scope="row">h</th> <td>clock-hour-of-am-pm (1-12)</td> <td>number</td> <td>12</td>
|
||||
</tr><tr><th scope="row">K</th> <td>hour-of-am-pm (0-11)</td> <td>number</td> <td>0</td>
|
||||
</tr><tr><th scope="row">k</th> <td>clock-hour-of-day (1-24)</td> <td>number</td> <td>24</td>
|
||||
|
||||
# $1 directory (absolute path)
|
||||
# $2 file (absolute path)
|
||||
# $3 model name
|
||||
# $4 site name
|
||||
# $5 unixtime
|
||||
</tr><tr><th scope="row">H</th> <td>hour-of-day (0-23)</td> <td>number</td> <td>0</td>
|
||||
</tr><tr><th scope="row">m</th> <td>minute-of-hour</td> <td>number</td> <td>30</td>
|
||||
</tr><tr><th scope="row">s</th> <td>second-of-minute</td> <td>number</td> <td>55</td>
|
||||
</tr><tr><th scope="row">S</th> <td>fraction-of-second</td> <td>fraction</td> <td>978</td>
|
||||
</tr><tr><th scope="row">A</th> <td>milli-of-day</td> <td>number</td> <td>1234</td>
|
||||
</tr><tr><th scope="row">n</th> <td>nano-of-second</td> <td>number</td> <td>987654321</td>
|
||||
</tr><tr><th scope="row">N</th> <td>nano-of-day</td> <td>number</td> <td>1234000000</td>
|
||||
|
||||
# format unixtime to human readable
|
||||
TIME=$(date --date="@$5" +%H:%M_%d.%m.%Y)
|
||||
</tr><tr><th scope="row">V</th> <td>time-zone ID</td> <td>zone-id</td> <td>America/Los_Angeles; Z; -08:30</td>
|
||||
</tr><tr><th scope="row">v</th> <td>generic time-zone name</td> <td>zone-name</td> <td>Pacific Time; PT</td>
|
||||
</tr><tr><th scope="row">z</th> <td>time-zone name</td> <td>zone-name</td> <td>Pacific Standard Time; PST</td>
|
||||
</tr><tr><th scope="row">O</th> <td>localized zone-offset</td> <td>offset-O</td> <td>GMT+8; GMT+08:00; UTC-08:00</td>
|
||||
</tr><tr><th scope="row">X</th> <td>zone-offset 'Z' for zero</td> <td>offset-X</td> <td>Z; -08; -0830; -08:30; -083015; -08:30:15</td>
|
||||
</tr><tr><th scope="row">x</th> <td>zone-offset</td> <td>offset-x</td> <td>+0000; -08; -0830; -08:30; -083015; -08:30:15</td>
|
||||
</tr><tr><th scope="row">Z</th> <td>zone-offset</td> <td>offset-Z</td> <td>+0000; -0800; -08:00</td>
|
||||
|
||||
cat $2/*.ts > "$2/all.ts" && ffmpeg -i "$2/all.ts" -acodec copy -vcodec copy -movflags faststart "/home/pi/hdd/plex/$3/$TIME-$3.mp4" && rm -r "$2"
|
||||
```
|
||||
</tr><tr><th scope="row">p</th> <td>pad next</td> <td>pad modifier</td> <td>1</td>
|
||||
|
||||
</tr><tr><th scope="row">'</th> <td>escape for text</td> <td>delimiter</td> <td></td>
|
||||
</tr><tr><th scope="row">''</th> <td>single quote</td> <td>literal</td> <td>'</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
Windows script by @electrotek@mastodon.cloud.
|
||||
Automatically converts .ts files into mkv after recording ended, factors in multiple/split files. Assumes mkvtoolnix installed in path stated
|
||||
```
|
||||
@echo off
|
||||
|
||||
set directory=%1
|
||||
set file=%2
|
||||
set model=%3
|
||||
set site=%4
|
||||
set unixtime=%5
|
||||
|
||||
FOR %%f in (%directory%\*.ts) do (
|
||||
"C:\Program Files\MKVToolNix\mkvmerge.exe" -o "%directory%\%%~nf.mkv" --title "%model%" "%directory%\%%~nf.ts"
|
||||
del "%directory%\%%~nf.ts"
|
||||
)
|
||||
```
|
||||
|
||||
##### Video Tutorials
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/QIZhrhBFhoc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
For more information see: [DateTimeFormatter](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html)
|
Loading…
Reference in New Issue