Add setting to use the shortest side to restrict the resolution
This commit is contained in:
parent
257bdda8f7
commit
b03a1acc20
|
@ -4,6 +4,8 @@
|
||||||
* Added blacklist and whitelist settings to automatically filter out models
|
* Added blacklist and whitelist settings to automatically filter out models
|
||||||
* Added setting to delete orphaned recording metadata (switched off by default)
|
* Added setting to delete orphaned recording metadata (switched off by default)
|
||||||
* Fixed thumbnail caching
|
* 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
|
5.2.3
|
||||||
========================
|
========================
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 after", splitAfter).converter(SplitAfterOption.converter()).onChange(this::splitValuesChanged),
|
||||||
Setting.of("Split recordings bigger than", splitBiggerThan).converter(SplitBiggerThanOption.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", 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("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("Concurrent Recordings (0 = unlimited)", concurrentRecordings),
|
||||||
Setting.of("Default Priority", defaultPriority, "lowest 0 - 10000 highest"),
|
Setting.of("Default Priority", defaultPriority, "lowest 0 - 10000 highest"),
|
||||||
|
|
|
@ -219,5 +219,6 @@ public class Settings {
|
||||||
public boolean dreamcamVR = false;
|
public boolean dreamcamVR = false;
|
||||||
public String filterBlacklist = "";
|
public String filterBlacklist = "";
|
||||||
public String filterWhitelist = "";
|
public String filterWhitelist = "";
|
||||||
|
public boolean checkResolutionByMinSide = false;
|
||||||
public int restrictBitrate = 0;
|
public int restrictBitrate = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,15 +97,10 @@ public abstract class AbstractDownload implements RecordingProcess {
|
||||||
return source;
|
return source;
|
||||||
} else {
|
} else {
|
||||||
// filter out stream resolutions, which are out of range of the configured min and max
|
// 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()
|
List<StreamSource> filteredStreamSources = streamSources.stream()
|
||||||
.filter(src -> src.getHeight() == 0 || src.getHeight() == UNKNOWN || minRes <= src.getHeight())
|
.filter(this::isResolutionInLimits)
|
||||||
.filter(src -> src.getHeight() == 0 || src.getHeight() == UNKNOWN || maxRes >= src.getHeight())
|
.filter(this::isBitRateInLimits)
|
||||||
.filter(src -> bitrateLimit == 0 || src.getBandwidth() == UNKNOWN || src.getBandwidth() <= bitrateLimit)
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (filteredStreamSources.isEmpty()) {
|
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
|
// 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
|
// 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
|
@Override
|
||||||
public AtomicLong getDownloadedBytes() {
|
public AtomicLong getDownloadedBytes() {
|
||||||
return downloadedBytes;
|
return downloadedBytes;
|
||||||
|
|
|
@ -189,6 +189,7 @@ public class Cam4Model extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(Optional.ofNullable(playlist.getStreamInfo()).map(StreamInfo::getResolution).map(res -> res.height).orElse(0));
|
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")) {
|
if (playlist.getUri().startsWith("http")) {
|
||||||
src.setMediaPlaylistUrl(playlist.getUri());
|
src.setMediaPlaylistUrl(playlist.getUri());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -92,6 +92,7 @@ public class ChaturbateModel extends AbstractModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getImageSize(String url) {
|
private int getImageSize(String url) {
|
||||||
|
log.debug("######## Get image size");
|
||||||
int imageSize = 0;
|
int imageSize = 0;
|
||||||
Request req = new Request.Builder()
|
Request req = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
|
@ -204,6 +205,7 @@ public class ChaturbateModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
||||||
|
src.setWidth(playlist.getStreamInfo().getResolution().width);
|
||||||
String masterUrl = streamInfo.url;
|
String masterUrl = streamInfo.url;
|
||||||
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
||||||
String segmentUri = baseUrl + playlist.getUri();
|
String segmentUri = baseUrl + playlist.getUri();
|
||||||
|
|
|
@ -119,6 +119,7 @@ public class CherryTvModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
||||||
|
src.setWidth(playlist.getStreamInfo().getResolution().width);
|
||||||
String masterUrl = masterPlaylistUrl;
|
String masterUrl = masterPlaylistUrl;
|
||||||
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
||||||
String segmentUri = baseUrl + playlist.getUri();
|
String segmentUri = baseUrl + playlist.getUri();
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class MVLiveModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
||||||
|
src.setWidth(playlist.getStreamInfo().getResolution().width);
|
||||||
String masterUrl = streamLocation.masterPlaylist;
|
String masterUrl = streamLocation.masterPlaylist;
|
||||||
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
String baseUrl = masterUrl.substring(0, masterUrl.lastIndexOf('/') + 1);
|
||||||
String segmentUri = baseUrl + playlist.getUri();
|
String segmentUri = baseUrl + playlist.getUri();
|
||||||
|
|
|
@ -141,6 +141,7 @@ public class StripchatModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
||||||
|
src.setWidth(playlist.getStreamInfo().getResolution().width);
|
||||||
src.setMediaPlaylistUrl(playlist.getUri());
|
src.setMediaPlaylistUrl(playlist.getUri());
|
||||||
if (src.getMediaPlaylistUrl().contains("?")) {
|
if (src.getMediaPlaylistUrl().contains("?")) {
|
||||||
src.setMediaPlaylistUrl(src.getMediaPlaylistUrl().substring(0, src.getMediaPlaylistUrl().lastIndexOf('?')));
|
src.setMediaPlaylistUrl(src.getMediaPlaylistUrl().substring(0, src.getMediaPlaylistUrl().lastIndexOf('?')));
|
||||||
|
|
|
@ -99,6 +99,7 @@ public class WinkTvModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
src.setHeight(playlist.getStreamInfo().getResolution().height);
|
||||||
|
src.setWidth(playlist.getStreamInfo().getResolution().width);
|
||||||
src.setMediaPlaylistUrl(playlist.getUri());
|
src.setMediaPlaylistUrl(playlist.getUri());
|
||||||
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
|
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
|
||||||
sources.add(src);
|
sources.add(src);
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class XloveCamModel extends AbstractModel {
|
||||||
StreamSource src = new StreamSource();
|
StreamSource src = new StreamSource();
|
||||||
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
src.setBandwidth(playlist.getStreamInfo().getBandwidth());
|
||||||
src.setHeight(Optional.ofNullable(playlist.getStreamInfo().getResolution()).map(r -> r.height).orElse(0));
|
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());
|
src.setMediaPlaylistUrl(playlist.getUri());
|
||||||
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
|
log.trace("Media playlist {}", src.getMediaPlaylistUrl());
|
||||||
sources.add(src);
|
sources.add(src);
|
||||||
|
|
Loading…
Reference in New Issue