Commit Graph

8941 Commits

Author SHA1 Message Date
Winlin
0f980d49a6
RTMP: Fix chunk timestamp/basic-header decoding and harden packet unmarshal. v8.0.3 (#4680)
Fixes three RTMP chunk-stream decoding bugs in the proxy and hardens AMF0 command-packet unmarshalling against malformed input, backed by a new protocol unit-test suite.

All changes are confined to the `internal/rtmp` package. No public API, log format, or emitted wire format changes — these are decode-correctness and robustness fixes only.

**3-byte chunk basic header decode (`readBasicHeader`) **

The 3-byte basic-header form (cid 64–65599) was selected by testing `cid == 1` *after* `cid` had already been overwritten with `64 + t`, so it was never detected. Capture the original marker before overwriting and test that instead.

**Extended-timestamp handling (`chunkStream`, `readMessageHeader`)**

- Use the extended timestamp as a delta for fmt=1/2 chunks (and a fmt=3 first chunk continuing them), required when the delta is ≥ `0xffffff`. Timestamp computation is unified into a single post-step: extended timestamp when present, otherwise the 3-byte header delta; fmt=0 absolute, fmt=1/2 accumulated.
- Detect Type-3 chunks that omit the extended timestamp. FMLE/FMS/Flash follow the RTMP 2012 spec and always send it on Type-3 chunks; librtmp/ffmpeg may not. Switched from an unconditional 4-byte read to `Peek` + conditional `Discard`: if the peeked value differs from the stored one on a non-first chunk, those 4 bytes are payload and are left in the reader.
- Split the single `extendedTimestamp` bool into `hasExtendedTimestamp` (bool) and `extendedTimestamp` (the last raw value, used for the detection above).

**Packet unmarshal hardening**
- Add an `advanceBytes(p, n)` helper that bounds-checks each `p = p[field.Size():]` advance, turning a slice-out-of-range panic into a clean error on truncated/untrusted input. Applied in `CallPacket`, `CreateStreamResPacket`, `PublishPacket`, and `PlayPacket`.
- Reset the optional `CommandObject` / `Args` to nil before probing for their presence, so a stale constructor default (e.g. Null) isn't counted by `Size()` and can't overflow a later advance.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 07:17:32 -04:00
Winlin
8df9410880
Edge: Fix HTTP-FLV 404 and RTMP late-join missing sequence headers. v8.0.2 (#4678)
Two edge-cluster regressions surfaced when validating an RTMP
origin/edge setup. Each is a small, surgical fix in its own commit.

- **HTTP-FLV play on edge always 404'd.**
`SrsHttpStreamServer::assemble()` registered the dynamic matcher only
when the mux cast was `NULL` (inverted guard), so the matcher was never
wired up. On edge the FLV mount is created lazily by the dynamic
matcher, so every HTTP-FLV client got 404. Invert the guard to register
when the mux is valid, mirroring the destructor.
(`trunk/src/app/srs_app_http_stream.cpp`)

- **RTMP players that join an edge stream after the first player fail to
decode.** After v7.0.94 (#4513) stopped creating `SrsOriginHub` on edge,
the `hub_active` gate in `SrsLiveSource::consumer_dumps()` always
evaluated false on edge. That gate guards the dump of cached
`onMetaData` + AVC sequence header + AAC sequence header + GOP cache to
a new consumer. Result: the first player attaches before the edge-pull
starts and gets headers via the live fan-out, but every subsequent
player gets coded payload with no codec config and ffmpeg aborts with
`dimensions not set` / `Could not write header`. Fall back to the meta
cache state when `hub_` is `NULL`, so the dump path runs once the
edge-pull has populated the cache.
(`trunk/src/app/srs_app_rtmp_source.cpp`)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:53:30 -04:00
Winlin
913b773282
Proxy: Fix RTC/SRT reader leak, legacy WHEP unwrap, WHEP perf guide. v8.0.1 (#4676)
- Fix a goroutine leak on the WHEP path: the backend→client reader was
being spawned on every inbound client packet (STUN keepalives + RTCP
feedback), leaking tens of thousands of goroutines under steady-state
load. Now spawned exactly once per connection via `sync.Once` on both
the RTC and SRT proxies. Listener and reader receive buffers are also
reused across iterations.
- Make the legacy SRS `/rtc/v1/play/` and `/rtc/v1/publish/` APIs work
end-to-end through the proxy. Those endpoints wrap the SDP in a JSON
envelope (`{"sdp":"v=0\r\n..."}` where `\r\n` is the literal 2-byte JSON
escape, not real CRLF), so ICE parsing previously absorbed the rest of
the body into the ufrag. Added `unwrapSDPEnvelope` for ICE extraction
and tightened `ParseIceUfragPwd`'s value class to stop at `\`. The bytes
forwarded to the client and the in-body candidate-port rewrite still
operate on the raw envelope.
- Enable `net/http/pprof` endpoints when `GO_PPROF` is set (blank import
in `internal/debug/pprof.go`) and add `docs/perf/proxy-whep.md` walking
through CPU/alloc/heap/goroutine/trace collection and `pprof -base`
before/after diffs for the WHEP workload (1 publisher + N players).
- Tighten `SRTHandshakePacket.UnmarshalBinary` to
`bytes.Clone(ExtraData)` so decoded handshakes kept on the connection
(`handshake0`, `handshake2`) stay valid once the receive buffer is
reused.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 21:13:21 -04:00
winlin
57d1062e91 Code name: Free. v8.0.0
"Free" represents the new era of open source development empowered by AI. Both freedom and free — the AI agent is not just free labor, it is like a copy of myself, or even tens of copies, all deeply understanding this project, how to deliver high-quality code, and how to serve the community. AI handles all the dirty work — the boring tasks, the documentation, the coding — and often does it better than I could, with ten times the power. We built an AI robot for the community to answer questions and help users learn this project, and we used AI to almost entirely rewrite the SRS Proxy server — its structure, its workflow — so that AI agents can comprehensively manage and maintain it. With AI I have power, and I have choice: no longer waiting for other developers to contribute, I am free to manage this project, freed from the labor of maintaining it alone. This is a fantastic, amazing new era for building and sustaining open source projects and communities.
2026-05-17 12:34:04 -04:00
Winlin
6ee6f1ca5f Proxy: Refactor for testability; add SRT/WHIP E2E and unit tests. v7.0.148 (#4675)
- Refactor the Go proxy for dependency injection: every proxy server,
the bootstrap, the signal handler, the load balancers, and AMF0 now accept
functional-option seams (factories/closures) so tests can inject fakes
without binding real sockets, talking to real Redis, or racing on
package globals.

- Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates
the LB locally and threads it through every proxy server constructor. Two old
global indirections in `internal/signal` and `internal/rtmp/amf0` are
likewise replaced by per-instance fields.

- Rename `internal/server` → `internal/proxy` and rename the `lb` public
surface for clarity: `SRSLoadBalancer` is split into `OriginService` /
`HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`;
`SRSServer` → `OriginServer`; all proxy server types gain a `Proxy`
qualifier (e.g. `RTMPServer` → `RTMPProxyServer`).

- Extract the Redis client behind a new `internal/redisclient` package
with a minimal `RedisClient` interface and a counterfeiter fake.

- Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`)
and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all
five proxy servers, the signal handler, and AMF0.

- Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through
proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh`
(WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus
`setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with
openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed.

- Workspace reorg: move `memory/` and `skills/` to the repo root so all
agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via
symlinks. Sync `docs/proxy/proxy-load-balancer.md` and
`memory/srs-codebase-map.md` with the new names.

No protocol, log, HTTP API, or wire-format changes. Refactor only — all
  externally observable proxy behavior is unchanged.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-05-17 12:09:07 -04:00
Winlin
3663a8e38f
Proxy: Refactor server APIs and expand RTMP test coverage. v7.0.147 (#4672)
This PR refactors the Go proxy server internals and significantly
expands RTMP/proxy verification coverage.

- Rename internal/protocol to internal/server to better describe the
package responsibility.
- Refactor proxy server constructors and types toward cleaner exported
interfaces:
      - NewRTMPServer
      - NewWebRTCServer
      - NewHTTPAPIServer
      - NewHTTPStreamServer
      - NewSystemAPI
  - Expose RTMP protocol interfaces for better testability:
      - Handshake
      - Protocol
      - Message
- AMF0 public interfaces such as Amf0Any, Amf0Number, Amf0String,
Amf0Object, etc.
- Add RTMP unit tests covering AMF0, handshake, protocol messages,
packet encoding/decoding, and API examples.
  - Add generated RTMP fakes for interface-based tests.
  - Add proxy E2E scripts for:
      - multi-origin memory load-balancer routing
      - Redis multi-proxy routing
- RTMP transmuxing verification across RTMP, HTTP-FLV, HLS, and optional
WebRTC WHEP
- Update OpenClaw/SRSBot development docs and memory to reflect the new
package layout, new verification scripts, and unsupported origin/edge
development scope.

---------

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-05-02 09:36:55 -04:00
Winlin
d8696434cb
Proxy: Refine logger and environment APIs. v7.0.146 (#4670)
This PR refines the next-generation proxy internals and workspace
documentation:

  - Reworks internal/logger to expose clearer slog-style APIs:
      - Replaces Vf/Df/Wf/Ef with Info/Debug/Warn/Error.
      - Adds structured key/value log arguments.
      - Adds version to every log record.
      - Uses standard slog level labels (DEBUG, INFO, WARN, ERROR).
      - Keeps compatibility for existing printf-style messages.
  - Renames proxy configuration abstractions:
      - Environment → ProxyEnvironment.
      - NewEnvironment → NewProxyEnvironment.
- Regenerates/renames the counterfeiter fake to FakeProxyEnvironment.
- Updates all proxy bootstrap, load balancer, protocol, signal, debug,
and utility call sites for the new logger and
    environment APIs.
  - Consolidates proxy codebase navigation:
      - Deletes docs/proxy/proxy-files.md.
- Moves the useful file/module map details into
.openclaw/memory/srs-codebase-map.md.
- Replaces agent instruction symlinks with explicit workspace
instruction files for Claude, Codex, and Kiro.
  - Updates OpenClaw tool notes with Codex commit-prefix guidance.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:18:45 -04:00
Winlin
30fc7775a5
Proxy: Modernize internal packages on stdlib and add unit tests. v7.0.145 (#4667)
Modernizes several `internal/*` packages under the Go proxy, replaces
third-party forks with standard-library primitives, and brings the
test suite from near-zero to high coverage across the touched packages.

Package changes

- **`internal/errors`** — Rewrites the `pkg/errors` fork as a thin
wrapper
  over stdlib `errors`. A single `withStack` struct captures stack
  traces via `runtime.Callers`; `fmt.Errorf("%w", ...)` handles all
  message wrapping. Restores `errors.Is`/`As`/`Unwrap` chain traversal
  (silently broken in the fork) and deletes ~190 lines of stack/frame
  formatting. `Is`, `As`, `Unwrap`, and `Join` are re-exported so
  callers need a single import.
- **`internal/logger`** — Swaps stdlib `log.Logger` for `log/slog` JSON
  handlers with UTC timestamps and custom level labels (`verb`, `debug`,
  `warn`, `error`). Hides `withContextID` (no external callers).
- **`internal/sync`** — Converts `Map[K, V]` from a concrete struct to
  an interface with a `NewMap` constructor for testability.
- **`internal/signal`** — Adds `signalNotify` / `osExit` indirections so
  `InstallSignals` and `InstallForceQuit` can be exercised without real
  OS signals or process termination.
- **`internal/utils`** — Drops deprecated `io/ioutil` and the stdlib
  `errors` alias (the internal `errors` package re-exports what's
  needed).
- **`internal/version`** — No code changes; fully covered by new tests.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 07:25:48 -04:00
Winlin
cd11a6720f
Proxy: Harden internal/env tests and add counterfeiter fakes. v7.0.144 (#4665)
- **Refactor `internal/env` for testability.** Route every
`os`/filesystem
  call in `env.go` through swappable package-level function variables
(`getEnv`, `setEnv`, `lookupEnv`, `openFile`). Split `parseEnvFile` into
a
thin file-opening wrapper plus a pure `parseEnvReader(io.Reader)` so the
  parser can be tested directly without touching disk.
- **Hermetic tests, 96.9% coverage.** Rewrite `internal/env/env_test.go`
to
install in-memory fakes via `withFakeEnv` / `withFakeOpen` helpers that
  swap the package vars and restore them on `t.Cleanup`. Tests no longer
mutate real process env or write temp `.env` files, removing a source of
flakiness under parallel test execution. New cases cover
`NewEnvironment`,
`setEnvDefault`, `loadEnvFile` error paths, and edge cases in the
parser.
- **Counterfeiter-based fake generation.** Add `counterfeiter` as a Go
tool
dependency, a `//go:generate` directive for the `Environment` interface
  (`internal/env/gen.go`), and commit the generated
  `internal/env/envfakes/fake_environment.go` so downstream packages can
test against a spec-faithful fake instead of hand-rolling stubs. Expose
  the step as `make generate`.
- **Tooling.** `scripts/proxy-utest.sh` gains a `--coverage` / `-c` flag
  that runs `go test -coverprofile=...` across `./cmd/...` and
  `./internal/...` and prints per-function coverage via `go tool cover
  -func`. The `srs-develop` skill doc is updated to include the
  regenerate-fakes step and the new coverage flag.
- **Go version.** Bump `go.mod` to Go 1.25 (required for the `go tool`
  directive used to pin the counterfeiter CLI as a tool dep).

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 20:33:07 -04:00
Winlin
460412c4b5
Move build output to bin/, replace godotenv with custom .env parser, and update docs. v7.0.143 (#4661)
- Move build output from `./srs-proxy` to `bin/srs-proxy` following Go
project conventions, updating Makefile, .gitignore, and all
documentation references
- Replace third-party `godotenv` dependency with a custom `.env` parser
that supports comments, `export` prefix, quoted values, escape
sequences, and inline comments — with full unit tests
- Remove `ignore-worklog.md` and update `README.md` with skill-based AI
prompts
- Bump copyright year from 2025 to 2026 across all source files

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:26:33 -04:00
Winlin
7c17c93b70
Refactor bootstrap for multi-server support and add srs-develop skill. v7.0.142 (#4657)
Summary
- Extract proxy bootstrap implementation from bootstrap.go into
internal/bootstrap/proxy.go, keeping only the Bootstrap interface in the
shared file. This prepares for origin/edge servers
  to have their own bootstrap implementations.
- Rename NewBootstrap() → NewProxyBootstrap() to follow the explicit
factory naming convention.
- Rebrand signature from SRSProxy to SRSX and update logger context key
accordingly.
- Add srs-develop skill with task router, module routing workflow, proxy
unit test script, and RTMP E2E test script.
- Remove st-develop skill (superseded by srs-develop).
- Add srs-support eval #21 for HLS AnnexB decode error scenario.
Test plan
- go build ./cmd/proxy/... compiles successfully
  - go test ./cmd/... ./internal/... passes
- E2E RTMP proxy test (proxy-e2e-test.sh) passes
  - Verify proxy starts and logs SRSX-Proxy/<version> started

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 08:28:00 -04:00
Winlin
5f47cee19c
OpenClaw: Improve SRS support skill with docs integration, troubleshooting, and workspace updates (#4655)
Enhance the srs-support skill with doc-based knowledge layers, a full
troubleshooting section, and new eval cases. Update workspace config
files with model auth notes, voice dictation dictionary, and gitignore
patterns.

srs-support skill:
- Reframe skill scope: operators and users, not developers
- Add Layer 2 doc file mapping (25+ topic-to-doc-file entries) so the
  skill loads relevant doc files instead of jumping to source code
- Add Step 4 troubleshooting section covering WebRTC candidate issues,
  HLS latency tuning, stream-not-found diagnostics, reverse proxy
  problems, VLC buffering trap, and firewall port reference
- Add Oryx out-of-scope policy (planned but not available yet)
- Add 6 new eval cases (ids 15-20) for troubleshooting scenarios
- Fix unicode arrows in evals for cross-platform compatibility

Workspace updates:
- TOOLS.md: Add model auth refresh instructions and git commit workflow
- USER.md: Add voice dictation dictionary for speech-to-text corrections
- srs-overview.md: Replace ASCII diagram with Mermaid, expand browser
  publisher description for mobile WHIP support
- .claude/settings.local.json: Add read-only shell command permissions
- .gitignore: Add workspace pattern exclusions

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 07:11:24 -04:00
Winlin
8a53cb59f1
OpenClaw: Restructure workspace with symlinks, add codebase map, and rewrite AI docs. v7.0.141 (#4654)
Restructure the OpenClaw workspace so all SRS project directories are
accessible via symlinks from `.openclaw/`, eliminating the need for
parent traversal or absolute paths. All AI tools (OpenClaw, Claude Code,
Codex, Kiro) now see the same relative paths from the workspace root.

**Workspace restructuring**
- Add symlinks in `.openclaw/` for `trunk/`, `cmd/`, `internal/`,
`cmake/`, `docs/`, `objs/`, and a self-referential `.openclaw` link
- Add root-level `memory` symlink pointing to `.openclaw/memory`
- Simplify `TOOLS.md` working directory rules: everything is relative
from CWD
- Update `.gitignore` patterns for `personal*`, `support*`,
`srs-consults*` directories

**New codebase map (`memory/srs-codebase-map.md`)**
- Comprehensive map of the entire SRS codebase: C++ media server modules
(`core/`, `kernel/`, `protocol/`, `app/`), State Threads, Go next-gen
server (`cmd/` + `internal/`), documentation, and testing structure
- Enables AI to reason about which files are relevant to a question
instead of blind grepping
- Added "Codebase map first" rule to `MEMORY.md`: always load the map
before searching code

**Skill updates**
The `srs-support` has been reorganized into a three-phase workflow
consisting of Setup, Load Knowledge, and Answer by Topic. It now
features a tiered approach to knowledge integration, with the codebase
map being incorporated as the third layer.
- `st-develop`: Simplified setup, added codebase map reference
For both skills, the dynamic resolution logic for `SRS_ROOT` has been
eliminated. Now, all paths are relative.

**Documentation rewrite (`getting-started-ai.md`)**
- Replaced Augment Code / GitHub Copilot / PR review content with
current AI tooling: SRS Robot (Telegram/Discord), Claude Code, Codex,
Kiro, and OpenClaw
- Added sections on skills and the knowledge base philosophy

**Cleanup**
- Removed `docs/ideas.md`, `docs/youtube/` transcripts, and
`proxy/README.md`
- Removed "Ideas Capture" and "YouTube Channel Content" sections from
`MEMORY.md`
- Fixed origin cluster doc build command (`cd srs && make`)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 08:08:18 -04:00
winlin
ada9396e48 OpenClaw: Rename openclaw/ to .openclaw/ and update all symlinks and paths
- Rename workspace directory from openclaw/ to .openclaw/ (hidden)
- Update all symlinks in .claude/, .codex/, .kiro/ to point to ../.openclaw/
- Add memory symlinks for .claude/, .codex/, .kiro/
- Replace .codex/CODEX.md regular file with symlink to AGENTS.md
- Remove .codex/AGENTS.md symlink (replaced by CODEX.md symlink)
- Update internal paths in MEMORY.md, TOOLS.md
- Remove kb-review and srs-learn skills
- Update srs-support and st-develop skills: unified SRS_ROOT resolution, relative knowledge base paths
2026-03-22 11:14:24 -04:00
winlin
c741943a50 Rename openclaw workspace name. 2026-03-22 10:38:53 -04:00
Winlin
f48b2b31d9
OpenClaw: Unify AI agent configs with shared persona symlinks (#4653)
Replace vendor-specific config (.augment-guidelines, .augmentignore) with
a unified approach: .claude/, .codex/, and .kiro/ directories all symlink
to the canonical persona files in openclaw/ (SOUL.md, USER.md, MEMORY.md,
IDENTITY.md, TOOLS.md, AGENTS.md).

All artificial intelligence programming entities, including Claude Code, Codex, 
and Kiro, possess commonality. the same identity, memory, and conventions 
without file duplication.

- Remove .augment-guidelines and .augmentignore (Augment AI)
- Add .claude/ with settings.local.json hook to auto-load persona files
- Add .codex/ with config.toml and CODEX.md instruction entrypoint
- Rename .agents/skills to .codex/skills
- Add .kiro/steering/ with persona symlinks
- Document ACP working directory convention in TOOLS.md
- Update openclaw/.gitignore for .pi and extensions directories

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:37:09 -04:00
Winlin
ebf8b712c9 Proxy: restructure repo as Go project with proxy as first module (#4652)
Reorganize the SRS (Simple Realtime Server) repository to
follow a conventional Go project structure, setting the stage for a
progressive transition from a C++ project to a Go project. The proxy,
which was once contained within its own `proxy/` subdirectory, will now
be converted into the initial Go module located at the root of the
repository, serving as a template for subsequent Go modules.

- **Go module at repo root:** `go.mod` moved to repo root, module
renamed from `proxy` to `srsx`. The repo is now a proper Go project with
`cmd/` and `internal/` at the top level.
- **Elevation of Proxy Code:** Move the proxy code from
`proxy/cmd/proxy-go/` to `cmd/proxy/`, and from `proxy/internal/` to
`internal/`. The proxy serves as the inaugural application; subsequent
modules (for instance, `cmd/origin`) will mimic this arrangement.
- **Documentation Restructured:** Transfer the documentation from
`proxy/docs/` to `docs/proxy/`, revise the main README to endorse
OpenClaw as the preferred AI tool, and update `proxy/README.md` to point
to the new documentation locations.
- **Build and config:** `Makefile` moved to root, `PROXY_STATIC_FILES`
default path corrected for the new layout, `.gitignore` consolidated.
- **Cleanup:** removed standalone `proxy/LICENSE` (repo-level license
applies), all internal imports updated to `srsx/internal/...`.
- **OpenClaw workspace:** added community bot info, git workflow
conventions, and support group behavior guidance.

This restructuring was performed by OpenClaw orchestrating Claude Code
and Codex via ACP.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-03-22 08:11:28 -04:00
Winlin
aa3da620dc
OpenClaw: Improve srs-support skill with evals, latency corrections, and knowledge base refinements (#4651)
Rewrite srs-support SKILL.md with selective knowledge loading and structured
answering-by-topic sections. Add 15 eval test cases covering protocols, codecs,
scaling, comparisons, deployment, and access control.                       
                          
Correct latency numbers in srs-overview.md: HLS is 10-30s in practice (not  
3-5s), add concrete ranges for SRT (~500ms-1s), WebRTC (~50-400ms), and     
HTTP-FLV (~1-3s). Add VLC player-side buffering warnings throughout.        
                          
Expand knowledge base entries: Security section now covers referer, IP      
allow/deny, and HTTP callback auth (no built-in user management). HTTP Callback
corrected to v0.9. Edge Cluster clarified as viewer scaling with new version
planned. Windows section explains the ST + SRT C++ exception handling blocker. 
                          
Add SRS Community Bot section to MEMORY.md with Telegram/Discord links.     
Update AGENTS.md to answer SRS support questions directly when mentioned. 

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 15:28:31 -04:00
Winlin
024342910d
OpenClaw: add and refine ST knowledge-base and learning/review skills (#4643)
- Add a comprehensive ST knowledge base document:
- openclaw/memory/srs-coroutines.md
- Add ST-focused developer skill:
- openclaw/skills/st-develop/SKILL.md
- openclaw/skills/st-develop/scripts/verify.sh
- Add KB workflow skills that support ST documentation quality and
learning:
- openclaw/skills/kb-review/SKILL.md
- openclaw/skills/srs-learn/SKILL.md
- Update openclaw/skills/srs-support/SKILL.md to use dynamic SRS_ROOT
path resolution, improving portability for KB/source
 loading.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-03-05 09:57:08 -05:00
winlin
4c39d2b8e8 Move proxy from ossrs/proxy repo to proxy directory
Move the SRS proxy server code from the standalone repository
https://github.com/ossrs/proxy into the proxy/ directory of the
main SRS repo. Also update build instructions in origin-cluster.md.
2026-02-15 09:48:27 -05:00
Winlin
a86cd7cdfa
OpenClaw: Create knowledge base for AI robot (#4636)
See https://clawhub.ai/winlinvip/srs-support
2026-02-14 08:42:16 -05:00
hyunwoo jo
6e2392f366
HLS/DASH: Fix dispose() to cleanup files after unpublish (#4618)
# HLS/DASH: Fix dispose() to cleanup files after unpublish

## Summary
Fixes a bug where HLS/DASH files are not deleted after the configured
`hls_dispose`/`dash_dispose` timeout.

## Problem
When a stream is unpublished:
1. `on_unpublish()` is called and sets `enabled_ = false`
2. After the dispose timeout, `cycle()` calls `dispose()`
3. `dispose()` immediately returns due to `if (!enabled_)` check at line
2722 (HLS) and line 891 (DASH)
4. `controller_->dispose()` is never called
5. Files remain on disk indefinitely

**Observed behavior**:
- Stream stopped at 11:32:42
- `dispose()` called at 11:33:14 (after 30s timeout)
- Log shows "hls cycle to dispose hls" but no "gracefully dispose hls"
message
- Files remain on disk

## Root Cause
Commit 550760f2d introduced an early return in `dispose()` when
`!enabled_`, which prevents file cleanup after `on_unpublish()` has
already been called and set `enabled_` to false.

## Solution
Reorder the logic in `dispose()` to:
1. Check if dispose is enabled (hls_dispose/dash_dispose > 0) first
2. Call `on_unpublish()` only if `enabled_` is still true (prevents
duplicate calls)
3. Always call `controller_->dispose()` to cleanup files when dispose
timeout occurs

This ensures files are properly cleaned up while still preventing
duplicate `on_unpublish()` calls.

## Changes Made
- **trunk/src/app/srs_app_hls.cpp** (lines 2718-2734): Reordered
dispose() logic
- **trunk/src/app/srs_app_dash.cpp** (lines 887-902): Reordered
dispose() logic
- **trunk/doc/CHANGELOG.md**: Added v7.0.137 entry

## Testing Recommendation

To verify the fix:

1. Start RTMP stream to `/live/test`:
   ```bash
   ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test
   ```

2. Wait for HLS segments to be created:
   ```bash
   ls -la /path/to/hls/live/test/
   ```

3. Stop the stream (Ctrl+C)

4. Wait for `hls_dispose` timeout (default 120s, or 30s with your
config):
   ```bash
# Watch logs for "hls cycle to dispose hls" and "gracefully dispose hls"
   tail -f srs.log
   ```

5. Verify files are deleted:
   ```bash
   ls -la /path/to/hls/live/test/
   # Should be empty or directory removed
   ```

**Expected results**:
- Before fix: Files remain on disk
- After fix: Files are deleted, logs show "gracefully dispose hls"

## Impact
- **Risk**: Low - minimal logic change, only reordering of checks
- **Breaking changes**: None
- **Performance**: No impact
- **Compatibility**: Fixes existing bug, improves expected behavior

## Checklist
- [x] Code follows project style
- [x] Both HLS and DASH are fixed
- [x] CHANGELOG updated
- [x] Tested locally (recommended before merge)
- [x] No breaking changes

## Related Issues
- Regression introduced in: 550760f2d
- Related to: #865 (hls_dispose feature)

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2026-02-03 19:36:11 -05:00
winlin
93c5d7225b Update for SRSX with proxy server. 2025-12-13 08:24:40 -05:00
Jacob Su
d3fce1c106
HLS: Fix audio-only fMP4 playback skipping. v7.0.136 (#4602) (#4602)
based on @HeeJoon-Kim's patch, try to fix #4594 

Fix audio-only HLS fMP4 streams causing players to skip segments.

The bug was in segment_close() which always used video_dts_ (0 for
audio-only) to calculate the final sample duration, causing unsigned
integer overflow and corrupted m4s files.

The fix passes max(audio_dts_, video_dts_) from the controller to
segment_close(), ensuring correct duration calculation for both
audio-only and video streams.

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-12-06 22:29:12 -05:00
Jacob Su
6a86d9e805
DVR: Fix HEVC mp4 recording error. v7.0.135 (#4604) (#4604)
When recording HEVC streams to MP4, DVR fails with error "doesn't
support
hvcC change" (ERROR_MP4_HVCC_CHANGE).

The root cause is in video_avc_demux(): the SrsVideoFrame object is
reused
across frames, and its initialize() method does not reset
avc_packet_type.
When a sequence header is processed, avc_packet_type is set to 0
(SrsVideoAvcFrameTraitSequenceHeader). When the next video info frame
arrives (which only appears in HEVC streams), the function returns early
without assigning video->avc_packet_type, so it retains the value 0 from
the previous sequence header frame.

When DVR processes this video info frame, it checks avc_packet_type and
incorrectly identifies it as a sequence header. Since the real HEVC
sequence
header was already recorded, DVR returns the "hvcC change" error.

The fix assigns video->avc_packet_type = packet_type before returning
early for VideoInfoFrame. After the fix, avc_packet_type is correctly
set
to the actual packet type (1 or 3 for coded frames), so DVR correctly
identifies it as NOT a sequence header.

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-12-06 19:49:13 -05:00
OSSRS-AI
1560077cbc
SRT: Fix peer_idle_timeout not applied to publishers and players. v7.0.134 (#4600) (#4606) 2025-12-06 17:26:49 -05:00
OSSRS-AI
a83c9026f9
SRT: Enable tlpktdrop by default to prevent 100% CPU usage. v7.0.133 (#4587) (#4601) 2025-12-04 09:47:01 -05:00
winlin
e970ad26fd Update README for 6.0 release 0. 2025-12-03 10:41:42 -05:00
OSSRS-AI
00494d5f87
AI: WebRTC: Fix audio-only WHIP publish without SSRC. v7.0.132 (#4570) (#4599) 2025-12-03 09:00:16 -05:00
OSSRS-AI
f47e3ab458
SRT: Support default_mode config for short streamid format. v7.0.131 (#4598) 2025-11-30 16:26:04 -05:00
OSSRS-AI
18c30dc07b
AI: SRT: Fix player not exiting when publisher disconnects. v7.0.130 (#4591) (#4596)
When SRT publisher disconnects, player hangs indefinitely instead of
exiting after the configured peer_idle_timeout. This is because the
consumer wait() never checks if the publisher is still connected.

After fix, player waits for peer_idle_timeout (default 10s) then exits
gracefully when no packets arrive and publisher has disconnected.
2025-11-27 19:32:24 -05:00
artem-smorodin-dacast
4101900daf
RTMP: Ignore FMLE start packet after flash publish. v7.0.129 (#4588)
We have discovered that some IP cameras send two publish packets in a
row.

The first packet is flash publish `publish('xxx')`
The second packet is FMLE publish `FCPublish('xxx|@setDataFrame()`

It seems that this is not processed correctly on the SRS side. In fact,
the stream is simply deinitialized, and republish is simply not
supported in this case.

As a fix, I suggest simply ignoring the FMLE publish packet after the
flash publish.

<img width="720" alt="screen"
src="https://github.com/user-attachments/assets/2db806ab-71b9-4e7b-bcf9-c16ea12df671"
/>
2025-11-27 09:28:46 -05:00
OSSRS-AI
e59b30301a
AI: API: Change pagination default count to 10, minimum 1. v7.0.128 (#4584) 2025-11-18 12:12:16 -05:00
OSSRS-AI
a3a2fa5ceb
AI: Fix race condition causing immediate deletion of new sources. v7.0.127 (#4449) (#4576)
**Problem**: Newly created sources (RTMP/SRT/RTC/RTSP) were being
immediately marked as "dead" and deleted by the cleanup timer before
publishers could connect, causing "new live source, dead=1" errors.

**Root Cause**: All source constructors initialized `stream_die_at_ =
0`, causing `stream_is_dead()` to return `true` immediately since
current time was always greater than `0 + 3 seconds`.

**Solution**: Changed all four source constructors to initialize
`stream_die_at_ = srs_time_now_cached()`, giving newly created sources a
proper 3-second grace period before cleanup.
2025-11-13 21:24:07 -05:00
OSSRS-AI
6e93dd73b5
AI: WebRTC: Support optional msid attribute per RFC 8830. v7.0.126 (#4570) (#4572)
Fix issue #4570 by supporting optional `msid` attribute in WebRTC SDP
negotiation, enabling compatibility with libdatachannel and other
clients that don't include msid information.

SRS failed to negotiate WebRTC connections from libdatachannel clients
because:
- libdatachannel SDP lacks `a=ssrc:XX msid:stream_id track_id`
attributes
- SRS required msid information to create track descriptions
- According to RFC 8830, the msid attribute and its appdata (track_id)
are **optional**

If diligently look at the SDP generated by libdatachannel:

```
a=ssrc:42 cname:video-send
a=ssrc:43 cname:audio-send
```

It's deliberately missing the `a=ssrc:XX msid:stream_id track_id` line,
comparing that with this one:

```
a=ssrc:42 cname:video-send
a=ssrc:42 msid:stream_id video_track_id
a=ssrc:43 cname:audio-send  
a=ssrc:43 msid:stream_id audio_track_id
```

In such a situation, to keep compatible with libdatachannel, if no msid
line in sdp, SRS comprehensively and consistently uses:

* app/stream as stream_id, such as live/livestream
* type=video|audio, cname, and ssrc as track_id, such as
track-video-video-send-43
2025-11-11 10:22:31 -05:00
OSSRS-AI
3f2539d8fb
AI: SRT: Stop TS parsing in SrsSrtFormat after codec detection. v7.0.125 (#4569) (#4571)
Fix log flooding issue when processing SRT streams containing SCTE-35
PIDs or other unrecognized stream types.

The `SrsSrtFormat::on_srt_packet()` method continuously parses TS
packets throughout the entire stream lifetime. The TS parser logs
warnings for every unrecognized stream type (like SCTE-35) in the PMT,
causing log flooding.

However, `SrsFormat` is only used to detect audio/video codec
information. Once both codecs are detected, there's no need to continue
parsing TS packets.

Note: This fix mitigates the problem - there will still be some warning
logs during the initial codec detection phase (typically 5-10 seconds),
but the continuous log flooding after codec detection is completely
eliminated.
2025-11-11 00:24:01 -05:00
Winlin
e509d079a2 Add codecs supprted in README 2025-11-09 12:17:31 -05:00
OSSRS-AI
bfb91f9b82
AI: WebRTC: Support G.711 (PCMU/PCMA) audio codec for WebRTC. v7.0.124 (#4075) (#4568)
This PR adds G.711 (PCMU/PCMA) audio codec support for WebRTC in SRS,
enabling relay-only streaming of G.711 audio between WebRTC clients via
WHIP/WHEP. G.711 is a widely-used, royalty-free audio codec with
excellent compatibility across VoIP systems, IP cameras, and legacy
telephony equipment.

Fixes #4075

Many IP cameras, VoIP systems, and IoT devices use G.711 (PCMU/PCMA) as
their default audio codec. Previously, SRS only supported Opus for
WebRTC audio, requiring transcoding or rejecting G.711 streams entirely.
This PR enables direct relay of G.711 audio streams in WebRTC, similar
to how VP9/AV1 video codecs are supported.

Enhanced WHIP/WHEP players with URL-based codec selection:
```
# Audio codec only
http://localhost:8080/players/whip.html?acodec=pcmu
http://localhost:8080/players/whip.html?acodec=pcma

# Video + audio codecs
http://localhost:8080/players/whip.html?vcodec=vp9&acodec=pcmu
http://localhost:8080/players/whep.html?vcodec=h264&acodec=pcma

# Backward compatible (codec = vcodec)
http://localhost:8080/players/whip.html?codec=vp9
```

Testing

```bash
# Build and run unit tests
cd trunk
make utest -j && ./objs/srs_utest

# Test with WHIP player
# 1. Start SRS server
./objs/srs -c conf/rtc.conf

# 2. Open WHIP publisher with PCMU audio
http://localhost:8080/players/whip.html?acodec=pcmu

# 3. Open WHEP player to receive stream
http://localhost:8080/players/whep.html
```

## Related Issues

- Fixes #4075 - WebRTC G.711A Audio Codec Support
- Related to #4548 - VP9 codec support (similar relay-only pattern)
2025-11-09 12:08:03 -05:00
OSSRS-AI
7fcd406a63
AI: WebRTC: Support VP9 codec for WebRTC-to-WebRTC streaming. v7.0.123 (#4548) (#4565)
VP9 is a similar codec to HEVC, but for WebRTC, VP9 works better than
AVC/HEVC in some special cases. However, SRS only support VP9 for
WebRTC, doesn't support converting it to RTMP, for RTMP only support
AVC/HEVC/AV1 and SRS cannot support transcoding.

Usage:
* Publish with VP9:
[http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream&codec=vp9](http://localhost:8080/players/whip.html?codec=vp9)
* Play with VP9:
[http://localhost:1985/rtc/v1/whep/?app=live&stream=livestream&codec=vp9](http://localhost:8080/players/whep.html?codec=vp9)
2025-11-08 12:47:31 -05:00
OSSRS-AI
1a96abc880
AI: API: Add audio_frames and video_frames to HTTP API. v7.0.122 (#4559) (#4564)
This PR adds separate audio and video frame counting to the HTTP API
(`/api/v1/streams/`) for better stream observability. The API now
reports three frame fields:
- `frames` - Total frames (video + audio)
- `video_frames` - Video frames/packets only
- `audio_frames` - Audio frames/packets only

This enhancement provides better visibility into stream composition and
helps detect issues with CBR/VBR streams, audio/video sync problems, and
codec-specific behavior.

**Before:**
```json
{
  "streams": [
    {
      "frames": 0, // video frames.
    }
  ]
}
```

**After:**
```json
{
  "streams": [
    {
      "frames": 6912, // video frames.
      "audio_frames": 5678, // audio frames.
      "video_frames": 1234, // video frames.
    }
  ]
}
```

Frame Counting Strategy
- All protocols report frames every N frames to balance accuracy and
performance
- Frames are counted at the protocol-specific message/packet level:
  - RTMP: Counts RTMP messages (video/audio)
  - WebRTC: Counts RTP packets (video/audio)
  - SRT: Counts MPEG-TS messages (H.264/HEVC/AAC)
2025-11-07 22:32:26 -05:00
Winlin
f392f9a5a7
WHIP: Return detailed HTTP error responses with proper status codes. v7.0.121 (#4502) (#4562)
This commit addresses issue #4502 by implementing proper HTTP error
handling
for WHIP endpoints, allowing clients to receive detailed error
information
instead of empty responses.

Before this change:
- WHIP clients received "Empty reply from server" when publish failed
- No way to distinguish between different failure reasons

After this change:
- WHIP clients receive proper HTTP status codes (400/401/409/500)
- Error responses include error code and description
- Clients can distinguish between SDP errors, stream busy, auth
failures, etc.

If success:

```
< HTTP/1.1 201 Created
< Content-Type: application/sdp
< Location: /rtc/v1/whip/?action=delete&token=77h5570j1&app=live&stream=livestream&session=x209e499:TKxW
< Content-Length: 1376
< Server: SRS/7.0.120(Kai)
< 
v=0
......
```

If request without SDP:

```
curl 'http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream' -v
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
< Content-Length: 13
< Server: SRS/7.0.120(Kai)
< 
5043: RtcInvalidSdp
```

If request with corrupt SDP:

```
curl 'http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream' --data-raw $'invalidsdp' -v
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
< Content-Length: 18
< Server: SRS/7.0.120(Kai)
< 
5012: RtcSdpDecode
```

If request with insufficient SDP:

```
curl 'http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream' --data-raw $'v=0' -v
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
< Content-Length: 21
< Server: SRS/7.0.120(Kai)
< 
5018: RtcSdpNegotiate
```

If publish to a exists stream:

```
< HTTP/1.1 409 Conflict
< Content-Type: text/plain; charset=utf-8
< Content-Length: 16
< Server: SRS/7.0.120(Kai)
< 
1028: StreamBusy
```

If HTTP hooks or security verify failed:

```
< HTTP/1.1 401 Unauthorized
< Content-Type: text/plain; charset=utf-8
< Content-Length: 16
< Server: SRS/7.0.120(Kai)
< 
1102: SystemAuth
```

Other errors, for exmaple, RTC disabled:

```
< HTTP/1.1 500 Internal Server Error
< Content-Type: text/plain; charset=utf-8
< Content-Length: 17
< Server: SRS/7.0.120(Kai)
< 
5021: RtcDisabled
```

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-11-07 21:05:41 -05:00
OSSRS-AI
99970d6ba0 AI: HLS: Support query string in hls_key_url for JWT tokens. v7.0.120 (#4426) 2025-11-06 23:00:19 -05:00
OSSRS-AI
0c26a3c309 AI: RTC: Support keep_original_ssrc to preserve SSRC and timestamps. v7.0.119 (#3850) 2025-11-06 21:45:50 -05:00
OSSRS-AI
dc8b2a804d AI: WebRTC: Report video/audio codec info and frame stats in HTTP API. v7.0.118 (#4554) 2025-11-05 21:56:16 -05:00
OSSRS-AI
eb9fca888d AI: SRT: Report video/audio codec info and frame stats in HTTP API. v7.0.117 (#4554) 2025-11-04 10:41:11 -05:00
Chunbo
f90a96a03d
Fix a typo in README.md (#4558) 2025-11-03 22:31:24 -05:00
OSSRS-AI
82d57e17ab AI: Refine bug caused flaky test failure. 2025-11-03 21:01:35 -05:00
winlin
7439a91daf Update README.md with v6.0-b3 release. 2025-11-03 21:01:28 -05:00
Laurentiu
1f4c05bdd5
Fill missing defs for H264/AVC video levels. v7.0.116 (#4556)
Fill missing H264/AVC video levels (4.2, 5.2, 6, 6.1, 6.2). 
Partial Fix #4555

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-11-03 10:31:13 -05:00
vivisoymilkhappy
57c74d1cdb
Add ignore configuration for cursor. v7.0.115 (#4547)
Cursor ignored.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: ZhangWei <zhangwei@jlsoft.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-10-31 19:11:51 -04:00