diff --git a/CHANGELOG.md b/CHANGELOG.md index 032d806f..a673e2b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ * Fixed recordings not stopping, if playlist requests returned 403 or 404 * LiveJasmin recordings no first check the high res stream and fall back to the low res stream, if it is not available +* Add data transfer detection to ShowupWebrtcDownload, so that downloads don't + get stuck in recording state 4.4.3 ======================== diff --git a/common/src/main/java/ctbrec/sites/showup/ShowupWebrtcDownload.java b/common/src/main/java/ctbrec/sites/showup/ShowupWebrtcDownload.java index 904327e6..50c700df 100644 --- a/common/src/main/java/ctbrec/sites/showup/ShowupWebrtcDownload.java +++ b/common/src/main/java/ctbrec/sites/showup/ShowupWebrtcDownload.java @@ -7,6 +7,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; +import java.time.Duration; import java.time.Instant; import java.util.concurrent.ExecutorService; import java.util.regex.Pattern; @@ -29,10 +30,12 @@ import okio.ByteString; public class ShowupWebrtcDownload extends AbstractDownload { private static final Logger LOG = LoggerFactory.getLogger(ShowupWebrtcDownload.class); + private static final int MAX_SECONDS_WITHOUT_TRANSFER = 20; private transient WebSocket ws; private transient HttpClient httpClient; private transient FileOutputStream fout; + private transient Instant timeOfLastTransfer = Instant.MAX; private volatile boolean running; @@ -50,6 +53,7 @@ public class ShowupWebrtcDownload extends AbstractDownload { this.downloadExecutor = executorService; splittingStrategy = initSplittingStrategy(config.getSettings()); targetFile = config.getFileForRecording(model, "mp4", startTime); + timeOfLastTransfer = Instant.now(); ShowupModel showupModel = (ShowupModel) model; Request request = new Request.Builder() @@ -80,6 +84,7 @@ public class ShowupWebrtcDownload extends AbstractDownload { @Override public void onMessage(WebSocket webSocket, ByteString bytes) { super.onMessage(webSocket, bytes); + timeOfLastTransfer = Instant.now(); if (bytes == null) { return; } @@ -105,7 +110,7 @@ public class ShowupWebrtcDownload extends AbstractDownload { if (t instanceof EOFException) { LOG.info("End of stream detected for model {}", model); } else { - LOG.error("onFailure {} {}", webSocket, response, t); + LOG.error("Websocket failure for model {} {} {}", model, response, t); } if (response != null) { response.close(); @@ -115,13 +120,13 @@ public class ShowupWebrtcDownload extends AbstractDownload { @Override public void onClosing(WebSocket webSocket, int code, String reason) { super.onClosing(webSocket, code, reason); - LOG.trace("onClosing {} {} {}", webSocket, code, reason); + LOG.trace("Websocket closing for model {} {} {}", model, code, reason); } @Override public void onClosed(WebSocket webSocket, int code, String reason) { super.onClosed(webSocket, code, reason); - LOG.debug("onClosed {} {} {}", webSocket, code, reason); + LOG.debug("Websocket closed for model {} {} {}", model, code, reason); stop(); } }); @@ -132,12 +137,8 @@ public class ShowupWebrtcDownload extends AbstractDownload { public void stop() { running = false; if (ws != null) { - boolean closed = ws.close(1000, ""); - if (closed) { - ws = null; - } else { - LOG.error("websocket.close() returned false"); - } + ws.close(1000, ""); + ws = null; } } @@ -188,15 +189,20 @@ public class ShowupWebrtcDownload extends AbstractDownload { @Override public Download call() throws Exception { + LOG.debug("ShowupWebrtcDownload.call()"); if (splittingStrategy.splitNecessary(this)) { stop(); rescheduleTime = Instant.now(); } else { - rescheduleTime = Instant.now().plusSeconds(Config.getInstance().getSettings().onlineCheckIntervalInSecs); + rescheduleTime = Instant.now().plusSeconds(5); } if (!model.isOnline(true)) { stop(); } + if (Duration.between(timeOfLastTransfer, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) { + LOG.info("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model); + stop(); + } return this; }