一行配置完成迁移获取免费 API Key
一行配置,从 Euler Stream 迁移到 Tik.Tools
继续用 TikTokLive(Python)或 tiktok-live-connector(Node),只需换掉签名服务的 host。事件名不变,SDK 不变,代码不变。
// connector-drop-in.mjs
// Run: npm i tiktok-live-connector && node connector-drop-in.mjs
// Existing Euler Stream users: ONLY change is the signProviderHost line.
import { WebcastPushConnection } from 'tiktok-live-connector';
const USER = (process.argv[2] || '').replace(/^@/, '') || 'aljazeeraenglish';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
const conn = new WebcastPushConnection(USER, {
// ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
signProviderHost: 'https://api.tik.tools', // was: 'https://tiktok.eulerstream.com'
signProviderApiKey: KEY, // was: your Euler API key
// ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
enableExtendedGiftInfo: true,
});
conn.on('connected', s => console.log('Connected, room', s.roomId));
conn.on('chat', d => console.log('[chat]', d.uniqueId + ':', d.comment));
conn.on('gift', d => console.log('[gift]', d.uniqueId + ' sent', d.giftName, 'x' + d.repeatCount));
conn.on('like', d => console.log('[like]', d.uniqueId, '+' + d.likeCount));
conn.on('member', d => console.log('[join]', d.uniqueId));
conn.on('disconnected', () => console.log('Closed.'));
await conn.connect();# tiktoklive-drop-in.py
# Run: pip install TikTokLive && python tiktoklive-drop-in.py aljazeeraenglish
# Existing Euler Stream users: ONLY change is the sign_api_url line.
import sys
from TikTokLive import TikTokLiveClient
from TikTokLive.events import ConnectEvent, CommentEvent, GiftEvent, LikeEvent, JoinEvent
USER = (sys.argv[1] if len(sys.argv) > 1 else '').lstrip('@') or 'aljazeeraenglish'
KEY = 'your_api_key' # <- swap for your free key at https://tik.tools
client = TikTokLiveClient(
unique_id=USER,
# ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
sign_api_key=KEY, # was: your Euler API key
web_proxy='https://api.tik.tools', # was: https://tiktok.eulerstream.com (set via TIKTOK_LIVE_SIGN_HOST too)
# ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
)
@client.on(ConnectEvent)
async def on_connect(e): print('Connected, room', e.unique_id)
@client.on(CommentEvent)
async def on_chat(e): print(f"[chat] {e.user.unique_id}: {e.comment}")
@client.on(GiftEvent)
async def on_gift(e):
if e.gift.streakable and not e.streaking: return
print(f"[gift] {e.user.unique_id} sent {e.gift.name} x{e.repeat_count}")
@client.on(LikeEvent)
async def on_like(e): print(f"[like] {e.user.unique_id} +{e.count}")
@client.on(JoinEvent)
async def on_join(e): print(f"[join] {e.user.unique_id}")
client.run()<!DOCTYPE html>
<!-- Save as euler-dropin.html and double-click. No SDK install needed -
this hits the same sign endpoint Euler Stream users already use,
then pipes the events into a <video>-tag-friendly DOM stream. -->
<meta charset="utf-8">
<title>Tik.Tools - Euler Stream drop-in</title>
<style>
body{font:14px ui-monospace,Menlo,monospace;background:#0a0a0c;color:#e4e4e7;padding:20px;max-width:760px;margin:0 auto}
h1{font-size:18px;margin:0 0 8px}
.bar{display:flex;gap:8px;margin:8px 0 14px}
input,button{font:inherit;background:#14141a;color:#fff;border:1px solid #333;border-radius:6px;padding:6px 10px}
button{background:#2a2a2a;border:none;cursor:pointer;font-weight:700}
.row{padding:6px 10px;border-bottom:1px solid #222;display:flex;gap:10px}
.t{color:#d1d3d4;width:60px;font-size:11px;text-transform:uppercase}
</style>
<h1>Drop-in for Euler Stream</h1>
<div class="bar">
<input id="u" placeholder="username (default: aljazeeraenglish)" />
<button id="go">Connect</button>
</div>
<div id="s">Same flow Euler exposes: JWT mint -> WebSocket. Just point at api.tik.tools.</div>
<div id="feed"></div>
<script>
// EXACTLY the same call shape Euler users make to their /authentication/jwt.
// Only difference: BASE = 'https://api.tik.tools' (was: 'https://tiktok.eulerstream.com')
const BASE = 'https://api.tik.tools';
const WSURL = 'wss://api.tik.tools';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
let ws = null;
async function connect() {
if (ws) try { ws.close(); } catch {}
feed.innerHTML = '';
let user = u.value.trim().replace(/^@/, '');
if (!user) {
s.textContent = 'Picking a random live creator...';
try {
const r = await fetch(BASE + '/api/live/top-channels').then(r => r.json());
user = (r.channels && r.channels[0] && r.channels[0].uniqueId) || '';
} catch {}
if (!user) { s.textContent = 'No live creators right now, try again in a minute.'; return; }
}
s.textContent = 'Minting JWT...';
const j = await fetch(BASE + '/authentication/jwt?apiKey=' + KEY, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ allowed_creators: [user], expire_after: 600, max_websockets: 1 }),
}).then(r => r.json());
const token = j.data && j.data.token;
if (!token) { s.textContent = 'Auth failed - get a free key at https://tik.tools'; return; }
s.textContent = 'Connecting to @' + user + '...';
ws = new WebSocket(WSURL + '?uniqueId=' + user + '&jwtKey=' + encodeURIComponent(token));
ws.onopen = () => s.textContent = '@' + user + ' - LIVE (Euler-shape drop-in)';
ws.onmessage = ev => {
const e = JSON.parse(ev.data);
if (e.event === 'roomInfo' || !e.event) return;
const d = e.data || {}, nm = (d.user && d.user.nickname) || d.user_unique_id || 'someone';
const text = d.comment || (d.giftName ? 'sent ' + d.giftName + ' x' + (d.repeatCount || 1) : '');
feed.insertAdjacentHTML('afterbegin',
'<div class="row"><span class="t">' + e.event + '</span><span>' + nm + '</span><span style="color:#9aa0a6;flex:1">' + text + '</span></div>');
while (feed.children.length > 50) feed.removeChild(feed.lastChild);
};
ws.onclose = ev => { s.textContent = 'Closed: ' + (ev.reason || ev.code); };
}
go.onclick = connect;
// Auto-connect on load so the embedded preview starts immediately.
connect();
</script>Write me a minimal one-file program that migrates an existing Euler Stream TikTokLive integration to Tik.Tools. ONE config line changes.
For Python (using TikTokLive lib):
- Was: TikTokLiveClient(unique_id=X, sign_api_key='euler_key')
- Now: TikTokLiveClient(unique_id=X, sign_api_key='your_api_key', web_proxy='https://api.tik.tools')
- Set env TIKTOK_LIVE_SIGN_HOST=https://api.tik.tools OR pass web_proxy
For Node (tiktok-live-connector):
- Was: new WebcastPushConnection(X, { signProviderHost: 'https://tiktok.eulerstream.com', signProviderApiKey: 'euler_key' })
- Now: new WebcastPushConnection(X, { signProviderHost: 'https://api.tik.tools', signProviderApiKey: 'your_api_key' })
For raw HTML/JS (no SDK):
- POST https://api.tik.tools/authentication/jwt?apiKey=your_api_key body {"allowed_creators":["<user>"],"expire_after":600,"max_websockets":1}
- Open WS wss://api.tik.tools?uniqueId=<user>&jwtKey=<token>
The demo key 'your_api_key' is the public default: 10-min sessions, 1 concurrent WS, strict per-IP daily caps. For production parity with Euler, sign up at https://tik.tools for a real key + access to /webcast/fetch /webcast/sign_url /webcast/ws_credentials (full Euler endpoint shape).
Pick the language I asked for. Comment the swap line. Stupid simple to copy/paste.实时预览
无缝替换的效果,就在这里看
和 Euler 一样的握手流程:签发签名 token -> WebSocket。下方 iframe 运行的就是这段代码的 HTML 版本,直连 api.tik.tools。复制粘贴过去,输出完全一样。
euler-dropin.html运行中
滚动到此处后加载预览。
// connector-drop-in.mjs
// Run: npm i tiktok-live-connector && node connector-drop-in.mjs
// Existing Euler Stream users: ONLY change is the signProviderHost line.
import { WebcastPushConnection } from 'tiktok-live-connector';
const USER = (process.argv[2] || '').replace(/^@/, '') || 'aljazeeraenglish';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
const conn = new WebcastPushConnection(USER, {
// ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
signProviderHost: 'https://api.tik.tools', // was: 'https://tiktok.eulerstream.com'
signProviderApiKey: KEY, // was: your Euler API key
// ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
enableExtendedGiftInfo: true,
});
conn.on('connected', s => console.log('Connected, room', s.roomId));
conn.on('chat', d => console.log('[chat]', d.uniqueId + ':', d.comment));
conn.on('gift', d => console.log('[gift]', d.uniqueId + ' sent', d.giftName, 'x' + d.repeatCount));
conn.on('like', d => console.log('[like]', d.uniqueId, '+' + d.likeCount));
conn.on('member', d => console.log('[join]', d.uniqueId));
conn.on('disconnected', () => console.log('Closed.'));
await conn.connect();# tiktoklive-drop-in.py
# Run: pip install TikTokLive && python tiktoklive-drop-in.py aljazeeraenglish
# Existing Euler Stream users: ONLY change is the sign_api_url line.
import sys
from TikTokLive import TikTokLiveClient
from TikTokLive.events import ConnectEvent, CommentEvent, GiftEvent, LikeEvent, JoinEvent
USER = (sys.argv[1] if len(sys.argv) > 1 else '').lstrip('@') or 'aljazeeraenglish'
KEY = 'your_api_key' # <- swap for your free key at https://tik.tools
client = TikTokLiveClient(
unique_id=USER,
# ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
sign_api_key=KEY, # was: your Euler API key
web_proxy='https://api.tik.tools', # was: https://tiktok.eulerstream.com (set via TIKTOK_LIVE_SIGN_HOST too)
# ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
)
@client.on(ConnectEvent)
async def on_connect(e): print('Connected, room', e.unique_id)
@client.on(CommentEvent)
async def on_chat(e): print(f"[chat] {e.user.unique_id}: {e.comment}")
@client.on(GiftEvent)
async def on_gift(e):
if e.gift.streakable and not e.streaking: return
print(f"[gift] {e.user.unique_id} sent {e.gift.name} x{e.repeat_count}")
@client.on(LikeEvent)
async def on_like(e): print(f"[like] {e.user.unique_id} +{e.count}")
@client.on(JoinEvent)
async def on_join(e): print(f"[join] {e.user.unique_id}")
client.run()<!DOCTYPE html>
<!-- Save as euler-dropin.html and double-click. No SDK install needed -
this hits the same sign endpoint Euler Stream users already use,
then pipes the events into a <video>-tag-friendly DOM stream. -->
<meta charset="utf-8">
<title>Tik.Tools - Euler Stream drop-in</title>
<style>
body{font:14px ui-monospace,Menlo,monospace;background:#0a0a0c;color:#e4e4e7;padding:20px;max-width:760px;margin:0 auto}
h1{font-size:18px;margin:0 0 8px}
.bar{display:flex;gap:8px;margin:8px 0 14px}
input,button{font:inherit;background:#14141a;color:#fff;border:1px solid #333;border-radius:6px;padding:6px 10px}
button{background:#2a2a2a;border:none;cursor:pointer;font-weight:700}
.row{padding:6px 10px;border-bottom:1px solid #222;display:flex;gap:10px}
.t{color:#d1d3d4;width:60px;font-size:11px;text-transform:uppercase}
</style>
<h1>Drop-in for Euler Stream</h1>
<div class="bar">
<input id="u" placeholder="username (default: aljazeeraenglish)" />
<button id="go">Connect</button>
</div>
<div id="s">Same flow Euler exposes: JWT mint -> WebSocket. Just point at api.tik.tools.</div>
<div id="feed"></div>
<script>
// EXACTLY the same call shape Euler users make to their /authentication/jwt.
// Only difference: BASE = 'https://api.tik.tools' (was: 'https://tiktok.eulerstream.com')
const BASE = 'https://api.tik.tools';
const WSURL = 'wss://api.tik.tools';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
let ws = null;
async function connect() {
if (ws) try { ws.close(); } catch {}
feed.innerHTML = '';
let user = u.value.trim().replace(/^@/, '');
if (!user) {
s.textContent = 'Picking a random live creator...';
try {
const r = await fetch(BASE + '/api/live/top-channels').then(r => r.json());
user = (r.channels && r.channels[0] && r.channels[0].uniqueId) || '';
} catch {}
if (!user) { s.textContent = 'No live creators right now, try again in a minute.'; return; }
}
s.textContent = 'Minting JWT...';
const j = await fetch(BASE + '/authentication/jwt?apiKey=' + KEY, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ allowed_creators: [user], expire_after: 600, max_websockets: 1 }),
}).then(r => r.json());
const token = j.data && j.data.token;
if (!token) { s.textContent = 'Auth failed - get a free key at https://tik.tools'; return; }
s.textContent = 'Connecting to @' + user + '...';
ws = new WebSocket(WSURL + '?uniqueId=' + user + '&jwtKey=' + encodeURIComponent(token));
ws.onopen = () => s.textContent = '@' + user + ' - LIVE (Euler-shape drop-in)';
ws.onmessage = ev => {
const e = JSON.parse(ev.data);
if (e.event === 'roomInfo' || !e.event) return;
const d = e.data || {}, nm = (d.user && d.user.nickname) || d.user_unique_id || 'someone';
const text = d.comment || (d.giftName ? 'sent ' + d.giftName + ' x' + (d.repeatCount || 1) : '');
feed.insertAdjacentHTML('afterbegin',
'<div class="row"><span class="t">' + e.event + '</span><span>' + nm + '</span><span style="color:#9aa0a6;flex:1">' + text + '</span></div>');
while (feed.children.length > 50) feed.removeChild(feed.lastChild);
};
ws.onclose = ev => { s.textContent = 'Closed: ' + (ev.reason || ev.code); };
}
go.onclick = connect;
// Auto-connect on load so the embedded preview starts immediately.
connect();
</script>Write me a minimal one-file program that migrates an existing Euler Stream TikTokLive integration to Tik.Tools. ONE config line changes.
For Python (using TikTokLive lib):
- Was: TikTokLiveClient(unique_id=X, sign_api_key='euler_key')
- Now: TikTokLiveClient(unique_id=X, sign_api_key='your_api_key', web_proxy='https://api.tik.tools')
- Set env TIKTOK_LIVE_SIGN_HOST=https://api.tik.tools OR pass web_proxy
For Node (tiktok-live-connector):
- Was: new WebcastPushConnection(X, { signProviderHost: 'https://tiktok.eulerstream.com', signProviderApiKey: 'euler_key' })
- Now: new WebcastPushConnection(X, { signProviderHost: 'https://api.tik.tools', signProviderApiKey: 'your_api_key' })
For raw HTML/JS (no SDK):
- POST https://api.tik.tools/authentication/jwt?apiKey=your_api_key body {"allowed_creators":["<user>"],"expire_after":600,"max_websockets":1}
- Open WS wss://api.tik.tools?uniqueId=<user>&jwtKey=<token>
The demo key 'your_api_key' is the public default: 10-min sessions, 1 concurrent WS, strict per-IP daily caps. For production parity with Euler, sign up at https://tik.tools for a real key + access to /webcast/fetch /webcast/sign_url /webcast/ws_credentials (full Euler endpoint shape).
Pick the language I asked for. Comment the swap line. Stupid simple to copy/paste.分步说明
两步搞定,零重构。
1
换掉签名服务的 host
在 SDK 初始化里改两行配置,把签名后端从 https://tiktok.eulerstream.com 指向 https://api.tik.tools。现有的事件处理函数、直播间 ID 和 SDK 代码都不用动。所有 tik.tools API 套餐 都可以无缝替换;演示 Key your_api_key 无需注册即可使用,但限额较低。
// Node — tiktok-live-connector v2.x (verified working against api.tik.tools)
import { TikTokLiveConnection, SignConfig, WebcastEvent } from 'tiktok-live-connector'
SignConfig.basePath = 'https://api.tik.tools' // was: https://tiktok.eulerstream.com
SignConfig.apiKey = 'tk_your_key' // your tik.tools key
const conn = new TikTokLiveConnection('@username', { fetchRoomInfoOnConnect: false })
conn.on(WebcastEvent.CHAT, e => console.log(e.user.uniqueId, ':', e.comment))
await conn.connect()
// Or env-var (no code change at all):
// SIGN_API_URL=https://api.tik.tools SIGN_API_KEY=tk_your_key node app.js# Python — TikTokLive v6.6+ (one config swap, existing code unchanged)
from TikTokLive.client.web.web_settings import WebDefaults
from TikTokLive import TikTokLiveClient
from TikTokLive.events import CommentEvent
WebDefaults.tiktok_sign_url = "https://api.tik.tools" # was: https://tiktok.eulerstream.com
WebDefaults.tiktok_sign_api_key = "tk_your_key"
client = TikTokLiveClient(unique_id="@username")
@client.on(CommentEvent)
async def on_chat(ev): print(ev.user.unique_id, ":", ev.comment)
await client.connect() # add fetch_live_check=False if running from a datacenter IP
# Or env-var (zero code change):
# SIGN_API_URL=https://api.tik.tools SIGN_API_KEY=tk_your_key python app.py// Direct @eulerstream/euler-api-sdk users — swap basePath
import { EulerStreamApiClient } from '@eulerstream/euler-api-sdk'
const client = new EulerStreamApiClient({
basePath: 'https://api.tik.tools',
apiKey: 'tk_your_key',
})
// Every webcast.* / premium.* / moderation.* method routes to tik.tools.
const res = await client.webcast.retrieveRoomId('username')
console.log(res.data.room_id)// connector-drop-in.mjs
// Run: npm i tiktok-live-connector && node connector-drop-in.mjs
// Existing Euler Stream users: ONLY change is the signProviderHost line.
import { WebcastPushConnection } from 'tiktok-live-connector';
const USER = (process.argv[2] || '').replace(/^@/, '') || 'aljazeeraenglish';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
const conn = new WebcastPushConnection(USER, {
// ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
signProviderHost: 'https://api.tik.tools', // was: 'https://tiktok.eulerstream.com'
signProviderApiKey: KEY, // was: your Euler API key
// ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
enableExtendedGiftInfo: true,
});
conn.on('connected', s => console.log('Connected, room', s.roomId));
conn.on('chat', d => console.log('[chat]', d.uniqueId + ':', d.comment));
conn.on('gift', d => console.log('[gift]', d.uniqueId + ' sent', d.giftName, 'x' + d.repeatCount));
conn.on('like', d => console.log('[like]', d.uniqueId, '+' + d.likeCount));
conn.on('member', d => console.log('[join]', d.uniqueId));
conn.on('disconnected', () => console.log('Closed.'));
await conn.connect();# tiktoklive-drop-in.py
# Run: pip install TikTokLive && python tiktoklive-drop-in.py aljazeeraenglish
# Existing Euler Stream users: ONLY change is the sign_api_url line.
import sys
from TikTokLive import TikTokLiveClient
from TikTokLive.events import ConnectEvent, CommentEvent, GiftEvent, LikeEvent, JoinEvent
USER = (sys.argv[1] if len(sys.argv) > 1 else '').lstrip('@') or 'aljazeeraenglish'
KEY = 'your_api_key' # <- swap for your free key at https://tik.tools
client = TikTokLiveClient(
unique_id=USER,
# ↓↓↓ THE ONE LINE TO CHANGE ↓↓↓
sign_api_key=KEY, # was: your Euler API key
web_proxy='https://api.tik.tools', # was: https://tiktok.eulerstream.com (set via TIKTOK_LIVE_SIGN_HOST too)
# ↑↑↑ THE ONE LINE TO CHANGE ↑↑↑
)
@client.on(ConnectEvent)
async def on_connect(e): print('Connected, room', e.unique_id)
@client.on(CommentEvent)
async def on_chat(e): print(f"[chat] {e.user.unique_id}: {e.comment}")
@client.on(GiftEvent)
async def on_gift(e):
if e.gift.streakable and not e.streaking: return
print(f"[gift] {e.user.unique_id} sent {e.gift.name} x{e.repeat_count}")
@client.on(LikeEvent)
async def on_like(e): print(f"[like] {e.user.unique_id} +{e.count}")
@client.on(JoinEvent)
async def on_join(e): print(f"[join] {e.user.unique_id}")
client.run()<!DOCTYPE html>
<!-- Save as euler-dropin.html and double-click. No SDK install needed -
this hits the same sign endpoint Euler Stream users already use,
then pipes the events into a <video>-tag-friendly DOM stream. -->
<meta charset="utf-8">
<title>Tik.Tools - Euler Stream drop-in</title>
<style>
body{font:14px ui-monospace,Menlo,monospace;background:#0a0a0c;color:#e4e4e7;padding:20px;max-width:760px;margin:0 auto}
h1{font-size:18px;margin:0 0 8px}
.bar{display:flex;gap:8px;margin:8px 0 14px}
input,button{font:inherit;background:#14141a;color:#fff;border:1px solid #333;border-radius:6px;padding:6px 10px}
button{background:#2a2a2a;border:none;cursor:pointer;font-weight:700}
.row{padding:6px 10px;border-bottom:1px solid #222;display:flex;gap:10px}
.t{color:#d1d3d4;width:60px;font-size:11px;text-transform:uppercase}
</style>
<h1>Drop-in for Euler Stream</h1>
<div class="bar">
<input id="u" placeholder="username (default: aljazeeraenglish)" />
<button id="go">Connect</button>
</div>
<div id="s">Same flow Euler exposes: JWT mint -> WebSocket. Just point at api.tik.tools.</div>
<div id="feed"></div>
<script>
// EXACTLY the same call shape Euler users make to their /authentication/jwt.
// Only difference: BASE = 'https://api.tik.tools' (was: 'https://tiktok.eulerstream.com')
const BASE = 'https://api.tik.tools';
const WSURL = 'wss://api.tik.tools';
const KEY = 'your_api_key'; // <- swap for your free key at https://tik.tools
let ws = null;
async function connect() {
if (ws) try { ws.close(); } catch {}
feed.innerHTML = '';
let user = u.value.trim().replace(/^@/, '');
if (!user) {
s.textContent = 'Picking a random live creator...';
try {
const r = await fetch(BASE + '/api/live/top-channels').then(r => r.json());
user = (r.channels && r.channels[0] && r.channels[0].uniqueId) || '';
} catch {}
if (!user) { s.textContent = 'No live creators right now, try again in a minute.'; return; }
}
s.textContent = 'Minting JWT...';
const j = await fetch(BASE + '/authentication/jwt?apiKey=' + KEY, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ allowed_creators: [user], expire_after: 600, max_websockets: 1 }),
}).then(r => r.json());
const token = j.data && j.data.token;
if (!token) { s.textContent = 'Auth failed - get a free key at https://tik.tools'; return; }
s.textContent = 'Connecting to @' + user + '...';
ws = new WebSocket(WSURL + '?uniqueId=' + user + '&jwtKey=' + encodeURIComponent(token));
ws.onopen = () => s.textContent = '@' + user + ' - LIVE (Euler-shape drop-in)';
ws.onmessage = ev => {
const e = JSON.parse(ev.data);
if (e.event === 'roomInfo' || !e.event) return;
const d = e.data || {}, nm = (d.user && d.user.nickname) || d.user_unique_id || 'someone';
const text = d.comment || (d.giftName ? 'sent ' + d.giftName + ' x' + (d.repeatCount || 1) : '');
feed.insertAdjacentHTML('afterbegin',
'<div class="row"><span class="t">' + e.event + '</span><span>' + nm + '</span><span style="color:#9aa0a6;flex:1">' + text + '</span></div>');
while (feed.children.length > 50) feed.removeChild(feed.lastChild);
};
ws.onclose = ev => { s.textContent = 'Closed: ' + (ev.reason || ev.code); };
}
go.onclick = connect;
// Auto-connect on load so the embedded preview starts immediately.
connect();
</script>Write me a minimal one-file program that migrates an existing Euler Stream TikTokLive integration to Tik.Tools. ONE config line changes.
For Python (using TikTokLive lib):
- Was: TikTokLiveClient(unique_id=X, sign_api_key='euler_key')
- Now: TikTokLiveClient(unique_id=X, sign_api_key='your_api_key', web_proxy='https://api.tik.tools')
- Set env TIKTOK_LIVE_SIGN_HOST=https://api.tik.tools OR pass web_proxy
For Node (tiktok-live-connector):
- Was: new WebcastPushConnection(X, { signProviderHost: 'https://tiktok.eulerstream.com', signProviderApiKey: 'euler_key' })
- Now: new WebcastPushConnection(X, { signProviderHost: 'https://api.tik.tools', signProviderApiKey: 'your_api_key' })
For raw HTML/JS (no SDK):
- POST https://api.tik.tools/authentication/jwt?apiKey=your_api_key body {"allowed_creators":["<user>"],"expire_after":600,"max_websockets":1}
- Open WS wss://api.tik.tools?uniqueId=<user>&jwtKey=<token>
The demo key 'your_api_key' is the public default: 10-min sessions, 1 concurrent WS, strict per-IP daily caps. For production parity with Euler, sign up at https://tik.tools for a real key + access to /webcast/fetch /webcast/sign_url /webcast/ws_credentials (full Euler endpoint shape).
Pick the language I asked for. Comment the swap line. Stupid simple to copy/paste.2
准备好后,换成正式 API Key
演示 Key your_api_key 无需注册即可使用,但限制为 1 个 WebSocket / 每次会话 10 分钟 / 每个 IP 每小时 6 次连接。获取免费 Tik.Tools Key,即可获得更高限额,并完整对齐 Euler 的全部接口。
接口对齐
每个 Euler 接口都 1:1 对应
Tik.Tools 完整镜像了 Euler 的接口,原本对接 Euler 的 SDK 无需任何补丁即可继续工作。
| Euler Stream | Tik.Tools(路径相同) | 套餐 |
|---|---|---|
POST /webcast/sign_url | POST /webcast/sign_url | 演示 |
GET /webcast/check_alive | GET /webcast/check_alive | 演示 |
POST /webcast/fetch | POST /webcast/fetch | Basic+ |
POST /webcast/ws_credentials | POST /webcast/ws_credentials | Basic+ |
POST /webcast/sign_websocket | POST /webcast/sign_websocket | Basic+ |
GET /webcast/room_id | GET /webcast/room_id | 演示 |
POST /webcast/room_info | POST /webcast/room_info | 演示 |
POST /webcast/bulk_live_check | POST /webcast/bulk_live_check | Basic+ |
| 额外福利(Euler 没有): 公开实时动态、排行榜 | 演示 | |
响应结构完全一致。 sign_url 返回
{ status_code, data: { signed_url, x_bogus, user_agent, cookies } }。你现有的解析代码照常可用。响应结构
JSON 完全一致,外加迁移提示
POST https://api.tik.tools/webcast/sign_url?apiKey=your_api_key
Body: { "url": "<upstream URL>" }
Response:
{
"status_code": 0,
"data": {
"signed_url": "<signed upstream URL>",
"x_bogus": "...",
"user_agent": "Mozilla/5.0 ...",
"cookies": "ttwid=<fresh visitor cookie>"
}
}