Add setting to use the shortest side to restrict the resolution

This commit is contained in:
0xb00bface 2023-12-30 19:55:58 +01:00
parent 257bdda8f7
commit b03a1acc20
12 changed files with 73 additions and 7 deletions

View File

@ -4,6 +4,8 @@
* Added blacklist and whitelist settings to automatically filter out models
* Added setting to delete orphaned recording metadata (switched off by default)
* Fixed thumbnail caching
* Added setting to restrict recording by bit rate
* Added setting to use the shortest side to restrict the resolution
5.2.3
========================

View File

@ -0,0 +1,44 @@
package ctbrec.ui.settings;
import ctbrec.Config;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
@Slf4j
public class RestrictResolutionSidePane extends HBox {
private ComboBox<String> combo;
private final Config config;
private static final List<String> names = List.of("by video height", "by shortest side");
public RestrictResolutionSidePane(Config config) {
this.config = config;
setSpacing(5);
getChildren().addAll(buildCombo());
}
private ComboBox<String> buildCombo() {
ObservableList<String> lst = FXCollections.observableList(names);
combo = new ComboBox<>(lst);
combo.setOnAction(evt -> saveConfig());
int index = config.getSettings().checkResolutionByMinSide ? 1 : 0;
combo.getSelectionModel().select(index);
return combo;
}
private void saveConfig() {
int index = combo.getSelectionModel().getSelectedIndex();
config.getSettings().checkResolutionByMinSide = (index == 1);
try {
config.save();
} catch (IOException e) {
log.error("Can't save config", e);
}
}
}

View File

@ -277,6 +277,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
Setting.of("Split recordings after", splitAfter).converter(SplitAfterOption.converter()).onChange(this::splitValuesChanged),
Setting.of("Split recordings bigger than", splitBiggerThan).converter(SplitBiggerThanOption.converter()).onChange(this::splitValuesChanged),
Setting.of("Restrict Resolution", resolutionRange, "Only record streams with resolution within the given range"),
Setting.of("Restrict Resolution", new RestrictResolutionSidePane(config)),
Setting.of("Restrict Video Bitrate (kbps, 0 = unlimited)", restrictBitrate, "Only record streams with a video bitrate below this limit (kbps)"),
Setting.of("Concurrent Recordings (0 = unlimited)", concurrentRecordings),
Setting.of("Default Priority", defaultPriority, "lowest 0 - 10000 highest"),

View File

@ -219,5 +219,6 @@ public class Settings {
public boolean dreamcamVR = false;
public String filterBlacklist = "";
public String filterWhitelist = "";
public boolean checkResolutionByMinSide = false;
public int restrictBitrate = 0;
}

View File

@ -97,15 +97,10 @@ public abstract class AbstractDownload implements RecordingProcess {
return source;
} else {
// filter out stream resolutions, which are out of range of the configured min and max
int minRes = Config.getInstance().getSettings().minimumResolution;
int maxRes = Config.getInstance().getSettings().maximumResolution;
int bitrateLimit = Config.getInstance().getSettings().restrictBitrate * 1024;
List<StreamSource> filteredStreamSources = streamSources.stream()
.filter(src -> src.getHeight() == 0 || src.getHeight() == UNKNOWN || minRes <= src.getHeight())
.filter(src -> src.getHeight() == 0 || src.getHeight() == UNKNOWN || maxRes >= src.getHeight())
.filter(src -> bitrateLimit == 0 || src.getBandwidth() == UNKNOWN || src.getBandwidth() <= bitrateLimit)
.filter(this::isResolutionInLimits)
.filter(this::isBitRateInLimits)
.toList();
if (filteredStreamSources.isEmpty()) {
// TODO save, why a stream has been filtered out and convey this information to the UI, so that the user understands why a recording
// doesn't start
@ -119,6 +114,21 @@ public abstract class AbstractDownload implements RecordingProcess {
}
}
private boolean isResolutionInLimits(StreamSource src) {
int minRes = Config.getInstance().getSettings().minimumResolution;
int maxRes = Config.getInstance().getSettings().maximumResolution;
boolean checkResolutionByMinSide = Config.getInstance().getSettings().checkResolutionByMinSide;
int resolution = checkResolutionByMinSide ? Math.min(src.getHeight(), src.getWidth()) : src.getHeight();
return resolution == 0 || resolution == UNKNOWN || (minRes <= resolution && maxRes >= resolution);
}
private boolean isBitRateInLimits(StreamSource src) {
int bitrateLimit = Config.getInstance().getSettings().restrictBitrate * 1024;
return bitrateLimit == 0
|| src.getBandwidth() == UNKNOWN
|| src.getBandwidth() <= bitrateLimit;
}
@Override
public AtomicLong getDownloadedBytes() {
return downloadedBytes;

View File

@ -189,6 +189,7 @@ public class Cam4Model extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(Optional.ofNullable(playlist.getStreamInfo()).map(StreamInfo::getResolution).map(res -> res.height).orElse(0));
src.setWidth(Optional.ofNullable(playlist.getStreamInfo()).map(StreamInfo::getResolution).map(res -> res.width).orElse(0));
if (playlist.getUri().startsWith("http")) {
src.setMediaPlaylistUrl(playlist.getUri());
} else {

View File

@ -92,6 +92,7 @@ public class ChaturbateModel extends AbstractModel {
}
private int getImageSize(String url) {
log.debug("######## Get image size");
int imageSize = 0;
Request req = new Request.Builder()
.url(url)
@ -204,6 +205,7 @@ public class ChaturbateModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(playlist.getStreamInfo().getResolution().height);
src.setWidth(playlist.getStreamInfo().getResolution().width);
String masterUrl = streamInfo.url;
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
String segmentUri = baseUrl + playlist.getUri();

View File

@ -119,6 +119,7 @@ public class CherryTvModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(playlist.getStreamInfo().getResolution().height);
src.setWidth(playlist.getStreamInfo().getResolution().width);
String masterUrl = masterPlaylistUrl;
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
String segmentUri = baseUrl + playlist.getUri();

View File

@ -80,6 +80,7 @@ public class MVLiveModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(playlist.getStreamInfo().getResolution().height);
src.setWidth(playlist.getStreamInfo().getResolution().width);
String masterUrl = streamLocation.masterPlaylist;
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
String segmentUri = baseUrl + playlist.getUri();

View File

@ -141,6 +141,7 @@ public class StripchatModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(playlist.getStreamInfo().getResolution().height);
src.setWidth(playlist.getStreamInfo().getResolution().width);
src.setMediaPlaylistUrl(playlist.getUri());
if (src.getMediaPlaylistUrl().contains("?")) {
src.setMediaPlaylistUrl(src.getMediaPlaylistUrl().substring(0, src.getMediaPlaylistUrl().lastIndexOf('?')));

View File

@ -99,6 +99,7 @@ public class WinkTvModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(playlist.getStreamInfo().getResolution().height);
src.setWidth(playlist.getStreamInfo().getResolution().width);
src.setMediaPlaylistUrl(playlist.getUri());
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
sources.add(src);

View File

@ -69,6 +69,7 @@ public class XloveCamModel extends AbstractModel {
StreamSource src = new StreamSource();
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
src.setHeight(Optional.ofNullable(playlist.getStreamInfo().getResolution()).map(r -> r.height).orElse(0));
src.setWidth(Optional.ofNullable(playlist.getStreamInfo().getResolution()).map(r -> r.width).orElse(0));
src.setMediaPlaylistUrl(playlist.getUri());
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
sources.add(src);