Merge pull request #50 from kohlerpop1/fixes-updates

Fixed bug, added final, removed not needed initialization, and minor improvements.
This commit is contained in:
Jacek W
2024-01-22 23:26:43 +01:00
committed by GitHub
6 changed files with 61 additions and 130 deletions

View File

@@ -36,7 +36,6 @@ public class LiveClientSettings {
/** /**
* ISO-Language for Client * ISO-Language for Client
*/ */
private String clientLanguage; private String clientLanguage;
/** /**
@@ -44,7 +43,6 @@ public class LiveClientSettings {
*/ */
private boolean retryOnConnectionFailure; private boolean retryOnConnectionFailure;
/** /**
* Before retrying connect, wait for select amount of time * Before retrying connect, wait for select amount of time
*/ */
@@ -53,42 +51,35 @@ public class LiveClientSettings {
/** /**
* Whether to print Logs to Console * Whether to print Logs to Console
*/ */
private boolean printToConsole = true; private boolean printToConsole = true;
/** /**
* LoggingLevel for Logs * LoggingLevel for Logs
*/ */
private Level logLevel; private Level logLevel;
/** /**
* Optional: Use it if you need to change TikTok live hostname in builder * Optional: Use it if you need to change TikTok live hostname in builder
*/ */
private String hostName; private String hostName;
/** /**
* Parameters used in requests to TikTok api * Parameters used in requests to TikTok api
*/ */
private HttpClientSettings httpSettings; private HttpClientSettings httpSettings;
/**
/*
* Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId * Optional: Sometimes not every messages from chat are send to TikTokLiveJava to fix this issue you can set sessionId
* documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages * documentation how to obtain sessionId https://github.com/isaackogan/TikTok-Live-Connector#send-chat-messages
*/ */
private String sessionId; private String sessionId;
/* /**
* Optional: By default roomID is fetched before connect to live, but you can set it manually * Optional: By default roomID is fetched before connect to live, but you can set it manually
* *
*/ */
private String roomId; private String roomId;
public static LiveClientSettings createDefault() public static LiveClientSettings createDefault()
{ {
var httpSettings = new HttpClientSettings(); var httpSettings = new HttpClientSettings();
@@ -103,12 +94,10 @@ public class LiveClientSettings {
clientSettings.setPrintToConsole(false); clientSettings.setPrintToConsole(false);
clientSettings.setLogLevel(Level.ALL); clientSettings.setLogLevel(Level.ALL);
clientSettings.setHttpSettings(httpSettings); clientSettings.setHttpSettings(httpSettings);
return clientSettings; return clientSettings;
} }
/** /**
* Default Parameters for HTTP-Request * Default Parameters for HTTP-Request
*/ */
@@ -147,11 +136,9 @@ public class LiveClientSettings {
clientParams.put("webcast_sdk_version", "1.3.0"); clientParams.put("webcast_sdk_version", "1.3.0");
clientParams.put("update_version_code", "1.3.0"); clientParams.put("update_version_code", "1.3.0");
return clientParams; return clientParams;
} }
/** /**
* Default Headers for HTTP-Request * Default Headers for HTTP-Request
*/ */
@@ -167,6 +154,4 @@ public class LiveClientSettings {
headers.put("Accept-Language", "en-US,en; q=0.9"); headers.put("Accept-Language", "en-US,en; q=0.9");
return headers; return headers;
} }
} }

View File

