Hode / verify.sh
Reooiq's picture
Replace app entirely with Reoo88/Tktktk (TikTok->YouTube relay manager)
35c2217
Raw History Blame Contribute Delete
6.69 kB
#!/bin/sh
# ุชุญู‚ู‘ู‚ ุจุนุฏ ุงู„ุฑูุน: ุชุฃูƒุฏ ุฃู† ู…ู„ูุงุช ุงู„ุณุจูŠุณ ุตุงุฑุช ุงู„ู†ุณุฎุฉ ุงู„ู…ูุตู„ูŽุญุฉ ูุนู„ู‹ุง.
# ุดุบู‘ู„ู‡ ุฏุงุฎู„ ุงู„ุณุจูŠุณ (Terminal) ุฃูˆ ู…ุญู„ูŠู‹ุง ุนู„ู‰ ุงู„ู…ุฌู„ุฏ ุงู„ุฐูŠ ูŠุญุชูˆูŠ ุงู„ู…ู„ูุงุช.
set -e
DIR="${1:-.}"
cd "$DIR"
echo "== ุงู„ู…ู„ูุงุช ุงู„ู…ูˆุฌูˆุฏุฉ =="
ls -1 Dockerfile flv_bridge.py relay.py youtube_manager.py
echo
echo "== 1) Dockerfile ูŠุญู…ู„ YOUTUBE_SEND_MODE =="
grep -q 'YOUTUBE_SEND_MODE=copy' Dockerfile && echo " OK" || { echo " FAIL โ€” Dockerfile ู‚ุฏูŠู…"; exit 1; }
echo
echo "== 2) flv_bridge.py ููŠู‡ FormatChanged =="
grep -q 'class FormatChanged' flv_bridge.py && echo " OK" || { echo " FAIL"; exit 1; }
grep -q '_video_signature' flv_bridge.py && echo " OK โ€” ูุญุต Sequence Header ู…ูˆุฌูˆุฏ" || { echo " FAIL"; exit 1; }
echo
echo "== 3) relay.py ููŠู‡ send_mode / canvas / note_format_change =="
for token in 'def send_mode' 'def canvas' 'def note_format_change' 'except FormatChanged' 'YOUTUBE_SEND_MODE'; do
grep -q "$token" relay.py && echo " OK โ€” $token" || { echo " FAIL โ€” ู†ุงู‚ุต $token"; exit 1; }
done
echo
echo "== 4) youtube_manager.py ููŠู‡ ู…ุนุงู„ุฌุฉ FormatChanged =="
grep -q 'from flv_bridge import FormatChanged' youtube_manager.py && echo " OK โ€” import" || { echo " FAIL"; exit 1; }
grep -q 'except FormatChanged' youtube_manager.py && echo " OK โ€” sender_loop" || { echo " FAIL"; exit 1; }
echo
echo "== 5) ุงู„ู…ู„ูุงุช ุชูุชุฑุฌูŽู… ุจุฏูˆู† ุฃุฎุทุงุก =="
python3 -m py_compile flv_bridge.py relay.py youtube_manager.py app.py && echo " OK"
echo
echo "== 6) ุงู„ุณู„ูˆูƒ ุงู„ูุนู„ูŠ: ุงู„ูˆุถุน ุงู„ุงูุชุฑุงุถูŠ = copyุŒ ูˆุงู„ุฃูˆุงู…ุฑ ุชูุจู†ู‰ ุตุญูŠุญู‹ุง =="
python3 - <<'PY'
import importlib.util, os, shutil, sys
def load(n, p):
s = importlib.util.spec_from_file_location(n, p); m = importlib.util.module_from_spec(s)
sys.modules[n] = m; s.loader.exec_module(m); return m
load('flv_bridge', 'flv_bridge.py'); rl = load('relay', 'relay.py')
r = rl.Relay(shutil.which('ffmpeg') or '/usr/bin/ffmpeg', lambda u: [], lambda u, m: None)
for mode in ('copy', 'fixed1080', 'fixed720'):
os.environ['YOUTUBE_SEND_MODE'] = mode
assert r.send_mode() == mode, mode
cmd = ' '.join(r.command('rtmps://a.rtmps.youtube.com:443/live2/KEY'))
if mode == 'copy':
assert '-c:v copy' in cmd and '-rtmp_enhanced_codecs hvc1' in cmd, cmd
assert 'libx264' not in cmd
else:
assert 'libx264' in cmd and 'pad=' in cmd and '-sc_threshold 0' in cmd, cmd
assert '-c:v copy' not in cmd
print(' OK โ€” %-9s -> %s' % (mode, cmd[:110] + '...'))
os.environ.pop('YOUTUBE_SEND_MODE', None)
assert r.send_mode() == 'copy', 'default must stay copy'
print(' OK โ€” ุจุฏูˆู† ุงู„ู…ุชุบูŠุฑ: ุงู„ุงูุชุฑุงุถูŠ copy (ู„ุง ุชุบูŠูŠุฑ ููŠ ุงู„ุณู„ูˆูƒ)')
PY
echo
echo "== 7) ุงุฎุชุจุงุฑ ุญูŠ: ุจุซ ูŠุบูŠู‘ุฑ ู…ู‚ุงุณู‡ ููŠ ุงู„ู…ู†ุชุตู =="
python3 - <<'PY'
import importlib.util, os, shutil, struct, subprocess, sys
def load(n, p):
s = importlib.util.spec_from_file_location(n, p); m = importlib.util.module_from_spec(s)
sys.modules[n] = m; s.loader.exec_module(m); return m
fb = load('flv_bridge', 'flv_bridge.py')
ff = shutil.which('ffmpeg')
if not ff:
print(' SKIP โ€” ffmpeg ุบูŠุฑ ู…ูˆุฌูˆุฏ'); sys.exit(0)
def enc(path, size, codec):
cmd = [ff, '-hide_banner', '-loglevel', 'error', '-y', '-f', 'lavfi',
'-i', 'testsrc2=size=%s:rate=30' % size, '-t', '3', '-c:v', codec]
if codec == 'libx265':
cmd += ['-x265-params', 'keyint=30:min-keyint=30:log-level=error', '-rtmp_enhanced_codecs', 'hvc1']
else:
cmd += ['-g', '30']
cmd += ['-f', 'flv', path]
subprocess.run(cmd, check=True)
def parse(p):
d = open(p, 'rb').read(); h = struct.unpack('>I', d[5:9])[0] + 4
pos = h; tags = []
while pos + 11 <= len(d):
t = d[pos]; sz = int.from_bytes(d[pos+1:pos+4], 'big')
ts = int.from_bytes(d[pos+4:pos+7], 'big') | (d[pos+7] << 24)
tags.append([t, ts, d[pos+11:pos+11+sz]]); pos += 11 + sz + 4
return d[:h], tags
def write(p, head, tags):
with open(p, 'wb') as f:
f.write(head)
for t, ts, b in tags:
f.write(bytes([t]) + len(b).to_bytes(3, 'big') + (ts & 0xFFFFFF).to_bytes(3, 'big')
+ bytes([(ts >> 24) & 0xFF]) + b'\0\0\0' + b + (11 + len(b)).to_bytes(4, 'big'))
for codec, ext in (('libx265', 'hevc'), ('libx264', 'h264')):
enc('/tmp/_a.flv', '1080x1920', codec); enc('/tmp/_b.flv', '720x1280', codec)
ha, ta = parse('/tmp/_a.flv'); _, tb = parse('/tmp/_b.flv')
base = max(x[1] for x in ta) + 34
merged = ta + [[t, ts + base, b] for t, ts, b in tb if t != 18]
write('/tmp/_sw.flv', ha, merged)
b = fb.FLVBridge()
raw = open('/tmp/_sw.flv', 'rb').read()
raised = False
try:
for i in range(0, len(raw), 65536):
b.feed(raw[i:i+65536])
except fb.FormatChanged:
raised = True
print(' %s: FormatChanged %s' % (ext.upper(), 'OK โ€” ุฑูุตุฏ ุงู„ุชุบูŠู‘ุฑ' if raised else 'FAIL'))
assert raised
# detection off (fixed canvas mode) must swallow it
b2 = fb.FLVBridge(detect_format_change=False); n = 0
for i in range(0, len(raw), 65536):
n += len(b2.feed(raw[i:i+65536]))
print(' %s: detect off -> emitted %d bytes, changes seen %d OK' % (ext.upper(), n, b2.format_changes))
PY
echo
echo "== 8) ุชูˆูƒู† ุชูŠูƒ ุชูˆูƒ: ุงู„ุตูŠุบ ูˆุงู„ุฃูˆู„ูˆูŠุงุช ูˆุนุฏู… ุงู„ุชุณุฑูŠุจ =="
python3 verify_tokens.py || { echo " FAIL"; exit 1; }
echo
echo "== 9) ูƒู„ ุทู„ุจุงุช ุชูŠูƒ ุชูˆูƒ ุชู…ุฑ ุนุจุฑ ุงู„ุชูˆูƒู† =="
COUNT=$(grep -c "tiktok_auth.headers(" app.py relay.py youtube_manager.py | awk -F: '{s+=$2} END {print s}')
echo " ู…ูˆุงุถุน tiktok_auth.headers(): $COUNT (ุงู„ู…ุชูˆู‚ุน 5)"
[ "$COUNT" -ge 5 ] || { echo " FAIL โ€” ูŠูˆุฌุฏ ุทู„ุจ ู„ุง ูŠุญู…ู„ ุงู„ุฌู„ุณุฉ"; exit 1; }
grep -q "tiktok_auth.py" Dockerfile && echo " OK โ€” Dockerfile ูŠู†ุณุฎ tiktok_auth.py" || { echo " FAIL"; exit 1; }
grep -q "TIKTOK_SESSIONID" Dockerfile && echo " OK โ€” Dockerfile ูŠุนู„ู† ู…ุชุบูŠุฑุงุช ุงู„ุชูˆูƒู†" || { echo " FAIL"; exit 1; }
grep -q "api/tiktok/token" app.py && echo " OK โ€” ู†ู‚ุงุท API ู„ู„ุชูˆูƒู† ู…ูˆุฌูˆุฏุฉ" || { echo " FAIL"; exit 1; }
grep -q "AgeRestricted" app.py && echo " OK โ€” ูƒุดู ุงู„ุชู‚ูŠูŠุฏ ุงู„ุนู…ุฑูŠ ู…ูˆุฌูˆุฏ" || { echo " FAIL"; exit 1; }
grep -q "renderTiktok" index.html && echo " OK โ€” ู„ูˆุญุฉ ุงู„ุชูˆูƒู† ููŠ ุงู„ูˆุงุฌู‡ุฉ" || { echo " FAIL"; exit 1; }
echo
echo "โœ… ูƒู„ ุงู„ูุญูˆุตุงุช ู†ุฌุญุช โ€” ุงู„ู…ู„ูุงุช ู…ูุตู„ูŽุญุฉ ูˆุฌุงู‡ุฒุฉ."