tiktok-live-api 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,253 @@
1
+ // src/client.ts
2
+ import WebSocket from "ws";
3
+ var WS_BASE = "wss://api.tik.tools";
4
+ var VERSION = "1.0.0";
5
+ var TikTokLive = class {
6
+ /**
7
+ * Create a new TikTokLive client.
8
+ *
9
+ * @param uniqueId - TikTok username (without @)
10
+ * @param options - Configuration options
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const client = new TikTokLive('streamer', { apiKey: 'YOUR_KEY' });
15
+ * ```
16
+ */
17
+ constructor(uniqueId, options = {}) {
18
+ this._handlers = /* @__PURE__ */ new Map();
19
+ this._ws = null;
20
+ this._connected = false;
21
+ this._intentionalClose = false;
22
+ this._reconnectAttempts = 0;
23
+ this._eventCount = 0;
24
+ this.uniqueId = uniqueId.replace(/^@/, "");
25
+ this.apiKey = options.apiKey || process.env.TIKTOOL_API_KEY || "";
26
+ if (!this.apiKey) {
27
+ throw new Error("apiKey is required. Get a free key at https://tik.tools");
28
+ }
29
+ this.autoReconnect = options.autoReconnect ?? true;
30
+ this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;
31
+ }
32
+ /** Whether the client is currently connected. */
33
+ get connected() {
34
+ return this._connected;
35
+ }
36
+ /** Total number of events received this session. */
37
+ get eventCount() {
38
+ return this._eventCount;
39
+ }
40
+ on(event, handler) {
41
+ if (!this._handlers.has(event)) {
42
+ this._handlers.set(event, /* @__PURE__ */ new Set());
43
+ }
44
+ this._handlers.get(event).add(handler);
45
+ return this;
46
+ }
47
+ /**
48
+ * Remove an event handler.
49
+ *
50
+ * @param event - Event name
51
+ * @param handler - The handler to remove
52
+ */
53
+ off(event, handler) {
54
+ this._handlers.get(event)?.delete(handler);
55
+ return this;
56
+ }
57
+ _emit(event, data) {
58
+ const handlers = this._handlers.get(event);
59
+ if (!handlers) return;
60
+ for (const handler of handlers) {
61
+ try {
62
+ const result = handler(data);
63
+ if (result instanceof Promise) {
64
+ result.catch(
65
+ (err) => console.error(`Error in '${event}' handler:`, err)
66
+ );
67
+ }
68
+ } catch (err) {
69
+ console.error(`Error in '${event}' handler:`, err);
70
+ }
71
+ }
72
+ }
73
+ /**
74
+ * Connect to the TikTok LIVE stream.
75
+ *
76
+ * @returns Promise that resolves when connected, rejects on fatal error.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * await client.connect();
81
+ * ```
82
+ */
83
+ async connect() {
84
+ this._intentionalClose = false;
85
+ const uri = `${WS_BASE}?uniqueId=${this.uniqueId}&apiKey=${this.apiKey}`;
86
+ return new Promise((resolve, reject) => {
87
+ this._ws = new WebSocket(uri, {
88
+ headers: { "User-Agent": `tiktok-live-api/${VERSION}` }
89
+ });
90
+ this._ws.on("open", () => {
91
+ this._connected = true;
92
+ this._reconnectAttempts = 0;
93
+ this._emit("connected", { uniqueId: this.uniqueId });
94
+ resolve();
95
+ });
96
+ this._ws.on("message", (raw) => {
97
+ try {
98
+ const event = JSON.parse(raw.toString());
99
+ this._eventCount++;
100
+ const eventType = event.event || "unknown";
101
+ const data = event.data || event;
102
+ this._emit("event", event);
103
+ this._emit(eventType, data);
104
+ } catch {
105
+ }
106
+ });
107
+ this._ws.on("close", () => {
108
+ this._connected = false;
109
+ this._emit("disconnected", { uniqueId: this.uniqueId });
110
+ this._maybeReconnect();
111
+ });
112
+ this._ws.on("error", (err) => {
113
+ this._emit("error", { error: err.message });
114
+ if (!this._connected) reject(err);
115
+ });
116
+ });
117
+ }
118
+ /**
119
+ * Disconnect from the stream.
120
+ */
121
+ disconnect() {
122
+ this._intentionalClose = true;
123
+ if (this._ws) {
124
+ this._ws.close();
125
+ this._ws = null;
126
+ }
127
+ this._connected = false;
128
+ }
129
+ async _maybeReconnect() {
130
+ if (this._intentionalClose || !this.autoReconnect || this._reconnectAttempts >= this.maxReconnectAttempts) {
131
+ return;
132
+ }
133
+ this._reconnectAttempts++;
134
+ const delay = Math.min(2 ** (this._reconnectAttempts - 1) * 1e3, 3e4);
135
+ await new Promise((r) => setTimeout(r, delay));
136
+ try {
137
+ await this.connect();
138
+ } catch {
139
+ }
140
+ }
141
+ };
142
+
143
+ // src/captions.ts
144
+ import WebSocket2 from "ws";
145
+ var CAPTIONS_BASE = "wss://api.tik.tools/captions";
146
+ var VERSION2 = "1.0.0";
147
+ var TikTokCaptions = class {
148
+ /**
149
+ * Create a new TikTokCaptions client.
150
+ *
151
+ * @param uniqueId - TikTok username (without @)
152
+ * @param options - Configuration options
153
+ */
154
+ constructor(uniqueId, options = {}) {
155
+ this._handlers = /* @__PURE__ */ new Map();
156
+ this._ws = null;
157
+ this._connected = false;
158
+ this._intentionalClose = false;
159
+ this.uniqueId = uniqueId.replace(/^@/, "");
160
+ this.apiKey = options.apiKey || process.env.TIKTOOL_API_KEY || "";
161
+ if (!this.apiKey) {
162
+ throw new Error("apiKey is required. Get a free key at https://tik.tools");
163
+ }
164
+ this.translate = options.translate;
165
+ this.diarization = options.diarization ?? true;
166
+ this.maxDurationMinutes = options.maxDurationMinutes;
167
+ }
168
+ /** Whether currently connected and receiving captions. */
169
+ get connected() {
170
+ return this._connected;
171
+ }
172
+ on(event, handler) {
173
+ if (!this._handlers.has(event)) {
174
+ this._handlers.set(event, /* @__PURE__ */ new Set());
175
+ }
176
+ this._handlers.get(event).add(handler);
177
+ return this;
178
+ }
179
+ /** Remove an event handler. */
180
+ off(event, handler) {
181
+ this._handlers.get(event)?.delete(handler);
182
+ return this;
183
+ }
184
+ _emit(event, data) {
185
+ const handlers = this._handlers.get(event);
186
+ if (!handlers) return;
187
+ for (const handler of handlers) {
188
+ try {
189
+ const result = handler(data);
190
+ if (result instanceof Promise) {
191
+ result.catch(
192
+ (err) => console.error(`Error in '${event}' handler:`, err)
193
+ );
194
+ }
195
+ } catch (err) {
196
+ console.error(`Error in '${event}' handler:`, err);
197
+ }
198
+ }
199
+ }
200
+ /**
201
+ * Start receiving captions from the stream.
202
+ *
203
+ * @returns Promise that resolves when connected.
204
+ */
205
+ async connect() {
206
+ this._intentionalClose = false;
207
+ let params = `uniqueId=${this.uniqueId}&apiKey=${this.apiKey}`;
208
+ if (this.translate) params += `&translate=${this.translate}`;
209
+ if (this.diarization) params += "&diarization=true";
210
+ if (this.maxDurationMinutes)
211
+ params += `&max_duration_minutes=${this.maxDurationMinutes}`;
212
+ const uri = `${CAPTIONS_BASE}?${params}`;
213
+ return new Promise((resolve, reject) => {
214
+ this._ws = new WebSocket2(uri, {
215
+ headers: { "User-Agent": `tiktok-live-api/${VERSION2}` }
216
+ });
217
+ this._ws.on("open", () => {
218
+ this._connected = true;
219
+ this._emit("connected", { uniqueId: this.uniqueId });
220
+ resolve();
221
+ });
222
+ this._ws.on("message", (raw) => {
223
+ try {
224
+ const event = JSON.parse(raw.toString());
225
+ const msgType = event.type || "unknown";
226
+ this._emit(msgType, event);
227
+ } catch {
228
+ }
229
+ });
230
+ this._ws.on("close", () => {
231
+ this._connected = false;
232
+ this._emit("disconnected", { uniqueId: this.uniqueId });
233
+ });
234
+ this._ws.on("error", (err) => {
235
+ this._emit("error", { error: err.message });
236
+ if (!this._connected) reject(err);
237
+ });
238
+ });
239
+ }
240
+ /** Stop receiving captions. */
241
+ disconnect() {
242
+ this._intentionalClose = true;
243
+ if (this._ws) {
244
+ this._ws.close();
245
+ this._ws = null;
246
+ }
247
+ this._connected = false;
248
+ }
249
+ };
250
+ export {
251
+ TikTokCaptions,
252
+ TikTokLive
253
+ };
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "tiktok-live-api",
3
+ "version": "1.0.0",
4
+ "description": "Unofficial TikTok LIVE API Client — Real-time chat, gifts, viewers, battles, and AI live captions from any TikTok livestream. Managed WebSocket API with 99.9% uptime.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "tiktok",
26
+ "tiktok-live",
27
+ "tiktok-api",
28
+ "tiktok-live-api",
29
+ "tiktok-live-connector",
30
+ "tiktok-live-sdk",
31
+ "tiktok-websocket",
32
+ "tiktok-chat",
33
+ "tiktok-gifts",
34
+ "tiktok-bot",
35
+ "tiktok-data",
36
+ "tiktok-stream",
37
+ "tiktok-events",
38
+ "tiktok-viewer",
39
+ "live-streaming",
40
+ "live-chat",
41
+ "webcast",
42
+ "websocket",
43
+ "real-time",
44
+ "speech-to-text",
45
+ "captions",
46
+ "transcription",
47
+ "translation",
48
+ "tiktok-live-python",
49
+ "tiktok-tools",
50
+ "euler-stream",
51
+ "tiktoklive",
52
+ "tiktok-connector",
53
+ "tiktok-live-node",
54
+ "tiktok-live-js",
55
+ "tiktok-scraper",
56
+ "tiktok-monitoring",
57
+ "livestream-api"
58
+ ],
59
+ "author": {
60
+ "name": "TikTool",
61
+ "email": "support@tik.tools",
62
+ "url": "https://tik.tools"
63
+ },
64
+ "license": "MIT",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "https://github.com/tiktool/tiktok-live-api"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/tiktool/tiktok-live-api/issues"
71
+ },
72
+ "homepage": "https://tik.tools",
73
+ "dependencies": {
74
+ "ws": "^8.16.0"
75
+ },
76
+ "devDependencies": {
77
+ "@types/ws": "^8.5.10",
78
+ "tsup": "^8.0.0",
79
+ "typescript": "^5.3.0"
80
+ },
81
+ "engines": {
82
+ "node": ">=16.0.0"
83
+ }
84
+ }