Skip to content

Releases: zfadhli/tokrec

v0.11.2

14 Jun 18:41
101d42d

Choose a tag to compare

[0.11.2] — 2026-06-15

Fixed

  • --no-normalize now actually disables normalization — the action handler
    only checked truthiness (if (opts.normalize)), so passing --no-normalize
    was silently ignored and normalization stayed on (the default). Now the boolean
    value is propagated correctly.
  • Post-processing no longer trusts the pipe byte counter — the early-return
    guard in processRecording() compared result.size === 0 using the in-memory
    pipe counter, which could diverge from the actual bytes written to disk under
    backpressure or error-recovery paths. Now it reads the real file size from disk
    via statSync, so valid recordings are never skipped.

What's Changed

Full Changelog: v0.11.1...v0.11.2

v0.11.1

14 Jun 16:35
9ffc5b0

Choose a tag to compare

Changed

  • --normalize defaults now accurate in docs — the README's CLI options table
    now correctly shows on (not off) for --normalize, and libopus/96k for
    the codec/bitrate defaults (matching the actual v0.10.0 behavior).

Added

  • Version banner shown in README example — the authentication output example
    now includes the tokrec v0.X.Y startup line.

What's Changed

Full Changelog: v0.11.0...v0.11.1

v0.11.0

14 Jun 16:31
04b9e69

Choose a tag to compare

Changed

  • CLI binary renamed from tiktok-live-recorder to tokrec — the installed
    binary is now tokrec instead of tiktok-live-recorder. Update any scripts or
    aliases accordingly.

Added

  • Version banner at startup — the CLI now shows tokrec v0.11.0 as the first
    line of output when running.

What's Changed

Full Changelog: v0.10.0...v0.11.0

v0.10.0

14 Jun 15:34
19d782e

Choose a tag to compare

Changed

  • Normalize audio now uses peaknorm's defaults (libopus/96k) — tokrec's
    hardcoded aac/128k defaults for --normalize-codec and
    --normalize-bitrate have been removed. When these flags are not
    explicitly provided, peaknorm's own defaults now apply: libopus audio
    codec at 96k bitrate (previously aac at 128k).

v0.9.1

14 Jun 15:13
da1657e

Choose a tag to compare

Changed

  • Consolidated download modulesdownload-stream.ts and download-hls.ts
    (which were 90% identical) merged into a single download.ts. The only difference
    (log message prefix) is now a parameterized label argument.
  • Utilities centralized in utils.tsfindFfmpegPath and formatDuration
    moved from ffmpeg-utils.ts to utils.ts, making the utility module the single
    source of truth for pure helper functions.
  • Removed getFfmpegPath() wrapper — the orchestrator (recorder/index.ts) now
    calls findFfmpegPath() directly instead of wrapping it in a one-liner that only
    added an error message.
  • ffmpeg-utils.ts scoped to pipe-only — after extracting general utilities, the
    module now only exports the core pipeFfmpegSegment primitive and its associated
    constants. Cleaner separation of concerns.
  • Removed no-op updateProgress from Display — the updateProgress() method
    was already a no-op (the recording timer is driven by an independent setInterval).
    Removed from the Display interface and the event subscription in index.ts. The
    download:progress event is still available in the recorder's event system for
    API consumers.

What's Changed

Full Changelog: v0.9.0...v0.9.1

v0.9.0

14 Jun 14:46
7106c77

Choose a tag to compare

Added

  • Recording elapsed timer — during recording, the spinner now shows a
    live counter that ticks every second (Recording... [1m 5s]) instead of
    a static Recording stream... message. Elapsed time is now visible from
    the very first second instead of waiting for the first progress event.

Changed

  • Audio normalization enabled by default--normalize is no longer
    needed; EBU R128 loudness normalization now runs automatically after
    every conversion. To disable, use --no-normalize.

Fixed

  • Offline status delayed 3 minutes after stream end — when a live stream
    ended, the recorder waited for the next poll tick (default 3 minutes) before
    reporting @user is offline. Now it immediately re-checks via the
    check_alive endpoint right after the recording finishes.
  • Misleading [last check: ...] label — the offline repeat message now
    shows [last online: ...] instead of [last check: ...], matching what
    the timestamp actually represents.

v0.8.0

14 Jun 13:20
49867ca

Choose a tag to compare

Added

  • Lightweight live check via /webcast/room/check_alive/ — new
    fetchCheckAlive(roomId) endpoint returns a tiny boolean response (~100 bytes)
    vs the multi-kilobyte room/info response. isRoomAlive() uses it as a
    cache-miss fallback. Down from kilobytes to ~100 bytes per check.
  • --debug CLI flag — gates [API_DEBUG] log output to stderr for
    troubleshooting without spamming the console by default.
  • Token-bucket rate limiter — limits API requests to --rate per second
    (default 5). Prevents WAF triggering on rapid polling or URL refresh loops.
  • Formal state machine — validated setState() transitions enforce the
    lifecycle: idle → polling → recording → converting → polling | stopped.
    Prevents invalid state transitions with clear error messages.
  • pendingRemuxes background queue — the stop() method now awaits
    in-flight conversion/segmenting promises with a 60-second timeout, ensuring
    they complete before the process exits.
  • Crash-safe MPEG-TS intermediate format — switched download output from
    raw FLV to MPEG-TS. TS is fully repair-able and append-friendly. The file
    survives even if FFmpeg is killed mid-write.
  • Segmenting disabled by defaultsegmentMinutes now defaults to 0
    (disabled). Simple TS→MP4 conversion is the default post-processing path.
  • Cookie source feedback — startup now logs which cookie source was used
    (ℹ Firefox cookies loaded or ℹ cookies.json loaded).
  • Auto-exit after -d recording — when a duration limit completes, the
    recorder now exits instead of going back to polling mode.
  • MP4 conversion result shown in terminal — the converted event is now
    wired to the display, showing ✔ Converted: filename.mp4 on success.

