بنقرة واحدة
test-stream
Boot the app, stream via RTMP, watch via HLS/DASH, and validate the full pipeline
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Boot the app, stream via RTMP, watch via HLS/DASH, and validate the full pipeline
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Update CLAUDE.md and README.md to reflect code changes
Audit the codebase for hexagonal architecture violations (forbidden imports, dependency direction, port conformance)
Explain Theatrum's hexagonal (ports & adapters) architecture with concrete examples from the codebase
Expert reference on streaming protocols (HLS, DASH, RTMP, adaptive bitrate) grounded in Theatrum's implementation
Write Go unit and e2e tests following Theatrum's exact conventions
Manage and extend the CI/CD pipeline (GitHub Actions, Docker, build scripts)
| name | test-stream |
| description | Boot the app, stream via RTMP, watch via HLS/DASH, and validate the full pipeline |
| disable-model-invocation | true |
This skill walks through a complete end-to-end test of Theatrum: build, start, stream via RTMP, validate HLS output, check metrics, and clean up. Use $ARGUMENTS to customize (e.g., /test-stream passthrough or /test-stream with-recording).
!cat config.yml 2>/dev/null || echo "No config.yml found — will create a test config"
Verify required tools are installed:
ffmpeg -version | head -1
go version
curl --version | head -1
If any are missing, stop and inform the user.
If no test input video exists, generate a 30-second test pattern:
ffmpeg -f lavfi -i "testsrc=duration=30:size=1280x720:rate=30" \
-f lavfi -i "sine=frequency=440:duration=30" \
-c:v libx264 -preset ultrafast -c:a aac -b:a 128k \
-pix_fmt yuv420p /tmp/theatrum_test_input.mp4
If no config.yml exists, create a minimal test config. Use a passthrough live stream for simplicity:
application:
public_path: "http://localhost:8080"
server:
http: 8080
rtmp: 1935
rtmp_config:
reconnect_delay: 5
cleanup_delay: 10
channels:
"/test/{username}":
stream:
type: live
path: "test/{username}"
live_stream_key: "testkey123"
auth_token_template: "{username}"
distribution:
hls:
segment_duration: 2
window_size: 3
viewers:
enabled: true
window: 5
views:
enabled: true
window: 5
# Build
cd src && go build -o ../theatrum ./cmd/main.go && cd ..
# Start in background
./theatrum &
THEATRUM_PID=$!
echo "Theatrum started with PID $THEATRUM_PID"
# Wait for startup
sleep 2
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/metrics
Expected: HTTP 200 from /metrics.
The RTMP auth token is computed via XOR. For the test config above (key=testkey123, username=alice):
python3 -c "
key = 'testkey123'
username = 'alice'
result = bytes([ord(c) ^ ord(key[i % len(key)]) for i, c in enumerate(username)])
print(result.hex())
"
This outputs the hex token to use as the RTMP publishing name.
TOKEN=$(python3 -c "
key = 'testkey123'
username = 'alice'
result = bytes([ord(c) ^ ord(key[i % len(key)]) for i, c in enumerate(username)])
print(result.hex())
")
ffmpeg -re -i /tmp/theatrum_test_input.mp4 \
-c copy -f flv \
"rtmp://localhost/test/alice/$TOKEN" &
FFMPEG_PID=$!
echo "FFmpeg streaming with PID $FFMPEG_PID"
Wait a few seconds for segments to be generated:
sleep 8
Check that playlists/manifests and segments are being served:
echo "=== HLS Playlist ==="
curl -s http://localhost:8080/test/alice/default/playlist.m3u8
echo ""
echo "=== Segment check ==="
SEGMENT=$(curl -s http://localhost:8080/test/alice/default/playlist.m3u8 | grep '.ts' | head -1)
if [ -n "$SEGMENT" ]; then
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8080/test/alice/default/$SEGMENT")
echo "Segment HTTP status: $HTTP_CODE"
else
echo "ERROR: No segments found in playlist"
fi
curl -s http://localhost:8080/test/alice/master.m3u8
curl -s http://localhost:8080/test/alice/low/playlist.m3u8
If the channel uses DASH distribution, check the MPD manifest:
echo "=== DASH Manifest ==="
curl -s http://localhost:8080/test/alice/manifest.mpd
echo ""
echo "=== DASH Segment check ==="
# Check an init segment
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8080/test/alice/init-stream0.m4s")
echo "Init segment HTTP status: $HTTP_CODE"
Both endpoints should work:
curl -s -o /dev/null -w "HLS: %{http_code}\n" http://localhost:8080/test/alice/master.m3u8
curl -s -o /dev/null -w "DASH: %{http_code}\n" http://localhost:8080/test/alice/manifest.mpd
echo "=== Theatrum Metrics ==="
curl -s http://localhost:8080/metrics | grep "theatrum_"
Expected metrics to see:
theatrum_stream_viewers — Concurrent viewers per streamtheatrum_stream_views — Total views per streamtheatrum_http_requests_total — HTTP request counttheatrum_stream_duration_seconds — Active stream durationstheatrum_ffmpeg_exits_total — FFmpeg process exitstheatrum_rtmp_received_bytes_total — Bytes received via RTMPIf viewers/views are enabled, test them:
# Simulate a viewer by requesting segments repeatedly
for i in $(seq 1 10); do
SEGMENT=$(curl -s http://localhost:8080/test/alice/default/playlist.m3u8 | grep '.ts' | tail -1)
[ -n "$SEGMENT" ] && curl -s -o /dev/null "http://localhost:8080/test/alice/default/$SEGMENT"
sleep 2
done &
# After the window period, check counts
sleep 10
echo "Viewers: $(curl -s http://localhost:8080/test/alice/viewers.txt)"
echo "Views: $(curl -s http://localhost:8080/test/alice/views.txt)"
# Stop FFmpeg
kill $FFMPEG_PID 2>/dev/null
# Wait for stream cleanup
sleep 5
# Stop Theatrum
kill $THEATRUM_PID 2>/dev/null
# Remove test data
rm -rf data/test/
rm -f /tmp/theatrum_test_input.mp4
echo "Cleanup complete"
| Symptom | Cause | Fix |
|---|---|---|
Connection refused on RTMP | Theatrum not running or port in use | Check $THEATRUM_PID, check lsof -i :1935 |
401 or auth error | Wrong token | Recompute token; verify live_stream_key and auth_token_template match config |
| Empty playlist | FFmpeg not started or segments not yet written | Wait longer; check FFmpeg stderr; check data/ directory |
404 on playlist | Wrong URL path | Path must match stream.path in config (e.g., test/alice/default/playlist.m3u8) |
| No metrics | Theatrum crashed | Check stderr output; look for panic or bind errors |
| Segments 404 but playlist 200 | Segments being deleted faster than requested | Increase window_size in config |
| FFmpeg exits immediately | Input file issue or RTMP rejected | Check FFmpeg stderr; verify RTMP URL and token |