{"id":14985021,"url":"https://github.com/wimpysworld/stream-sprout","last_synced_at":"2025-04-09T20:09:40.746Z","repository":{"id":249662261,"uuid":"832042254","full_name":"wimpysworld/stream-sprout","owner":"wimpysworld","description":"Restream a video source to multiple destinations such as Twitch, YouTube, Owncast and Peertube 📡","archived":false,"fork":false,"pushed_at":"2025-03-28T13:44:50.000Z","size":1861,"stargazers_count":65,"open_issues_count":6,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T20:09:33.819Z","etag":null,"topics":["ffmpeg","hacktoberfest","kick","livestream","meld-studio","multi-stream","obs-studio","owncast","peertube","restream","rtmp","rtmp-server","rtmp-stream","simulcast","streamlabs","trovo","twitch","youtube"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wimpysworld.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["flexiondotorg"]}},"created_at":"2024-07-22T08:35:59.000Z","updated_at":"2025-04-07T07:11:02.000Z","dependencies_parsed_at":"2024-09-07T17:59:16.540Z","dependency_job_id":"b010d4d4-a370-43b8-ad97-77e336a9dde6","html_url":"https://github.com/wimpysworld/stream-sprout","commit_stats":{"total_commits":88,"total_committers":6,"mean_commits":"14.666666666666666","dds":"0.13636363636363635","last_synced_commit":"39c182ecf70e4fe4a37eb244228a56da33a09e81"},"previous_names":["wimpysworld/stream-sprout"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wimpysworld%2Fstream-sprout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wimpysworld%2Fstream-sprout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wimpysworld%2Fstream-sprout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wimpysworld%2Fstream-sprout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wimpysworld","download_url":"https://codeload.github.com/wimpysworld/stream-sprout/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103871,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffmpeg","hacktoberfest","kick","livestream","meld-studio","multi-stream","obs-studio","owncast","peertube","restream","rtmp","rtmp-server","rtmp-stream","simulcast","streamlabs","trovo","twitch","youtube"],"created_at":"2024-09-24T14:10:06.797Z","updated_at":"2025-04-09T20:09:40.721Z","avatar_url":"https://github.com/wimpysworld.png","language":"Shell","funding_links":["https://github.com/sponsors/flexiondotorg"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg src=\".github/logo.png\" alt=\"Stream Sprout\" width=\"256\" /\u003e\n\n# Stream Sprout\n\n**Restream a video source to multiple destinations such as Twitch, YouTube, Owncast and Peertube**\n\n**Made with 💝 for \u003cimg src=\".github/tux.png\" align=\"top\" width=\"24\" alt=\"Tux (Linux)\"/\u003e \u0026 \u003cimg src=\".github/apple.png\" align=\"top\" width=\"24\" alt=\"Apple (macOS)\"/\u003e**\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u0026nbsp;\u003ca href=\"https://wimpysworld.io/discord\" target=\"_blank\"\u003e\u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/712850672223125565?style=for-the-badge\u0026logo=discord\u0026logoColor=%23ffffff\u0026label=Discord\u0026labelColor=%234253e8\u0026color=%23e4e2e2\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u0026nbsp;\u003ca href=\"https://fosstodon.org/@wimpy\" target=\"_blank\"\u003e\u003cimg alt=\"Mastodon\" src=\"https://img.shields.io/badge/Mastodon-6468fa?style=for-the-badge\u0026logo=mastodon\u0026logoColor=%23ffffff\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u0026nbsp;\u003ca href=\"https://twitter.com/m_wimpress\" target=\"_blank\"\u003e\u003cimg alt=\"Twitter\" src=\"https://img.shields.io/badge/Twitter-303030?style=for-the-badge\u0026logo=x\u0026logoColor=%23ffffff\"\u003e\u003c/a\u003e\u0026nbsp;\n  \u0026nbsp;\u003ca href=\"https://linkedin.com/in/martinwimpress\" target=\"_blank\"\u003e\u003cimg alt=\"LinkedIn\" src=\"https://img.shields.io/badge/LinkedIn-1667be?style=for-the-badge\u0026logo=linkedin\u0026logoColor=%23ffffff\"\u003e\u003c/a\u003e\u0026nbsp;\n\u003c/p\u003e\n\n# Introduction\n\nStream Sprout 🌱 is a simple, self-contained, and easy-to-use solution for streaming to multiple destinations such as Twitch, YouTube, [Owncast](https://owncast.online/) and [Peertube](https://joinpeertube.org/) 📡\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\".github/demo.gif\" alt=\"Stream Sprout\" width=\"505\" height=\"415\"/\u003e\n\u003c/div\u003e\n\nIt uses [FFmpeg](https://ffmpeg.org/) to receive the video stream from OBS Studio (or any encoder that can produce RTMP) and then restreams it to multiple destinations. This provides similar functionality as services like Restream.io and Livepush.io but without the need to pay 💸 for a third-party service or run something like nginx with the [RTMP module](https://github.com/arut/nginx-rtmp-module).\n\nStream Sprout is configured with a simple YAML file and designed to be run on the same computer as your [OBS Studio](https://obsproject.com/) instance (it can be run remotely, [**with appropriate security measures**](#-ffmpeg-rtmp-server-accepts-any-rtmp-stream-on-the-listening-port-), and does not require root privileges.\n\nThere is no transcoding or processing of the video stream 🎞️\nThe stream is received and then restreamed to the destinations you configure without modification.\nOptionally you can also archive the stream to disk 💾\n\nWhile the restreaming process is lightweight, **your bandwidth requirements will increase with each destination you add.** 📈\nEnsure you have sufficient bandwidth to support the number of destinations you intend to stream to ⤴️\n\nStream Sprout is developed on Linux 🐧 and should work on macOS 🍏 or any other platform that supports `bash` and `ffmpeg` 👍️\n\n## Get Started\n\n- [Install](#installation) Stream Sprout 🧑‍💻\n- [Configure](#configure-stream-sprout) Stream Sprout 🧑‍💻\n- [Configure](#configure-obs-studio) OBS Studio 🎛️\n- Start `stream-sprout` ⌨️\n- Click the *Start Streaming* button in OBS Studio 🖱️\n- Do you your thing 🎥\n- Click the *Stop Streaming* button in OBS Studio 🖱️\n- \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e to stop `stream-sprout` ⌨️\n\n## Installation\n\n### Debian\n\n- Download the Stream Sprout .deb package from the [releases page](https://github.com/wimpysworld/stream-sprout/releases) 📦️\n- Install it with `apt-get install ./stream-sprout_0.1.5-1_all.deb`.\n\n### macOS\n\nInstall the Stream Sprout requirements using `brew`:\n\n```shell\nbrew install bash ffmpeg\n```\n\nNow clone the project:\n\n```shell\ngit clone https://github.com/wimpysworld/stream-sprout.git\ncd stream-sprout\n```\n\n### Nix \u0026 NixOS\n\n[![FlakeHub](https://img.shields.io/endpoint?url=https://flakehub.com/f/wimpysworld/stream-sprout/badge)](https://flakehub.com/flake/wimpysworld/stream-sprout)\n\nStable releases of Stream Sprout are published to FlakeHub for Nix users ❄️\nSee the flake on FlakeHub for more details:\n\n- \u003chttps://flakehub.com/flake/wimpysworld/stream-sprout\u003e\n\n### Snap\n\n[![stream-sprout](https://snapcraft.io/stream-sprout/badge.svg)](https://snapcraft.io/stream-sprout)\n\nFor Linux distributions that support snap packages, Stream Sprout is available from the Snap Store 🛍️\n\n```shell\nsudo snap install stream-sprout\n```\n\n### Ubuntu\n\n- Download the Stream Sprout .deb package from the [releases page](https://github.com/wimpysworld/stream-sprout/releases) 📦️\n- Install it with `apt-get install ./stream-sprout_0.1.5-1_all.deb`.\n\n### Docker \u0026 Podman\n\n#### Pull the container\n\nThe Stream Sprout container image is available from the GitHub Container Registry for amd64 and arm64.\nTo pull the latest container image:\n\n```shell\ndocker pull ghcr.io/wimpysworld/stream-sprout:latest-alpine\n```\n\nOr if you want a specific version:\n\n```shell\ndocker pull ghcr.io/wimpysworld/stream-sprout:0.1.5-alpine\n```\n\n#### Run the container\n\nThe `stream-sprout.yaml` configuration file will be on the host computer so you need mount a volume to access it from the container.\n\nIf you have already pulled the container image, you can run Stream Sprout with:\n\n```shell\ndocker run -p 1935:1935 -it -v $PWD:/data stream-sprout --config /data/stream-sprout.yaml\n```\n\nIf you have not pulled or built the container image, you can run Stream Sprout with:\n\n```shell\ndocker run -p 1935:1935 -it -v $PWD:/data ghcr.io/wimpysworld/stream-sprout:alpine-latest --config /data/stream-sprout.yaml\n```\n\n- The `-p 1935:1935` part will expose the RTMP server port `1935` on the host computer.\n  - If you have configured Stream Sprout to use a different port, you should change the port number here too.\n- The `-it` options will run the container in interactive mode.\n- The `-v $PWD:/data` part will mount your current directory `$PWD` as `/data` within the container, allowing you to access your files using the `/data` path.\n\n#### Build the container\n\nBuild the Stream Sprout container image:\n\n```shell\ndocker build -t stream-sprout .\n```\n\n### From source\n\nYou need to have [FFmpeg](https://ffmpeg.org/) on your system.\n\n```bash\ngit clone https://github.com/wimpysworld/stream-sprout.git\ncd stream-sprout\n```\n\n## Configure Stream Sprout\n\nCopy the [example Stream Sprout configuration](https://github.com/wimpysworld/stream-sprout/blob/main/stream-sprout.yaml.example) and edit it to suit your needs 📝\n\nYou can specify the configuration file to use with the `--config \u003cpath\u003e` option.\nIf you don't specify a configuration file, Stream Sprout will look for a configuration file in the following locations, in this order:\n\n- Current working directory `./stream-sprout.yaml`\n- XDG configuration directory `$XDG_CONFIG_HOME/stream-sprout.yaml` (*Linux*) or `~/.config/stream-sprout.yaml` (*macOS*)\n- `/etc/stream-sprout.yaml`\n\n### Server\n\nHere's an example configuration for the Stream Sprout `server:` section.\n\n```yaml\nserver:\n  ip: 127.0.0.1\n  port: 1935\n  app: sprout\n  key: create your key with uuidgen here\n  archive_stream: false\n  archive_path: ~/Streams\n```\n\nThe `server:` section is used to configure the RTMP server that Stream Sprout creates.\n- The default `ip` address is `127.0.0.1`. Use `0.0.0.0` to allow connections to any network interface.\n  - If you remotely host Stream Sprout, use an IP address that is accessible by your computer that runs OBS Studio.\n- The default `port` for RTMP is `1935`, but you can use any port between `1024` and `65535`.\n- The default `app` name is `sprout`, but you can use any name you like.\n- Set `key:` to a secure value to prevent unauthorized access. Running `uuidgen` will generate a suitable value.\n\nThe IP address, port, app name and key are composed to create the RTMP URL that you will use in OBS Studio.\nFor example, `rtmp://ip:port/app/key`.\n\n### 🚨 FFMPEG WILL ACCEPT ANY RTMP STREAM ON THE CORRECT PORT 🚨\n\n**FFmpeg does not currently enforce `app` or `key` paths for its incoming RTMP server.**\n**Regardless of the `app` or `key` you set in the Stream Sprout YAML FFmpeg will accept *any* incoming stream on the correct `port`**\n\n⚠️ Do not expose the Stream Sprout RTMP server to the public internet without additional security measures ⚠️\n- Consider using a VPN or SSH tunnel to secure the connection 🔐\n- Or firewall the RTMP port to only allow connections from trusted IP addresses 🔥🧱\n- See the [Limitations section](#limitations) section below for more information.\n\n#### Archive streams\n\nIf `archive_stream:` is `true` Stream Sprout will archive the stream to disk in the directory specified by `archive_path:`.\nIf `archive_path:` is not accessible, Stream Sprout will fallback to using the current working directory.\n\n### Services\n\n`services:` are arbitrarily named.\n**Just create an entry for each RTMP destination you want to stream to.**\nThe example configuration includes entries for Trovo, Twitch, and YouTube but any RTMP destination can be added.\n\n```yaml\nservices:\n  my-rtmp-destination:\n    enabled: true\n    rtmp_server: \"rtmp://rtmp.example.com/live/\"\n    key: \"my_super_secret_stream_key\"\n```\n\n### Twitch\n\nHere's an example configuration for Twitch.\n\n```yaml\nservices:\n  twitch:\n    enabled: true\n    rtmp_server: \"rtmp://live.twitch.tv/app/\"\n    key: \"your_twitch_stream_key\"\n```\n\n#### Ingest servers\n\nThe example configuration uses the primary Twitch ingest endpoint, which is `rtmp://live.twitch.tv/app/`.\nIf you want to optimize your stream latency, you can use a Twitch ingest endpoint closer to your location.\nA short list of recommended endpoints, based on your whereabouts, is available from [Recommended Ingest Endpoints For You](https://help.twitch.tv/s/twitch-ingest-recommendation).\n\nYou can find a complete list of Twitch ingest endpoints from \u003chttps://twitchstatus.com/\u003e.\n\n#### Testing\n\nIf you want to test streaming to Twitch without going live, you can use the `?bandwidthtest=true` query parameter.\n\nAdd `?bandwidthtest=true` to the end of your Twitch stream key, this will enable bandwidth testing, which you can monitor using \u003chttps://inspector.twitch.tv/\u003e, and the stream will not go live on your channel.\n\n### YouTube\n\nHere's an example configuration for YouTube.\n\n```yaml\nservices:\n  youtube:\n    enabled: true\n    rtmp_server: \"rtmp://a.rtmp.youtube.com/live2/\"\n    key: \"your_youtube_stream_key\"\n```\n\n## Configure OBS Studio\n\n- Open OBS Studio\n- Go to `Settings` \u003e `Stream`\n- Select `Custom` from the `Service` dropdown\n- Copy the server `url:` from your Stream Sprout configuration to the `Server` field:\n  - `rtmp://127.0.0.1:1935/sprout` (*default*)\n- Copy the `key:` (if you specified one) from your Stream Sprout configuration to the `Stream Key` field\n\n![OBS Studio Stream Settings](.github/obs-settings.png)\n\n## Limitations\n\n- Protecting the Stream Sprout RTMP server with a key does not work\n  - FFmpeg does not currently support enforcing RTMP stream app paths or keys\n  - https://www.reddit.com/r/ffmpeg/comments/s4keuu/enforce_rtmp_stream_keys_and_strict_paths/\n  - https://patchwork.ffmpeg.org/project/ffmpeg/patch/20190925185708.70924-1-unique.will.martin@gmail.com/\n```\n  [rtmp @ 0x2ca9be80] Unexpected stream STREAMBOMB, expecting c5b559b2-589d-4925-a28e-20d1954fd6c5\n    Last message repeated 1 times\n```\n- Stream Sprout does not support restreaming using secure RTMP (RTMPS).\n  - *At least I don't think it does, but I haven't fully tested it.*\n    - Kick only appears to support rtmps:// URLs and Stream Sprout restreams do not appear on Kick.\n  - https://superuser.com/questions/1438939/live-streaming-over-rtmps-using-ffmpeg\n- Each destination you add will increase your bandwidth requirements.\n\n## References\n\nThese are some of the references used to create this project:\n\n- https://trac.ffmpeg.org/wiki/EncodingForStreamingSites\n- https://ffmpeg.org/ffmpeg-protocols.html#rtmp\n- https://ffmpeg.org/ffmpeg-formats.html#flv\n- https://ffmpeg.org/ffmpeg-formats.html#tee-1\n- https://obsproject.com/forum/resources/obs-studio-stream-to-multiple-platforms-or-channels-at-once.932/\n- https://stackoverflow.com/questions/16658873/how-to-minimize-the-delay-in-a-live-streaming-with-ffmpeg\n- https://dev.to/ajeetraina/run-ffmpeg-within-a-docker-container-a-step-by-step-guide-c0l\n- https://github.com/jrottenberg/ffmpeg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwimpysworld%2Fstream-sprout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwimpysworld%2Fstream-sprout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwimpysworld%2Fstream-sprout/lists"}