@@ -87,6 +87,7 @@ public class ProxyClientSettings implements Iterator<ProxyData>
@Override @Override
public void remove() { public void remove() {
proxyList.remove(index); proxyList.remove(index);
lastSuccess = false; // index is no longer valid and lastSuccess needs falsified
} }
public void setIndex(int index) { public void setIndex(int index) {

View File

@@ -26,7 +26,7 @@ import io.github.jwdeveloper.tiktok.*;
import io.github.jwdeveloper.tiktok.data.dto.ProxyData; import io.github.jwdeveloper.tiktok.data.dto.ProxyData;
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData; import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
import io.github.jwdeveloper.tiktok.data.settings.*; import io.github.jwdeveloper.tiktok.data.settings.*;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException; import io.github.jwdeveloper.tiktok.exceptions.*;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
@@ -41,7 +41,7 @@ public class TikTokWebSocketClient implements SocketClient {
private final TikTokLiveEventHandler tikTokEventHandler; private final TikTokLiveEventHandler tikTokEventHandler;
private WebSocketClient webSocketClient; private WebSocketClient webSocketClient;
private TikTokWebSocketPingingTask pingingTask; private final TikTokWebSocketPingingTask pingingTask;
private boolean isConnected; private boolean isConnected;
public TikTokWebSocketClient( public TikTokWebSocketClient(
@@ -91,6 +91,20 @@ public class TikTokWebSocketClient implements SocketClient {
} }
public void connectProxy(ProxyClientSettings proxySettings) { public void connectProxy(ProxyClientSettings proxySettings) {
try {
if (proxySettings.getType() == Proxy.Type.SOCKS) {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}
public X509Certificate[] getAcceptedIssuers() { return null; }
}}, null);
webSocketClient.setSocketFactory(sc.getSocketFactory());
}
} catch (Exception e) {
// This will never be thrown.
throw new TikTokProxyRequestException("Unable to set Socks proxy SSL instance");
}
while (proxySettings.hasNext()) { while (proxySettings.hasNext()) {
ProxyData proxyData = proxySettings.next(); ProxyData proxyData = proxySettings.next();
if (!tryProxyConnection(proxySettings, proxyData)) { if (!tryProxyConnection(proxySettings, proxyData)) {
@@ -98,6 +112,7 @@ public class TikTokWebSocketClient implements SocketClient {
proxySettings.remove(); proxySettings.remove();
continue; continue;
} }
pingingTask.run(webSocketClient);
isConnected = true; isConnected = true;
break; break;
} }
@@ -107,21 +122,6 @@ public class TikTokWebSocketClient implements SocketClient {
public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) { public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) {
try { try {
if (proxySettings.getType() == Proxy.Type.SOCKS) {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}}, null);
webSocketClient.setSocketFactory(sc.getSocketFactory());
}
webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress())); webSocketClient.setProxy(new Proxy(proxySettings.getType(), proxyData.toSocketAddress()));
webSocketClient.connect(); webSocketClient.connect();
return true; return true;

View File

@@ -11,14 +11,10 @@ public class TikTokWebSocketPingingTask
private final int MIN_TIMEOUT = 250; private final int MIN_TIMEOUT = 250;
private final int MAX_TIMEOUT = 500; private final int MAX_TIMEOUT = 500;
public void run(WebSocket webSocket) public void run(WebSocket webSocket)
{ {
stop(); stop();
thread = new Thread(() -> thread = new Thread(() -> pingTask(webSocket));
{
pingTask(webSocket);
});
isRunning = true; isRunning = true;
thread.start(); thread.start();
} }
@@ -26,9 +22,7 @@ public class TikTokWebSocketPingingTask
public void stop() public void stop()
{ {
if (thread != null) if (thread != null)
{
thread.interrupt(); thread.interrupt();
}
isRunning = false; isRunning = false;
} }
@@ -36,12 +30,9 @@ public class TikTokWebSocketPingingTask
private void pingTask(WebSocket webSocket) private void pingTask(WebSocket webSocket)
{ {
var random = new Random(); var random = new Random();
while (isRunning) while (isRunning) {
{ try {
try if (!webSocket.isOpen()) {
{
if(!webSocket.isOpen())
{
Thread.sleep(100); Thread.sleep(100);
continue; continue;
} }
@@ -50,8 +41,7 @@ public class TikTokWebSocketPingingTask
var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT; var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT;
Thread.sleep(timeout); Thread.sleep(timeout);
} }
catch (Exception e) catch (Exception e) {
{
isRunning = false; isRunning = false;
} }
} }

View File

@@ -24,24 +24,18 @@ package io.github.jwdeveloper.tiktok.extension.recorder.impl;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver; import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
import io.github.jwdeveloper.tiktok.data.events.TikTokLiveEndedEvent; import io.github.jwdeveloper.tiktok.data.events.*;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder;
import io.github.jwdeveloper.tiktok.data.events.TikTokConnectedEvent;
import io.github.jwdeveloper.tiktok.data.events.TikTokDisconnectedEvent;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.DownloadData;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.RecorderSettings;
import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent; import io.github.jwdeveloper.tiktok.data.events.http.TikTokRoomDataResponseEvent;
import io.github.jwdeveloper.tiktok.data.settings.LiveClientSettings;
import io.github.jwdeveloper.tiktok.exceptions.TikTokLiveException;
import io.github.jwdeveloper.tiktok.extension.recorder.api.LiveRecorder;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.data.*;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality; import io.github.jwdeveloper.tiktok.extension.recorder.impl.enums.LiveQuality;
import io.github.jwdeveloper.tiktok.extension.recorder.impl.event.TikTokLiveRecorderStartedEvent;
import io.github.jwdeveloper.tiktok.http.HttpClientFactory;
import io.github.jwdeveloper.tiktok.live.LiveClient; import io.github.jwdeveloper.tiktok.live.LiveClient;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -86,13 +80,11 @@ public class RecorderListener implements LiveRecorder {
throw new TikTokLiveException("Unable to find download live url!"); throw new TikTokLiveException("Unable to find download live url!");
} }
liveClient.getLogger().info("Live download url found!"); liveClient.getLogger().info("Live download url found!");
} }
@TikTokEventObserver @TikTokEventObserver
private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) { private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) {
liveDownloadThread = new Thread(() -> liveDownloadThread = new Thread(() -> {
{
try { try {
var bufferSize = 1024; var bufferSize = 1024;
var url = new URL(downloadData.getFullUrl()); var url = new URL(downloadData.getFullUrl());
@@ -102,40 +94,33 @@ public class RecorderListener implements LiveRecorder {
socksConnection.setRequestProperty(entry.getKey(), entry.getValue()); socksConnection.setRequestProperty(entry.getKey(), entry.getValue());
} }
try (var in = new BufferedInputStream(socksConnection.getInputStream())) { var in = new BufferedInputStream(socksConnection.getInputStream());
var path = settings.getOutputPath() + File.separator + settings.getOutputFileName(); var path = settings.getOutputPath() + File.separator + settings.getOutputFileName();
var file = new File(path); var file = new File(path);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
var fileOutputStream = new FileOutputStream(file); var fileOutputStream = new FileOutputStream(file);
byte dataBuffer[] = new byte[bufferSize]; byte[] dataBuffer = new byte[bufferSize];
int bytesRead; int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) { while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead); fileOutputStream.write(dataBuffer, 0, bytesRead);
} }
} catch (IOException e) { in.close();
throw e;
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
;
} }
}); });
liveDownloadThread.start(); liveDownloadThread.start();
} }
private static void downloadUsingStream(String urlStr, String file) throws IOException { private static void downloadUsingStream(String urlStr, String file) throws IOException {
URL url = new URL(urlStr); URL url = new URL(urlStr);
BufferedInputStream bis = new BufferedInputStream(url.openStream()); BufferedInputStream bis = new BufferedInputStream(url.openStream());
FileOutputStream fis = new FileOutputStream(file); FileOutputStream fis = new FileOutputStream(file);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int count = 0; int count;
while ((count = bis.read(buffer, 0, 1024)) != -1) { while ((count = bis.read(buffer, 0, 1024)) != -1)
fis.write(buffer, 0, count); fis.write(buffer, 0, count);
}
fis.close(); fis.close();
bis.close(); bis.close();
} }
@@ -143,25 +128,23 @@ public class RecorderListener implements LiveRecorder {
@TikTokEventObserver @TikTokEventObserver
private void onDisconnected(LiveClient liveClient, TikTokDisconnectedEvent event) { private void onDisconnected(LiveClient liveClient, TikTokDisconnectedEvent event) {
if (isConnected())
liveDownloadThread.interrupt(); liveDownloadThread.interrupt();
} }
@TikTokEventObserver @TikTokEventObserver
private void onDisconnected(LiveClient liveClient, TikTokLiveEndedEvent event) { private void onDisconnected(LiveClient liveClient, TikTokLiveEndedEvent event) {
if (isConnected())
liveDownloadThread.interrupt(); liveDownloadThread.interrupt();
} }
private int terminateFfmpeg(final Process process) { private int terminateFfmpeg(final Process process) {
if (!process.isAlive()) { if (!process.isAlive()) {
/* // ffmpeg -version, do nothing
* ffmpeg -version, do nothing
*/
return process.exitValue(); return process.exitValue();
} }
/* // ffmpeg -f x11grab
* ffmpeg -f x11grab
*/
System.out.println("About to destroy the child process..."); System.out.println("About to destroy the child process...");
try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) { try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) {
out.write('q'); out.write('q');
@@ -174,7 +157,7 @@ public class RecorderListener implements LiveRecorder {
process.waitFor(); process.waitFor();
} }
return process.exitValue(); return process.exitValue();
} catch (final InterruptedException ie) { } catch (InterruptedException ie) {
System.out.println("Interrupted"); System.out.println("Interrupted");
ie.printStackTrace(); ie.printStackTrace();
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@@ -201,12 +184,10 @@ public class RecorderListener implements LiveRecorder {
.get("flv") .get("flv")
.getAsString(); .getAsString();
var sessionId = streamDataJsonObject.getAsJsonObject("common") var sessionId = streamDataJsonObject.getAsJsonObject("common")
.get("session_id") .get("session_id")
.getAsString(); .getAsString();
//main //main
//https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/stage/stream-3284937501738533765.flv?session_id=136-20240109000954BF818F1B3A8E5E39E238&_webnoredir=1 //https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/stage/stream-3284937501738533765.flv?session_id=136-20240109000954BF818F1B3A8E5E39E238&_webnoredir=1
//Working //Working
@@ -216,5 +197,7 @@ public class RecorderListener implements LiveRecorder {
return new DownloadData(urlLink, sessionId); return new DownloadData(urlLink, sessionId);
} }
private boolean isConnected() {
return liveDownloadThread != null && liveDownloadThread.isAlive();
}
} }

