mirror of
https://github.com/jwdeveloper/TikTokLiveJava.git
synced 2026-02-28 01:09:40 -05:00
Merge pull request #50 from kohlerpop1/fixes-updates
Fixed bug, added final, removed not needed initialization, and minor improvements.
This commit is contained in:
@@ -36,7 +36,6 @@ public class LiveClientSettings {
|
||||
/**
|
||||
* ISO-Language for Client
|
||||
*/
|
||||
|
||||
private String clientLanguage;
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,6 @@ public class LiveClientSettings {
|
||||
*/
|
||||
private boolean retryOnConnectionFailure;
|
||||
|
||||
|
||||
/**
|
||||
* Before retrying connect, wait for select amount of time
|
||||
*/
|
||||
@@ -53,42 +51,35 @@ public class LiveClientSettings {
|
||||
/**
|
||||
* Whether to print Logs to Console
|
||||
*/
|
||||
|
||||
private boolean printToConsole = true;
|
||||
|
||||
/**
|
||||
* LoggingLevel for Logs
|
||||
*/
|
||||
private Level logLevel;
|
||||
|
||||
|
||||
/**
|
||||
* Optional: Use it if you need to change TikTok live hostname in builder
|
||||
*/
|
||||
private String hostName;
|
||||
|
||||
|
||||
/**
|
||||
* Parameters used in requests to TikTok api
|
||||
*/
|
||||
private HttpClientSettings httpSettings;
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private String sessionId;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Optional: By default roomID is fetched before connect to live, but you can set it manually
|
||||
*
|
||||
*/
|
||||
private String roomId;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static LiveClientSettings createDefault()
|
||||
{
|
||||
var httpSettings = new HttpClientSettings();
|
||||
@@ -103,12 +94,10 @@ public class LiveClientSettings {
|
||||
clientSettings.setPrintToConsole(false);
|
||||
clientSettings.setLogLevel(Level.ALL);
|
||||
|
||||
|
||||
clientSettings.setHttpSettings(httpSettings);
|
||||
return clientSettings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default Parameters for HTTP-Request
|
||||
*/
|
||||
@@ -147,11 +136,9 @@ public class LiveClientSettings {
|
||||
clientParams.put("webcast_sdk_version", "1.3.0");
|
||||
clientParams.put("update_version_code", "1.3.0");
|
||||
|
||||
|
||||
return clientParams;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default Headers for HTTP-Request
|
||||
*/
|
||||
@@ -167,6 +154,4 @@ public class LiveClientSettings {
|
||||
headers.put("Accept-Language", "en-US,en; q=0.9");
|
||||
return headers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -87,6 +87,7 @@ public class ProxyClientSettings implements Iterator<ProxyData>
|
||||
@Override
|
||||
public void remove() {
|
||||
proxyList.remove(index);
|
||||
lastSuccess = false; // index is no longer valid and lastSuccess needs falsified
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import io.github.jwdeveloper.tiktok.*;
|
||||
import io.github.jwdeveloper.tiktok.data.dto.ProxyData;
|
||||
import io.github.jwdeveloper.tiktok.data.requests.LiveConnectionData;
|
||||
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 org.java_websocket.client.WebSocketClient;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
private final TikTokLiveEventHandler tikTokEventHandler;
|
||||
private WebSocketClient webSocketClient;
|
||||
|
||||
private TikTokWebSocketPingingTask pingingTask;
|
||||
private final TikTokWebSocketPingingTask pingingTask;
|
||||
private boolean isConnected;
|
||||
|
||||
public TikTokWebSocketClient(
|
||||
@@ -91,6 +91,20 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
}
|
||||
|
||||
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()) {
|
||||
ProxyData proxyData = proxySettings.next();
|
||||
if (!tryProxyConnection(proxySettings, proxyData)) {
|
||||
@@ -98,6 +112,7 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
proxySettings.remove();
|
||||
continue;
|
||||
}
|
||||
pingingTask.run(webSocketClient);
|
||||
isConnected = true;
|
||||
break;
|
||||
}
|
||||
@@ -107,21 +122,6 @@ public class TikTokWebSocketClient implements SocketClient {
|
||||
|
||||
public boolean tryProxyConnection(ProxyClientSettings proxySettings, ProxyData proxyData) {
|
||||
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.connect();
|
||||
return true;
|
||||
|
||||
@@ -11,24 +11,18 @@ public class TikTokWebSocketPingingTask
|
||||
private final int MIN_TIMEOUT = 250;
|
||||
private final int MAX_TIMEOUT = 500;
|
||||
|
||||
|
||||
public void run(WebSocket webSocket)
|
||||
{
|
||||
stop();
|
||||
thread = new Thread(() ->
|
||||
{
|
||||
pingTask(webSocket);
|
||||
});
|
||||
isRunning =true;
|
||||
thread = new Thread(() -> pingTask(webSocket));
|
||||
isRunning = true;
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
if(thread != null)
|
||||
{
|
||||
if (thread != null)
|
||||
thread.interrupt();
|
||||
}
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
@@ -36,12 +30,9 @@ public class TikTokWebSocketPingingTask
|
||||
private void pingTask(WebSocket webSocket)
|
||||
{
|
||||
var random = new Random();
|
||||
while (isRunning)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!webSocket.isOpen())
|
||||
{
|
||||
while (isRunning) {
|
||||
try {
|
||||
if (!webSocket.isOpen()) {
|
||||
Thread.sleep(100);
|
||||
continue;
|
||||
}
|
||||
@@ -50,11 +41,10 @@ public class TikTokWebSocketPingingTask
|
||||
var timeout = random.nextInt(MAX_TIMEOUT)+MIN_TIMEOUT;
|
||||
Thread.sleep(timeout);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
catch (Exception e) {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,24 +24,18 @@ package io.github.jwdeveloper.tiktok.extension.recorder.impl;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import io.github.jwdeveloper.tiktok.annotations.TikTokEventObserver;
|
||||
import io.github.jwdeveloper.tiktok.data.events.TikTokLiveEndedEvent;
|
||||
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.*;
|
||||
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.event.TikTokLiveRecorderStartedEvent;
|
||||
import io.github.jwdeveloper.tiktok.http.HttpClientFactory;
|
||||
import io.github.jwdeveloper.tiktok.live.LiveClient;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -86,13 +80,11 @@ public class RecorderListener implements LiveRecorder {
|
||||
throw new TikTokLiveException("Unable to find download live url!");
|
||||
}
|
||||
liveClient.getLogger().info("Live download url found!");
|
||||
|
||||
}
|
||||
|
||||
@TikTokEventObserver
|
||||
private void onConnected(LiveClient liveClient, TikTokConnectedEvent event) {
|
||||
liveDownloadThread = new Thread(() ->
|
||||
{
|
||||
liveDownloadThread = new Thread(() -> {
|
||||
try {
|
||||
var bufferSize = 1024;
|
||||
var url = new URL(downloadData.getFullUrl());
|
||||
@@ -102,40 +94,33 @@ public class RecorderListener implements LiveRecorder {
|
||||
socksConnection.setRequestProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
try (var in = new BufferedInputStream(socksConnection.getInputStream())) {
|
||||
var path = settings.getOutputPath() + File.separator + settings.getOutputFileName();
|
||||
var file = new File(path);
|
||||
file.getParentFile().mkdirs();
|
||||
var fileOutputStream = new FileOutputStream(file);
|
||||
byte dataBuffer[] = new byte[bufferSize];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) {
|
||||
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
var in = new BufferedInputStream(socksConnection.getInputStream());
|
||||
var path = settings.getOutputPath() + File.separator + settings.getOutputFileName();
|
||||
var file = new File(path);
|
||||
file.getParentFile().mkdirs();
|
||||
var fileOutputStream = new FileOutputStream(file);
|
||||
byte[] dataBuffer = new byte[bufferSize];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, bufferSize)) != -1) {
|
||||
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
liveDownloadThread.start();
|
||||
}
|
||||
|
||||
|
||||
private static void downloadUsingStream(String urlStr, String file) throws IOException {
|
||||
URL url = new URL(urlStr);
|
||||
BufferedInputStream bis = new BufferedInputStream(url.openStream());
|
||||
FileOutputStream fis = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[1024];
|
||||
int count = 0;
|
||||
while ((count = bis.read(buffer, 0, 1024)) != -1) {
|
||||
int count;
|
||||
while ((count = bis.read(buffer, 0, 1024)) != -1)
|
||||
fis.write(buffer, 0, count);
|
||||
}
|
||||
fis.close();
|
||||
bis.close();
|
||||
}
|
||||
@@ -143,25 +128,23 @@ public class RecorderListener implements LiveRecorder {
|
||||
|
||||
@TikTokEventObserver
|
||||
private void onDisconnected(LiveClient liveClient, TikTokDisconnectedEvent event) {
|
||||
liveDownloadThread.interrupt();
|
||||
if (isConnected())
|
||||
liveDownloadThread.interrupt();
|
||||
}
|
||||
|
||||
@TikTokEventObserver
|
||||
private void onDisconnected(LiveClient liveClient, TikTokLiveEndedEvent event) {
|
||||
liveDownloadThread.interrupt();
|
||||
if (isConnected())
|
||||
liveDownloadThread.interrupt();
|
||||
}
|
||||
|
||||
private int terminateFfmpeg(final Process process) {
|
||||
if (!process.isAlive()) {
|
||||
/*
|
||||
* ffmpeg -version, do nothing
|
||||
*/
|
||||
// ffmpeg -version, do nothing
|
||||
return process.exitValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* ffmpeg -f x11grab
|
||||
*/
|
||||
// ffmpeg -f x11grab
|
||||
System.out.println("About to destroy the child process...");
|
||||
try (final OutputStreamWriter out = new OutputStreamWriter(process.getOutputStream(), UTF_8)) {
|
||||
out.write('q');
|
||||
@@ -174,7 +157,7 @@ public class RecorderListener implements LiveRecorder {
|
||||
process.waitFor();
|
||||
}
|
||||
return process.exitValue();
|
||||
} catch (final InterruptedException ie) {
|
||||
} catch (InterruptedException ie) {
|
||||
System.out.println("Interrupted");
|
||||
ie.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
@@ -201,12 +184,10 @@ public class RecorderListener implements LiveRecorder {
|
||||
.get("flv")
|
||||
.getAsString();
|
||||
|
||||
|
||||
var sessionId = streamDataJsonObject.getAsJsonObject("common")
|
||||
.get("session_id")
|
||||
.getAsString();
|
||||
|
||||
|
||||
//main
|
||||
//https://pull-f5-tt03.fcdn.eu.tiktokcdn.com/stage/stream-3284937501738533765.flv?session_id=136-20240109000954BF818F1B3A8E5E39E238&_webnoredir=1
|
||||
//Working
|
||||
@@ -216,5 +197,7 @@ public class RecorderListener implements LiveRecorder {
|
||||
return new DownloadData(urlLink, sessionId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
private boolean isConnected() {
|
||||
return liveDownloadThread != null && liveDownloadThread.isAlive();
|
||||
}
|
||||
}
|
||||
@@ -29,25 +29,6 @@ import lombok.Setter;
|
||||
|
||||
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
|
||||
@Setter
|
||||
public class RecorderSettings {
|
||||
@@ -63,20 +44,11 @@ public class RecorderSettings {
|
||||
return new RecorderSettings();
|
||||
}
|
||||
|
||||
public void setQuality(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public void setQuality(LiveQuality quality) {
|
||||
this.quality = quality.name();
|
||||
}
|
||||
|
||||
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public void setFormat(LiveFormat format) {
|
||||
this.format = format.name();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user