TikTok capture pipeline
Run pipeline.sh. Do not re-derive ffmpeg, mpv, or Xvfb commands yourself, and
do not attempt to judge whether a recording succeeded by eye or by duration.
The one rule
Never report a capture as successful. Only pipeline.sh decides that, by exit
code.
This matters because a recording that silently loses its last second still has
exactly the right duration and exactly the right frame count. Only the
first-frame/last-frame comparison in verify.py catches it. If you are ever
tempted to check duration or file size and call it good, that is exactly the
failure this pipeline exists to prevent.
Run one job
OUT_DIR=/data/out ./pipeline.sh "https://www.tiktok.com/@user/video/123"
With cookies, when the source needs a session:
OUT_DIR=/data/out COOKIES=/data/cookies.txt ./pipeline.sh "$URL"
Run a batch
Read URLs one per line from a queue file and loop. Run serially unless you have checked the CPU budget first — each job needs roughly 2 vCPU to hold 30fps without dropping frames, and each job takes a display number and PulseAudio instance derived from its own PID, so concurrent runs do not collide.
while read -r url; do
[ -z "$url" ] && continue
OUT_DIR=/data/out ./pipeline.sh "$url" || echo "FAILED: $url"
done < queue.txt
Exit codes
| Code | Meaning | Do this |
|---|---|---|
| 0 | Verified | Record the output path. Nothing else to do. |
| 3 | Missing dependency | Stop and report. Not retryable. |
| 10 | Download failed | Expected. Blocked, private, or removed. Log and move on. |
| 11 | Source has no audio | Log and move on. |
| 12 | Transcode failed | Log. Retry once, then report. |
| 13 | Capture failed | Check Xvfb/pulseaudio are installed and the display range is free. |
| 14 | Trim failed | The lead-in could not be measured or validated. Report; do not retry blindly. |
| 15 | Verification failed | Output is at <output>.rejected. Report as a pipeline defect. |
Exit code 10 is routine, not an incident. On a datacenter IP it is the expected outcome for a large share of URLs. Report it as a count, do not retry it in a loop.
When things fail repeatedly
Exit 14 or 15 means the pipeline itself is wrong, not the video. Read the run's
manifest.json measurements — first_frame_mae and last_frame_mae separate
the two cases:
- last frame MAE high, first frame MAE low → the lead was measured short and the ending was truncated.
- both high → the capture is misaligned or the display never updated.
Report the numbers rather than adjusting tolerances to force a pass. Raising
--match-threshold to get a green result is not a fix.