{"_id":"@agora-build/stream-to-agora","_rev":"5-d1c1da0d0be66984c8cbbed8e3f3ea85","name":"@agora-build/stream-to-agora","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"@agora-build/stream-to-agora","version":"0.1.0","keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","_id":"@agora-build/stream-to-agora@0.1.0","maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"homepage":"https://github.com/Agora-Build/stream-to-agora#readme","bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"os":["linux"],"bin":{"stream-to-agora":"bin/stream-to-agora"},"cpu":["x64"],"dist":{"shasum":"e298d6145178d4c0c1b8b6e7ab0956c00176266d","tarball":"https://registry.npmjs.org/@agora-build/stream-to-agora/-/stream-to-agora-0.1.0.tgz","fileCount":4,"integrity":"sha512-WZ72Xi3uID3d9WAEXlRTsB9I3J8ujH+9zu5jbeALGgUd2YQBIcm4kHRiYaIFpmwKUkFKjRGNmxtSkXqvRxbXDQ==","signatures":[{"sig":"MEUCIQDYeFNOuzdBEi4NrLSsb3kDYRdP4FEU9it/mbb31vQmcQIgdve9515gre7O8INj0XPE4uKewkqhmbPCA4X0uYxKzgI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":8742},"gitHead":"976e1aca0c6b04a92f0dc98840a1b663a2844043","scripts":{"postinstall":"node install.js"},"_npmUser":{"name":"agora.build","email":"brent@agora.io"},"repository":{"url":"git+https://github.com/Agora-Build/stream-to-agora.git","type":"git"},"_npmVersion":"10.8.2","description":"Stream local files (and later https/rtmp/rtsp) to an Agora RTC channel.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stream-to-agora_0.1.0_1778640818070_0.12829776158936768","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@agora-build/stream-to-agora","version":"0.2.0","keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","_id":"@agora-build/stream-to-agora@0.2.0","maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"homepage":"https://github.com/Agora-Build/stream-to-agora#readme","bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"os":["linux"],"bin":{"stream-to-agora":"bin/stream-to-agora"},"cpu":["x64"],"dist":{"shasum":"6bf19583ffd8075aadc21cffec815212ebe3c5cc","tarball":"https://registry.npmjs.org/@agora-build/stream-to-agora/-/stream-to-agora-0.2.0.tgz","fileCount":4,"integrity":"sha512-CzyuvQ1+O/Rb49rDwIfaeaL53UirMO317c10C2R2Livk19bMSeTb90dfwggRMuJKjaq/TlVsCAdUKNU8yCXZOw==","signatures":[{"sig":"MEUCICol+qsVZw51wJqW8FE9Rdwelmfc6iWVzwzABAKqnqrXAiEA+RukZtGgw2PT/AwG8xyTu4LyGXUM+v8+mRtL6iA4PJM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9535},"gitHead":"c6e72aa8a64aa4075eadbc7ca33043ac71f270e4","scripts":{"postinstall":"node install.js"},"_npmUser":{"name":"agora.build","email":"brent@agora.io"},"repository":{"url":"git+https://github.com/Agora-Build/stream-to-agora.git","type":"git"},"_npmVersion":"10.8.2","description":"Stream local files (and later https/rtmp/rtsp) to an Agora RTC channel.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stream-to-agora_0.2.0_1778752577671_0.045234727258859575","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@agora-build/stream-to-agora","version":"0.2.1","keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","_id":"@agora-build/stream-to-agora@0.2.1","maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"homepage":"https://github.com/Agora-Build/stream-to-agora#readme","bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"os":["linux"],"bin":{"stream-to-agora":"bin/stream-to-agora"},"cpu":["x64"],"dist":{"shasum":"c4a70c6e78d519395c369285ef2b8ccc6a8a8066","tarball":"https://registry.npmjs.org/@agora-build/stream-to-agora/-/stream-to-agora-0.2.1.tgz","fileCount":4,"integrity":"sha512-JRy0Yn3WUih0p4bmlC1WrAT6wnSPEd+vGMznW0ChQa/rlx6vtH8v3v06dMfgYe+76KHFRL3SBOBHKq/fikpE5A==","signatures":[{"sig":"MEUCIHQTpj0S2BXr7f6apeU53Hx2/gxZA1NAYfArzV8kE0vdAiEArpbUCNDXsImXlDNScfk5GpmohXEx29RPcWiGLm1SWGg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9535},"gitHead":"13f37144a1bb6c0c04e6c5097d3aa21cb35138b4","scripts":{"postinstall":"node install.js"},"_npmUser":{"name":"agora.build","email":"brent@agora.io"},"repository":{"url":"git+https://github.com/Agora-Build/stream-to-agora.git","type":"git"},"_npmVersion":"10.8.2","description":"Stream local files (and later https/rtmp/rtsp) to an Agora RTC channel.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stream-to-agora_0.2.1_1778753082678_0.3385841055544192","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@agora-build/stream-to-agora","version":"0.2.2","keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","_id":"@agora-build/stream-to-agora@0.2.2","maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"homepage":"https://github.com/Agora-Build/stream-to-agora#readme","bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"os":["linux"],"bin":{"stream-to-agora":"bin/stream-to-agora"},"cpu":["x64"],"dist":{"shasum":"c6035c48644df7e48ac844af529f9dd0c719356d","tarball":"https://registry.npmjs.org/@agora-build/stream-to-agora/-/stream-to-agora-0.2.2.tgz","fileCount":4,"integrity":"sha512-oxEKozm1Zjx3CppLC/Gdv7JnLXWrYN6yW71/QskTt6TrUamXR3eOkjAi3zHD9OGkONPcerCCkH3PLyJY/NxvUg==","signatures":[{"sig":"MEUCIGCFpEmlPdMVqiseUVIu/lUoUNmeV2jaIDN9fYviy+oLAiEA39htYEGUeH9UlgHGBSh/PMN4K1XF3DKkRoJ5379sUqg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9533},"gitHead":"66c67b4d6aeb4e92bcbd3803d4be6d447de6b408","scripts":{"postinstall":"node install.js"},"_npmUser":{"name":"agora.build","email":"brent@agora.io"},"repository":{"url":"git+https://github.com/Agora-Build/stream-to-agora.git","type":"git"},"_npmVersion":"10.8.2","description":"Stream local files or http(s)/rtmp/rtsp URLs to an Agora RTC channel.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stream-to-agora_0.2.2_1779096073163_0.18362752872812593","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@agora-build/stream-to-agora","version":"0.4.0","description":"Stream local files or http(s)/rtmp/rtsp URLs to an Agora RTC channel.","bin":{"stream-to-agora":"bin/stream-to-agora"},"scripts":{"postinstall":"node install.js"},"repository":{"type":"git","url":"git+https://github.com/Agora-Build/stream-to-agora.git"},"keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"homepage":"https://github.com/Agora-Build/stream-to-agora#readme","os":["linux"],"cpu":["x64"],"gitHead":"2bff1dbb895aa45de5a2acb707a1797dd72c4209","_id":"@agora-build/stream-to-agora@0.4.0","_nodeVersion":"20.17.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-rWUyU0ft9b/nlMZ5C5k0QlAmYakbQUMX5Jhvyokl9TTkhMqSKN3w5aCwC/vMIuLsBLS94TK3JSvaLtGdDsi/sg==","shasum":"55ba9a3db804949080b572e01195025eea3ac8cc","tarball":"https://registry.npmjs.org/@agora-build/stream-to-agora/-/stream-to-agora-0.4.0.tgz","fileCount":4,"unpackedSize":13255,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAcFjoiHJh/A9ts0bEbnFGCDG1TFUDWAqnkfNtExQIAGAiEA74N+/VT2xtz8WqpQnAqdG23eyTJYIyObdTcDFXcuDMw="}]},"_npmUser":{"name":"agora.build","email":"brent@agora.io"},"directories":{},"maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/stream-to-agora_0.4.0_1779819731352_0.4981668906909389"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-13T02:53:37.974Z","modified":"2026-05-26T18:22:11.608Z","0.1.0":"2026-05-13T02:53:38.220Z","0.2.0":"2026-05-14T09:56:17.792Z","0.2.1":"2026-05-14T10:04:42.815Z","0.2.2":"2026-05-18T09:21:13.295Z","0.4.0":"2026-05-26T18:22:11.502Z"},"bugs":{"url":"https://github.com/Agora-Build/stream-to-agora/issues"},"author":{"name":"Agora Build","email":"build@agora.io"},"license":"MIT","homepage":"https://github.com/Agora-Build/stream-to-agora#readme","keywords":["agora","rtc","streaming","video","audio","ffmpeg"],"repository":{"type":"git","url":"git+https://github.com/Agora-Build/stream-to-agora.git"},"description":"Stream local files or http(s)/rtmp/rtsp URLs to an Agora RTC channel.","maintainers":[{"name":"agora.build","email":"brent@agora.io"}],"readme":"# @agora-build/stream-to-agora\n\nStream a local file or `http(s)://` / `rtmp://` / `rtsp://` URL to an [Agora](https://www.agora.io) RTC channel as a regular publisher. ffmpeg decodes/demuxes the source; codecs the SDK's encoded senders accept (H.264, H.265, VP8, VP9, AV1 video; AAC/HE-AAC/HE-AACv2, Opus, G.711 audio) pass through as-is, anything else is decoded to raw YUV/PCM and pushed via the raw senders — useful for load testing, demos, simulated participants, and pumping pre-recorded media into a live channel.\n\n## Features\n\n- **Local files** — any container/codec ffmpeg can read (`./demo.mp4`, `./loop.mkv`, …).\n- **Remote sources** — `http://`, `https://`, `rtmp://`, `rtsp://`.\n- **Encoded passthrough** — H.264/H.265/VP8/VP9/AV1 video and AAC/HE-AAC/HE-AACv2/Opus/G.711 audio are demuxed with `-c copy` (zero CPU on our side); the SDK gets the bitstream as-is. Mode is per-input all-or-nothing: both streams must be passthrough-eligible or the whole input falls back to Raw.\n- **Raw fallback** — anything else (MP3, MPEG-2, AC-3, …) is decoded by ffmpeg to yuv420p + s16le PCM and pushed via the raw senders.\n- **Selective publish** — `--audio-only` / `--video-only`.\n- **Hybrid reconnect** — `http(s)` uses ffmpeg's built-in `-reconnect` flags; RTMP/RTSP respawn the ffmpeg subprocess, bounded by `--reconnect-attempts`.\n- **Token renewal** — `--token-renew-cmd <shell-cmd>` runs your token-minter on `TokenWillExpire` and rotates the token without dropping the channel.\n- **`--loop` forever** — steady-state load testing from a single short file.\n- **ffmpeg passthrough flags** — `--http-header K:V` (repeatable), `--user-agent`, `--rtsp-transport tcp|udp|http`.\n\n### Encoded passthrough caveats\n\n- Subscriber decode support is codec-dependent: H.264/VP8 every WebRTC client; H.265 Safari + hardware-accelerated Chrome; VP9/AV1 Chrome/Edge/Firefox. Agora's native SDK subscriber decodes all.\n- Passthrough cannot synthesise keyframes to answer `onIntraRequestReceived`; mid-join black at a browser subscriber is bounded by the source's keyframe interval (sub-second for keyframe-dense inputs). Use `--mode raw` if you need the SDK's own encoder to answer subscriber PLIs on demand (costs a re-encode generation; see Modes below).\n- **AV1 encoded passthrough is partial.** Agora's SDK marks `VIDEO_CODEC_AV1` as `@technical preview`. H.264/H.265/VP8/VP9 deliver cleanly end-to-end, but AV1 with a hierarchical-B encoder (SVT-AV1's default) loses ~60–70% of frames at the receiver. Use `--mode raw` for reliable AV1, or pre-encode source with `-svtav1-params 'pred-struct=1'` (low-delay, no `show_existing_frame`). Will be reliable once Agora promotes AV1 out of preview.\n\n## Install\n\n```bash\nnpm install -g @agora-build/stream-to-agora\n```\n\nOr via shell script:\n\n```bash\ncurl -fsSL https://dl.agora.build/stream-to-agora/install.sh | bash\n```\n\nBoth download a prebuilt bundle for your platform — the binary plus the Agora SDK shared libraries it depends on. The binary's rpath finds the libs at runtime, so there's no `LD_LIBRARY_PATH` / `DYLD_LIBRARY_PATH` setup.\n\n> **v0.4.0 currently ships Linux x86_64 only.** Linux aarch64 and macOS releases were on v0.3.x against the previous SDK; the SDK upgrade in v0.4.0 (which delivers the VP9/AV1 packetizer fix) is currently only published for Linux x86_64. aarch64 + macOS releases will return once Agora publishes the matching SDK builds for those targets.\n\n## Usage\n\n```bash\nstream-to-agora <INPUT> --app-id <ID> --channel <NAME> --rtc-user-id <UID> --token <TOKEN> [OPTIONS]\n```\n\n```bash\n# Local file\nstream-to-agora ./demo.mp4 \\\n  --app-id      $AGORA_APP_ID \\\n  --channel     demo \\\n  --rtc-user-id 42 \\\n  --token       \"$RTC_TOKEN\"\n\n# String account (same \"s/\" convention as `atem serv rtc`)\nstream-to-agora ./demo.mp4 --app-id ... --channel demo --rtc-user-id s/alice --token \"$RTC_TOKEN\"\n\n# Loop forever — steady-state load testing\nstream-to-agora ./loop.mp4 --app-id ... --channel demo --rtc-user-id 42 --token \"$RTC_TOKEN\" --loop\n\n# Audio only / video only\nstream-to-agora ./demo.mp4 --app-id ... --channel demo --rtc-user-id 42 --token \"$RTC_TOKEN\" --audio-only\n\n# Remote source (later release — ffmpeg already handles these, so the arg shape is unchanged)\nstream-to-agora rtmp://live.example.com/app/key --app-id ... --channel demo --rtc-user-id 42 --token \"$RTC_TOKEN\"\n```\n\n### Options\n\n| Flag | Description |\n|---|---|\n| `--app-id <ID>` | Agora App ID. Falls back to `AGORA_APP_ID` env var. |\n| `--channel <NAME>` | RTC channel to join. |\n| `--rtc-user-id <UID>` | RTC user. All-digit → int uid; non-digit → string account; `s/` prefix forces string mode. |\n| `--token <TOKEN>` | Pre-minted RTC token (required). |\n| `--mode <auto\\|raw\\|encoded>` | Sender path (default `auto`). See **Modes** below. |\n| `--hwaccel <auto\\|none\\|...>` | ffmpeg HW decode backend for Raw mode (default `auto`). See **Hardware acceleration**. |\n| `--loop` | Restart the input on EOF. |\n| `--audio-only` / `--video-only` | Push just one track. |\n| `--ffmpeg-path <PATH>` | ffmpeg binary (default: `ffmpeg` on `PATH`). |\n\n### Modes\n\n| `--mode` | Behaviour |\n|---|---|\n| `auto` (default) | Encoded passthrough when every stream's codec is passthrough-eligible, else Raw. |\n| `raw` | Force ffmpeg-decode → SDK-re-encode for every input. More CPU + one re-encode generation, but the SDK's internal encoder owns the bitstream — it answers subscriber keyframe requests (PLI) itself, so mid-join subscribers aren't stuck on black, and it works for any codec ffmpeg decodes, including VP9/AV1. Hardware-accelerated — see below. |\n| `encoded` | Force zero-CPU passthrough; errors at startup (naming the codec) if a stream can't pass through, instead of silently falling back. |\n\n### Hardware acceleration\n\nRaw mode is hardware-accelerated by default: ffmpeg decodes with\n`-hwaccel` and the SDK is asked to use its hardware video encoder.\n\n- `--hwaccel <auto|none|cuda|vaapi|qsv|videotoolbox>` (default `auto`).\n  At startup the tool runs a silent probe; with `auto` it tries a\n  platform candidate list and picks the first that works; a pinned\n  backend is probed too and falls back to software with a one-line\n  message if unavailable (no crash, no noise); `none` skips the probe.\n  You'll see one of `hardware decode: <backend>` or\n  `hardware decode unavailable — using software decode` on startup.\n- Applies only to Raw mode's video decode — `--mode encoded` decodes\n  nothing, so `--hwaccel` is a no-op there.\n- SDK hardware encode is best-effort: it falls back to software when the\n  platform build has no hardware encoder.\n\n### Tokens\n\nstream-to-agora **does not mint tokens** — token minting is a security-sensitive concern that belongs in your token service or [atem](https://github.com/Agora-Build/Atem). Supply a pre-minted token:\n\n```bash\nTOKEN=$(atem token rtc create --channel demo --rtc-user-id 42)\nstream-to-agora ./demo.mp4 --app-id $AGORA_APP_ID --channel demo --rtc-user-id 42 --token \"$TOKEN\"\n```\n\nTwo publishers on the same channel must use different uids (Agora kicks a duplicate uid). Same channel + different uids = fine.\n\n## Requirements\n\n- **ffmpeg** on `PATH` (or pass `--ffmpeg-path`). Used to decode the input into raw frames.\n- The project must have an App Certificate and the token must be valid for the channel + uid + publisher role.\n\n## Supported Platforms\n\n| Platform | Source build | Released binary |\n|----------|--------------|-----------------|\n| Linux x86_64 | ✅ | ✅ |\n| Linux aarch64 | ⏸ paused (matching SDK URL pending from Agora) | ⏸ paused |\n| macOS arm64 / x86_64 | ⏸ paused (matching SDK URL pending from Agora) | ❌ |\n| Windows | — | — (not on the roadmap) |\n\n## Build from Source\n\n```bash\ngit clone https://github.com/Agora-Build/stream-to-agora.git\ncd stream-to-agora\ncargo build --release         # CMake fetches the Agora SDK on first build\n# Binary at target/release/stream-to-agora\n```\n\nTo skip the SDK auto-download and point at a pre-staged SDK:\n\n```bash\nAGORA_RTC_SDK_PATH=/path/to/agora_rtc_sdk cargo build --release\n```\n\n## Related Projects\n\n- [atem](https://github.com/Agora-Build/Atem) — Agora platform terminal: projects, tokens, ConvoAI test pages, webhook receiver, AI agent integration\n- [Astation](https://github.com/Agora-Build/Astation) — macOS menubar hub coordinating Chisel, atem, and AI agents\n- [Vox](https://github.com/Agora-Build/Vox) — AI latency evaluation platform\n\n## License\n\nMIT\n","readmeFilename":"README.md"}