View File

@@ -29,25 +29,6 @@ import lombok.Setter;
import java.util.function.Function; import java.util.function.Function;
/**
* self,
* path: str,
* duration: Optional[int] = None,
* quality: Optional[VideoQuality] = None,
* verbose: bool = True,
* loglevel: str = "error",
* global_options: Set[str] = set(),
* inputs: Dict[str, str] = dict(),
* outputs: Dict[str, str] = dict()
* :param loglevel: Set the FFmpeg log level
* :param outputs: Pass custom params to FFmpeg outputs
* :param inputs: Pass custom params to FFmpeg inputs
* :param global_options: Pass custom params to FFmpeg global options
* :param path: The path to download the livestream video to
* :param duration: If duration is None or less than 1, download will go forever
* :param quality: If quality is None, download quality will auto
* :param verbose: Whether to log info about the download in console
*/
@Getter @Getter
@Setter @Setter
public class RecorderSettings { public class RecorderSettings {
@@ -63,19 +44,10 @@ public class RecorderSettings {
return new RecorderSettings(); return new RecorderSettings();
} }
public void setQuality(String format) {
this.format = format;
}
public void setQuality(LiveQuality quality) { public void setQuality(LiveQuality quality) {
this.quality = quality.name(); this.quality = quality.name();
} }
public void setFormat(String format) {
this.format = format;
}
public void setFormat(LiveFormat format) { public void setFormat(LiveFormat format) {
this.format = format.name(); this.format = format.name();
} }