diff --git a/.openclaw/skills/srs-develop/scripts/proxy-e2e-redis-test.sh b/.openclaw/skills/srs-develop/scripts/proxy-e2e-redis-test.sh index 148a81d18..e5e54f77b 100755 --- a/.openclaw/skills/srs-develop/scripts/proxy-e2e-redis-test.sh +++ b/.openclaw/skills/srs-develop/scripts/proxy-e2e-redis-test.sh @@ -38,7 +38,12 @@ PYTHON_BIN="${PYTHON_BIN:-python3}" SOURCE_FLV="$WORKSPACE/trunk/doc/source.flv" SRS_BINARY="$WORKSPACE/trunk/objs/srs" -TEST_STREAM_URL="__defaultVhost__/live/livestream" +# Randomize per run so each invocation uses unique Redis keys and never shares +# state with sibling E2E tests or a developer's local proxy that publishes to +# "live/livestream". +STREAM_NAME="redis$(date +%s)" +STREAM_PATH="live/$STREAM_NAME" +TEST_STREAM_URL="__defaultVhost__/$STREAM_PATH" # PIDs to clean up on exit. PROXY_A_PID="" @@ -279,7 +284,7 @@ echo "SRS origin started and registered in Redis." # --- Step 6: Publish RTMP stream to proxy A --- echo "=== Step 6: Publishing RTMP stream to proxy A ===" ffmpeg -stream_loop -1 -re -i "$SOURCE_FLV" -c copy -f flv \ - "rtmp://localhost:$PROXY_A_RTMP_PORT/live/livestream" >/tmp/srs-ffmpeg-redis-e2e.log 2>&1 & + "rtmp://localhost:$PROXY_A_RTMP_PORT/$STREAM_PATH" >/tmp/srs-ffmpeg-redis-e2e.log 2>&1 & FFMPEG_PID=$! echo "FFmpeg publisher PID: $FFMPEG_PID" @@ -296,7 +301,7 @@ echo "Stream publishing through proxy A." # --- Step 7: Verify RTMP playback through proxy B --- echo "=== Step 7: Verifying RTMP playback through proxy B ===" PROBE_OUTPUT=$(ffprobe -v error -show_streams \ - "rtmp://localhost:$PROXY_B_RTMP_PORT/live/livestream" 2>&1 || true) + "rtmp://localhost:$PROXY_B_RTMP_PORT/$STREAM_PATH" 2>&1 || true) if echo "$PROBE_OUTPUT" | grep -q "codec_type=video"; then echo "PASS: Video stream detected through proxy B." diff --git a/.openclaw/skills/srs-develop/scripts/proxy-e2e-srt-test.sh b/.openclaw/skills/srs-develop/scripts/proxy-e2e-srt-test.sh index 3bd387e8a..030894b47 100755 --- a/.openclaw/skills/srs-develop/scripts/proxy-e2e-srt-test.sh +++ b/.openclaw/skills/srs-develop/scripts/proxy-e2e-srt-test.sh @@ -35,7 +35,10 @@ ORIGIN_SRT_PORT=10081 SOURCE_FLV="$WORKSPACE/trunk/doc/source.flv" SRS_BINARY="$WORKSPACE/trunk/objs/srs" -STREAM_URL="live/livestream" +# Randomize per run so each invocation starts from clean origin state (HLS +# segments, RTMP source, proxy stream registry) and never shares state with +# sibling E2E tests that publish to "live/livestream". +STREAM_URL="live/srt$(date +%s)" # SRT streamid format used by SRS: "#!::r=/,m=publish|request". # @see trunk/3rdparty/srs-docs/doc/srt.md and internal/proxy/srt.go. diff --git a/.openclaw/skills/srs-develop/scripts/proxy-e2e-test.sh b/.openclaw/skills/srs-develop/scripts/proxy-e2e-test.sh index 093a731e5..61f25608e 100755 --- a/.openclaw/skills/srs-develop/scripts/proxy-e2e-test.sh +++ b/.openclaw/skills/srs-develop/scripts/proxy-e2e-test.sh @@ -24,6 +24,10 @@ PROXY_SYSTEM_API_PORT=12025 SOURCE_FLV="$WORKSPACE/trunk/doc/source.flv" SRS_BINARY="$WORKSPACE/trunk/objs/srs" ORIGIN_CONF="$WORKSPACE/trunk/conf/origin1-for-proxy.conf" +# Randomize per run so each invocation starts from clean origin state (HLS +# segments, RTMP source, proxy stream registry) and never shares state with +# sibling E2E tests that publish to "live/livestream". +STREAM_URL="live/rtmp$(date +%s)" # PIDs to clean up on exit. PROXY_PID="" @@ -143,7 +147,7 @@ echo "SRS origin started and registered." # --- Step 5: Publish RTMP stream --- echo "=== Step 5: Publishing RTMP stream to proxy ===" ffmpeg -stream_loop -1 -re -i "$SOURCE_FLV" -c copy -f flv \ - "rtmp://localhost:$PROXY_RTMP_PORT/live/livestream" >/tmp/srs-ffmpeg-e2e.log 2>&1 & + "rtmp://localhost:$PROXY_RTMP_PORT/$STREAM_URL" >/tmp/srs-ffmpeg-e2e.log 2>&1 & FFMPEG_PID=$! echo "FFmpeg publisher PID: $FFMPEG_PID" @@ -160,7 +164,7 @@ echo "Stream publishing." # --- Step 6: Verify RTMP playback --- echo "=== Step 6: Verifying RTMP playback via proxy ===" PROBE_OUTPUT=$(ffprobe -v error -show_streams \ - "rtmp://localhost:$PROXY_RTMP_PORT/live/livestream" 2>&1 || true) + "rtmp://localhost:$PROXY_RTMP_PORT/$STREAM_URL" 2>&1 || true) if echo "$PROBE_OUTPUT" | grep -q "codec_type=video"; then echo "PASS: Video stream detected." diff --git a/.openclaw/skills/srs-develop/scripts/proxy-e2e-transmux-test.sh b/.openclaw/skills/srs-develop/scripts/proxy-e2e-transmux-test.sh index c454d0458..0f9069857 100755 --- a/.openclaw/skills/srs-develop/scripts/proxy-e2e-transmux-test.sh +++ b/.openclaw/skills/srs-develop/scripts/proxy-e2e-transmux-test.sh @@ -32,7 +32,10 @@ ORIGIN_SRT_PORT=10081 SOURCE_FLV="$WORKSPACE/trunk/doc/source.flv" SRS_BINARY="$WORKSPACE/trunk/objs/srs" -STREAM_URL="live/livestream" +# Randomize per run so each invocation starts from clean origin state (HLS +# segments, RTMP source, proxy stream registry) and never shares state with +# sibling E2E tests that publish to "live/livestream". +STREAM_URL="live/transmux$(date +%s)" # PIDs to clean up on exit. PROXY_PID="" diff --git a/.openclaw/skills/srs-develop/scripts/proxy-e2e-whip-test.sh b/.openclaw/skills/srs-develop/scripts/proxy-e2e-whip-test.sh index 882a86d43..0127c6f58 100755 --- a/.openclaw/skills/srs-develop/scripts/proxy-e2e-whip-test.sh +++ b/.openclaw/skills/srs-develop/scripts/proxy-e2e-whip-test.sh @@ -35,12 +35,16 @@ ORIGIN_SRT_PORT=10081 SOURCE_FLV="$WORKSPACE/trunk/doc/source.flv" SRS_BINARY="$WORKSPACE/trunk/objs/srs" -STREAM_URL="live/livestream" +# Randomize the stream name per run so each test starts from a clean origin +# state (HLS segments, RTMP source, proxy stream registry) and never shares +# state with sibling E2E tests that publish to "live/livestream". +STREAM_NAME="whip$(date +%s)" +STREAM_URL="live/$STREAM_NAME" # WHIP endpoint exposed by the proxy. The proxy parses ?app=&stream= via # utils.ConvertURLToStreamURL, then forwards the SDP exchange to the backend # SRS origin. @see internal/proxy/api.go and internal/proxy/rtc.go. -WHIP_PUBLISH_URL="http://localhost:$PROXY_HTTP_API_PORT/rtc/v1/whip/?app=live&stream=livestream" +WHIP_PUBLISH_URL="http://localhost:$PROXY_HTTP_API_PORT/rtc/v1/whip/?app=live&stream=$STREAM_NAME" # Make the SRS origin advertise a host candidate that loops back through the # proxy. The proxy rewrites only the port in the SDP answer (origin RTC port @@ -117,6 +121,49 @@ wait_for_hls_playlist() { exit 1 } +first_hls_segment() { + local url="$1" + + curl -fsS "$url" 2>/dev/null | awk ' + /^[[:space:]]*$/ { next } + /^#/ { next } + { print; exit } + ' +} + +wait_for_hls_to_skip_first_segment() { + local url="$1" + local deadline=60 + local first_segment current_segment output + + first_segment="$(first_hls_segment "$url")" + if [[ -z "$first_segment" ]]; then + echo "FAIL: HLS playlist has no media segment: $url" >&2 + curl -fsS "$url" 2>&1 || true + exit 1 + fi + + echo "Waiting for HLS to skip the first possibly incomplete segment (up to ${deadline}s): $first_segment" + for ((i = 1; i <= deadline; i++)); do + current_segment="$(first_hls_segment "$url")" + if [[ -n "$current_segment" && "$current_segment" != "$first_segment" ]]; then + output=$("$FFPROBE_BIN" -v error -show_streams "$url" 2>&1 || true) + if echo "$output" | grep -q "codec_type=video" && echo "$output" | grep -q "codec_type=audio"; then + echo "HLS first segment advanced and audio/video is ready: $current_segment" + return + fi + fi + sleep 1 + done + + echo "FAIL: HLS did not skip the first segment and expose audio/video in ${deadline}s." >&2 + echo "Last HLS response:" >&2 + curl -fsS "$url" 2>&1 || true + echo "Last ffprobe output:" >&2 + echo "$output" >&2 + exit 1 +} + echo "=== E2E WHIP Proxy Test ===" echo "Workspace: $WORKSPACE" echo "Stream: $STREAM_URL" @@ -285,6 +332,7 @@ probe_has_audio_video "HTTP-FLV" "http://localhost:$PROXY_HTTP_SERVER_PORT/$STRE echo "=== Step 8: Verifying HLS playback via proxy ===" HLS_URL="http://localhost:$PROXY_HTTP_SERVER_PORT/$STREAM_URL.m3u8" wait_for_hls_playlist "$HLS_URL" +wait_for_hls_to_skip_first_segment "$HLS_URL" probe_has_audio_video "HLS" "$HLS_URL" # --- Step 9: WebRTC WHEP playback (placeholder) ---