diff --git a/client/pom.xml b/client/pom.xml
index d6191b83..739486ca 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -80,6 +80,11 @@
org.eclipse.jetty
jetty-servlet
+
+ com.twelvemonkeys.imageio
+ imageio-webp
+ 3.10.1
+
diff --git a/client/src/main/java/ctbrec/ui/sites/streamray/AbstractStreamrayUpdateService.java b/client/src/main/java/ctbrec/ui/sites/streamray/AbstractStreamrayUpdateService.java
index f38a04eb..0ae1f535 100644
--- a/client/src/main/java/ctbrec/ui/sites/streamray/AbstractStreamrayUpdateService.java
+++ b/client/src/main/java/ctbrec/ui/sites/streamray/AbstractStreamrayUpdateService.java
@@ -27,7 +27,7 @@ public abstract class AbstractStreamrayUpdateService extends PaginatedScheduledS
protected String getPreviewURL(String name) {
String lname = name.toLowerCase();
- String url = MessageFormat.format("https://images4.streamray.com/images/streamray/won/jpg/{0}/{1}/{2}_640.jpg", lname.substring(0, 1), lname.substring(lname.length() - 1), lname);
+ String url = MessageFormat.format("https://s3root.prod.cams.run/cams-d-com-production-model-snapshot/won/jpg/{0}/{1}/{2}.jpg", lname.substring(0,1), lname.substring(lname.length()-1), lname);
try {
return MessageFormat.format("https://dynimages.securedataimages.com/unsigned/rs:fill:640::0/g:no/plain/{0}@jpg", URLEncoder.encode(url, UTF_8));
} catch (Exception ex) {
diff --git a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java
index 14d035eb..5784a3b9 100644
--- a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java
+++ b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java
@@ -47,6 +47,7 @@ import javafx.scene.shape.Shape;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.util.Duration;
+import javafx.embed.swing.SwingFXUtils;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
@@ -61,6 +62,9 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+
import static ctbrec.Model.State.OFFLINE;
import static ctbrec.Model.State.ONLINE;
import static ctbrec.io.HttpConstants.*;
@@ -434,7 +438,8 @@ public class ThumbCell extends StackPane {
double width = 480;
double height = width * imgAspectRatio;
InputStream bodyStream = Objects.requireNonNull(resp.body(), "HTTP body is null").byteStream();
- var img = new Image(bodyStream, width, height, preserveAspectRatio.get(), true);
+ BufferedImage bimg = ImageIO.read(bodyStream);
+ Image img = SwingFXUtils.toFXImage(bimg, null);
if (img.progressProperty().get() == 1.0) {
Platform.runLater(() -> {
iv.setImage(img);
diff --git a/common/src/main/java/ctbrec/sites/streamray/StreamrayModel.java b/common/src/main/java/ctbrec/sites/streamray/StreamrayModel.java
index f5d1b4c4..0ddbe6f8 100644
--- a/common/src/main/java/ctbrec/sites/streamray/StreamrayModel.java
+++ b/common/src/main/java/ctbrec/sites/streamray/StreamrayModel.java
@@ -27,11 +27,14 @@ import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ExecutionException;
+import java.net.URLEncoder;
import static ctbrec.Model.State.*;
import static ctbrec.io.HttpConstants.*;
import static ctbrec.sites.streamray.Streamray.API_URL;
+import static java.nio.charset.StandardCharsets.UTF_8;
@Slf4j
public class StreamrayModel extends AbstractModel {
@@ -52,6 +55,9 @@ public class StreamrayModel extends AbstractModel {
private transient JSONObject modelInfo;
private transient Instant lastInfoRequest = Instant.EPOCH;
+ private transient JSONObject apiInfo;
+ private transient Instant lastApiRequest = Instant.EPOCH;
+
@Override
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
if (ignoreCache) {
@@ -101,10 +107,45 @@ public class StreamrayModel extends AbstractModel {
}
private String getMasterPlaylistUrl() throws IOException {
- JSONObject json = getModelInfo();
- String mpp = json.getString("mpp");
String lname = getName().toLowerCase();
- return MessageFormat.format("https://stream14.cams.com/h5live/http/playlist.m3u8?url=rtmp%3A%2F%2F{0}%3A1935%2Fcams%2F{1}%3Fcams%2F{1}_720p&stream={2}", mpp, lname, getName());
+ JSONObject apiInfo = getApiInfo();
+ if (apiInfo.has("origin")) {
+ String origin = apiInfo.optString("origin");
+ String appName = apiInfo.optString("applicationName", "origin");
+ String token = apiInfo.optString("token");
+ String streamUrl = MessageFormat.format("rtmp://{0}:1935/{1}/{2}?token={3}&site=cams.com", origin, appName, lname, token);
+ String streamName = lname;
+ if (appName.equals("webrtc")) {
+ streamName = lname + "_720p";
+ }
+ String playlistURL = MessageFormat.format("https://stream14cdn.securedataimages.com/h5live/http/playlist.m3u8?url={0}&stream={1}", URLEncoder.encode(streamUrl, UTF_8), URLEncoder.encode(streamName, UTF_8));
+ return playlistURL;
+ } else {
+ throw new IOException("Can not get master playlist url");
+ }
+ }
+
+ private JSONObject getApiInfo() throws IOException {
+ if (Objects.nonNull(apiInfo) && Duration.between(lastApiRequest, Instant.now()).getSeconds() < 5) {
+ return apiInfo;
+ }
+ lastApiRequest = Instant.now();
+ String url = MessageFormat.format(API_URL + "/broadcasting/api/urls/anonymous/{0}/", URLEncoder.encode(getName().toLowerCase(), UTF_8));
+ Request req = new Request.Builder().url(url)
+ .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
+ .header(ACCEPT_LANGUAGE, "en")
+ .header(ORIGIN, getSite().getBaseUrl())
+ .header(REFERER, getSite().getBaseUrl() + '/' + getName())
+ .build();
+ try (Response response = site.getHttpClient().execute(req)) {
+ if (response.isSuccessful()) {
+ JSONObject jsonResponse = new JSONObject(response.body().string());
+ apiInfo = jsonResponse;
+ return apiInfo;
+ } else {
+ throw new HttpException(response.code(), response.message());
+ }
+ }
}
@Override
@@ -157,7 +198,7 @@ public class StreamrayModel extends AbstractModel {
@Override
public RecordingProcess createDownload() {
- return new FfmpegHlsDownload(getSite().getHttpClient());
+ return new FfmpegHlsDownload(new StreamrayHttpClient(Config.getInstance()));
}
@Override
@@ -238,6 +279,8 @@ public class StreamrayModel extends AbstractModel {
status = null;
lastInfoRequest = Instant.EPOCH;
modelInfo = null;
+ lastApiRequest = Instant.EPOCH;
+ apiInfo = null;
}
public boolean isNew() {