Fixed

  • Slardar WAF bypass — the HTML page scrape on www.tiktok.com was blocked
    by the WAF. The detection now falls through to the /api-live/user/room/
    endpoint which is not behind the WAF, using a Firefox TLS fingerprint for
    the HTTP session.
  • -d duration limit ignored during long segments — a single TikTok stream
    URL can stay alive for 90+ seconds. The duration check only ran between
    segments, so -d 1 could overshoot by 30+ seconds. Fixed by passing
    -t <remaining> to FFmpeg for per-segment enforcement.
  • AbortSignal listener memory leak — each sleep() call that used an
    AbortSignal added a new abort listener but never removed it. Fixed by
    cleaning up the listener in both the resolve and abort paths.
  • Race condition in FFmpeg abortproc.kill() could lose the race
    against proc.on("close"). Replaced with spawn() signal option which
    guarantees atomic cleanup.
  • Missing abort signal in some FFmpeg spawns — not all FFmpeg invocations
    received the abort signal, leaving orphaned processes on Ctrl-C. Fixed by
    threading the signal to every spawn call.
  • FFmpeg startup hang — a bad URL would cause FFmpeg to hang indefinitely.
    Added a 30-second startup timeout that escalates from SIGTERM to SIGKILL.
  • Process signal handlers accumulationprocess.on("SIGINT", ...) was
    called multiple times without process.off(), causing duplicate handlers.
    Fixed by removing handlers before re-registering.
  • Ctrl-C during recording left .ts unconvertedstop() aborted the
    converter signal before awaiting the in-flight tick, so the conversion
    skipped. Reordered stop() to let conversion complete first.
  • Memory leak from HTTP client + stream references — the download loop
    held references to HTTP responses that prevented GC. Fixed by draining and
    destroying stale sockets.

Changed

  • Download output format: FLV → MPEG-TS — FFMpeg now writes MPEG-TS
    (-f mpegts) instead of raw FLV. The .ts file is crash-safe: even if
    FFmpeg is killed mid-write, all data before the last complete TS packet is
    valid and playable.
  • Default segmenting disabledsegmentMinutes defaults to 0. Existing
    users who rely on segmenting should pass -s 20 (or their preferred value).
  • Architectural refactoring — the monolithic recorder.ts was split into
    9 focused files under src/recorder/. Shared utilities were extracted to
    ffmpeg-utils.ts. No behavioral changes.
  • Dependency bumps — various dependencies updated to latest versions.

What's Changed

Full Changelog: v0.7.1...v0.8.0

v0.7.1

10 Jun 03:54
12d2c7a

Choose a tag to compare

Fixed

  • Ctrl-C graceful shutdown now converts partial downloadsreader.cancel()
    was unreliable at resolving the pending read, causing a 60-second hang on
    Ctrl-C. Replaced with AbortController + Promise.race for instant abort
    (~5ms). The download catch block now flushes the in-memory buffer and closes
    the write stream so the partial FLV is valid for FFmpeg conversion.
  • Duplicate signals no longer force-exit mid-conversion — Bun fires both
    SIGINT and SIGTERM for a single Ctrl-C. The second signal is now silently
    ignored instead of calling process.exit(1), letting the graceful shutdown
    pipeline (abort → flush → convert → exit) finish.
  • Offline [last check: ...] timestamp now increases over time — the
    elapsed time was incorrectly measured from the previous poll tick instead of
    from the first offline detection, so it always showed the polling interval
    (e.g. always 3m ago) rather than growing (3m ago6m ago → ...).

Changed

  • CLI output alignment — removed the 2-space indent from all icon lines so
    spinners and icons both start at column 0, fixing visual misalignment.

What's Changed

Full Changelog: v0.7.0...v0.7.1

v0.7.0

10 Jun 03:16
2f90acf

Choose a tag to compare

Added

  • Audio normalization via peaknorm — new --normalize flag applies EBU R128
    two-pass loudness normalization using peaknorm. Configurable target loudness
    (--normalize-loudness), audio codec (--normalize-codec), and bitrate
    (--normalize-bitrate). Runs after conversion/segmenting on each MP4 file
    sequentially with a live progress spinner (Analyzing / Normalizing phases).

Fixed

  • Offline timestamp not updating — the [last check: ...] timestamp now
    correctly measures elapsed time from the first offline detection instead of
    from the previous poll tick, so it shows an increasing duration (e.g. 3m ago
    6m ago9m ago) rather than always displaying the polling interval.

Changed

  • Dependency upgrades — TypeScript 5.9 → 6.0, Biome 1.9 → 2.4,
    peaknorm 0.2.2 → 0.2.4.

What's Changed

Full Changelog: v0.6.0...v0.7.0

v0.6.0

09 Jun 23:45
dc4d2e1

Choose a tag to compare

What's Changed

Full Changelog: v0.5.0...v0.6.0

What's Changed

Full Changelog: v0.5.0...v0.6.0