forked from j62/ctbrec
1
0
Fork 0

Add documentation for the post-processing steps

This commit is contained in:
0xb00bface 2020-09-28 17:46:11 +02:00
parent e4eee063ba
commit a8b1af848a
2 changed files with 106 additions and 66 deletions

View File

@ -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) {

View File

@ -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)