# Live Stream > Live Stream is a live streaming plugin for WordPress by WordPlus. Hosts go live from the browser or from OBS, and viewers watch on the pages of the site in the browser, with low delay over WebRTC, and with chat and reactions beside the stream. The video and the chat run on the servers of WordPlus Cloud. Facts to rely on, as of version 0.2.0: - **Names:** "Live Stream" on its website and in the WordPress admin. On WordPress.org it is "WordPlus Live Stream", slug `wordplus-live-stream`: https://wordpress.org/plugins/wordplus-live-stream/. - **What it needs:** WordPress 6.0 or later, PHP 7.4 or later, and a WordPlus Cloud subscription that includes live streaming (https://www.wordplus.cloud). Hosts going live from the browser need the site on HTTPS. - **What it costs:** the plugin is free to download. Streaming runs on the WordPlus Cloud subscription. Each site streams to 50 viewers at once unmetered, however long they watch. Above that, each viewer takes one credit a minute. Each WordPress site adds 5,000 credits a month to its WordPlus Cloud account, and more are bought at https://www.wordplus.cloud/pricing. Hosts take no credits. A stream has no limit of viewers. - **Going live:** from the WordPress admin (Live Stream → Studio) with a camera, a microphone and a shared screen, in HD (720p) or Full HD (1080p), or from OBS 30 or later and any other encoder over WHIP, with the server address and bearer token the studio gives. Hosts can blur their background or replace it with a picture, and remove the noise around them with AI noise removal. - **Watching:** in the browser over WebRTC, with no app. Each viewer gets the picture size that their player and connection need. Picture-in-picture, full screen with the chat, and keyboard controls. - **Chat:** a light chat run by WordPlus Cloud (not saved, with moderation: pin, delete, mute, remove, ban, slow mode), a Better Messages chat room saved on the site (Better Messages 3.1 or later, WebSocket version), or none. Reactions rise over the picture. - **On a page:** the Live stream block with ready layouts, a block for each part (player, chat, details, studio), a shortcode for each, such as `[wordplus_stream id="12"]`, and the Live now block or `[wordplus_stream_live]` for the streams live now. - **Who watches:** everyone, logged-in users, or chosen roles, and membership plugins decide with the `wordplus_stream_can_watch` filter. Administrators host every stream. - **Scheduled streams:** a countdown before the start, Add to calendar, and a schedule of times for a show that goes live again and again. - **For developers:** `wordplus_streams()` in PHP, `wordplus_stream_…` hooks, and `window.wordplusStreams` in JavaScript, to give the groups, courses or events of another plugin a stream, or let its members go live. - **Not there yet:** streaming in over RTMP, and guests on stage beside the host. - **Status:** a beta. It works, and it still changes. - **Get it:** Plugins → Add New Plugin in WordPress, searching for WordPlus Live Stream, or the zip at https://www.wordplus.cloud/download/live-stream. Docs at https://stream.wordplus.cloud/docs/. --- # Getting started Address: https://stream.wordplus.cloud/docs/ Live Stream puts live streams on your WordPress site. Hosts go live from the WordPress admin, with a camera or from OBS, and viewers watch on your own pages with a chat beside the picture. The video and the chat run on the servers of WordPlus Cloud, and your site decides who may watch and who may go live. **It is a beta** Live Stream works, and it still changes. See [The beta](https://stream.wordplus.cloud/docs/beta/). ## What you need - **WordPress 6.0 or later** and **PHP 7.4 or later**. - **A [WordPlus Cloud](https://www.wordplus.cloud) subscription** that includes live streaming. Live Stream comes with it. Each site streams to 50 viewers at once unmetered, and above that each minute a viewer watches takes a credit: see [Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/). - **HTTPS.** Browsers let a page use the camera and the microphone only over HTTPS, so hosts going live from the browser need your site on it. ## Install the plugin Live Stream is on WordPress.org as [WordPlus Live Stream](https://wordpress.org/plugins/wordplus-live-stream/). 1. In WordPress, go to **Plugins → Add New Plugin** and search for **WordPlus Live Stream**. 2. Press **Install Now**, then **Activate**. A **Live Stream** menu appears in the admin. Or [download the zip](https://www.wordplus.cloud/download/live-stream), version 0.2.0, and upload it under **Plugins → Add New Plugin → Upload Plugin**. Later releases come as updates in **Dashboard → Updates**, like those of any plugin, once the licence is active. ## Activate the licence Go to **Live Stream → Licence** and enter your WordPlus Cloud licence key. If the site already runs another WordPlus plugin on the subscription, such as Better Messages, it is connected already. The header of **Live Stream → Studio** shows where the licence stands: the domain of your site once WordPlus Cloud takes its streams, or **Licence issue**. Choose it for the details, to check again, or to open the Licence page. Until the licence is active, a notice on every tab says why nobody can go live or watch yet: - No licence is active on the site. - The licence does not include Live Stream. - The plan does not include live streaming. - The site is still getting its own key, which takes a minute or two after activating. Without a licence you can still start a test stream in the studio and watch it on its page in another tab of the same browser, as your viewers will see it. Only you can see a test stream, and nothing of it leaves your computer ([A test stream](https://stream.wordplus.cloud/docs/going-live/#test-stream)). ## Create a stream **Live Stream → Studio** is one page with three tabs: **Studio**, where hosts go live, then **Streams** and **Appearance** for administrators. 1. Open **Streams** and press **Create stream**. Give it a title, such as "Weekly Q&A". 2. Set what it needs. Each stream keeps its own settings: - **Schedule:** when it is planned to go live, in the time zone of the site. Viewers see a countdown to the next time. Add more times, each with a title of its own if you like, for a stream that goes live again and again, like a weekly show ([A schedule](https://stream.wordplus.cloud/docs/on-a-page/#a-scheduled-start)). Optional, as a stream can go live any time. - **Cover:** the picture before the stream starts and after it ends. Without one, the cover set in the Appearance tab. - **Who can watch:** everyone, logged-in users, or selected roles. Administrators host. - **Chat:** see [Chat and moderation](https://stream.wordplus.cloud/docs/chat/). - **Texts:** what viewers read at each moment of this stream, in your own words. Before it starts, with a line of your own under it, while waiting for the picture of the host, after it ends with the thanks under it, and the notes of the light chat while it is closed. Leave one empty for the words of Live Stream, in the language of the site. 3. Press **Save changes**. Creating, copying and deleting a stream happen at once, and every other change waits for the save bar. ![The settings of a stream on the Streams tab: title, shortcode, start, cover, Live now link and who can watch](https://stream.wordplus.cloud/img/shots/stream-settings.webp) ## Put it on a page - In the **Studio** tab, press **Create a page** beside the stream. Live Stream publishes a page with the stream on it, the chat beside the player. It is offered while no page has the stream on it yet. - Or add the **Live stream** block to any page and choose the stream in it. - Or paste the shortcode of the stream, shown in its settings, such as `[wordplus_stream id="12"]`. More ways, and the blocks for each part, in [Putting a stream on a page](https://stream.wordplus.cloud/docs/on-a-page/). ## Go live Open **Live Stream → Studio**, choose **Go live** beside the stream, turn on your camera and press **Go live**. [Going live from the browser](https://stream.wordplus.cloud/docs/going-live/) walks through it, and [Streaming from OBS](https://stream.wordplus.cloud/docs/obs/) covers OBS. --- # Going live from the browser Address: https://stream.wordplus.cloud/docs/going-live/ Hosts go live with the camera and microphone of the computer or phone they are on, and can share their screen. For scenes and overlays, [stream from OBS](https://stream.wordplus.cloud/docs/obs/) instead. ## Where hosts go live - **Live Stream → Studio**, in the WordPress admin. Its Studio tab lists the streams you host. Choose **Go live** beside one to open its studio. - **The admin bar.** On a page showing a stream you host, **Go live** in the admin bar opens its studio. - **The page of the stream**, where the page has the **Stream studio** block or `[wordplus_stream_studio id="12"]`. Only the hosts of the stream see it, and everyone else sees nothing there. See [Putting a stream on a page](https://stream.wordplus.cloud/docs/on-a-page/). Administrators host every stream. ## Going live 1. **Open the studio of the stream.** Its picture says "Ready when you are". 2. **Choose "Turn on camera and microphone".** Your browser asks for the camera and the microphone the first time. Until you go live the picture is a preview: only you see it. 3. **Set up.** Choose the camera, the microphone and the speakers (where the browser lets a page choose them). The level of the microphone moves as you speak. On a phone, switch between the front and the back camera. If you play or sing, switch on **Original sound, for music** ([Sound](#sound), below). 4. **Choose the quality** (below). 5. **Countdown.** "Count down 3, 2, 1 before going live" shows a countdown over the picture, which you can stop. Switch it off to go live at once. 6. **Press Go live.** The studio remembers your camera, microphone, speakers, quality and sound in this browser. Before you go live, you can also blur the room behind you or put a picture there, and turn on **AI noise removal** for the microphone ([Background blur, backgrounds and noise removal](https://stream.wordplus.cloud/docs/effects/)). ![The studio while live: the camera of the host, the statistics, the controls and the chat beside them](https://stream.wordplus.cloud/img/shots/studio-live.webp) ## While you are live - **The bar under the picture:** the microphone and the camera, each with a menu of devices, and the menu of the microphone with **Speech** and **Original sound** too, **Share screen**, **Effects** for the background and the noise removal ([Background blur, backgrounds and noise removal](https://stream.wordplus.cloud/docs/effects/)), **More** (with Stream from OBS) and **End stream**. - **The statistics:** time on air, how many watch and their peak, messages, reactions and the connection. Under them, how your picture goes out, such as "720p · 30 fps · 1.4 Mbps". - **Beside the picture:** the **Chat**, and the **Stream** tab, with its link to share. - **Shortcuts:** ⌘/Ctrl+D turns the microphone on and off, ⌘/Ctrl+E the camera. - **Staying live:** the studio keeps the screen awake, and asks before you leave the page. The viewer count counts the audience only: you are not in it. ### Sharing your screen Press **Share screen** and choose a screen, a window or a tab. **Stop sharing** ends it. The screen goes out no larger than the quality you chose, at 30 frames a second. ### From another window If you open the page of the stream, or a second studio, while you are live, that window shows the stream as everyone sees it and sends nothing: "You are live from another window." ## A test stream Without a WordPlus Cloud subscription, you can still see how a stream will look. Where **Go live** would be, the studio offers **Start a test stream**: 1. Turn on your camera and microphone, or share your screen, as for going live. 2. Press **Start a test stream**. The studio counts down 3, 2, 1 if its countdown is on, then shows **Test** over your picture, with the time on air and "Only you can see it". 3. Choose **Watch it as viewers do**. The page of the stream opens in another tab of the same browser and plays your stream as your viewers will get it, with its title, the Live badge, the chat and the reactions, and "Only you can see this test" beside Live. Its sound waits for **Turn sound on**, so your microphone does not hear itself. A message written on the page shows in the studio, and one written in the studio shows on the page. 4. Press **End test** when you are done. The page shows that the stream has ended, and the studio says how long the test ran. The page must be opened from the studio. A page opened another way, or one a security plugin serves with a Cross-Origin-Opener-Policy header, says that it cannot reach the test. A test cannot be watched on another device. Nothing of a test leaves your computer, so nobody else can see it. Going live for everyone needs the site connected to WordPlus Cloud: **Connect to go live** in the studio shows the way. ## Quality Before going live, **Best quality** offers: | Choice | Upload it needs | |---|---| | **HD** (720p) | Up to about 4 Mbps | | **Full HD** (1080p) | Up to about 8 Mbps | It is the best the stream sends, not what every viewer gets. Each viewer gets the picture that the size of their player and their connection need, so a phone gets less than a big screen. While nobody watches in a big window or full screen, less goes out, and the statistics say so ("720p of 1080p"). Viewers can also choose the quality in the settings of the player: **Auto**, which follows the size of the player and their connection, or one of the sizes the stream sends up to 720p, such as **720p**, **540p** or **360p**, which they then get whatever the size of their player. The smallest saves data. Full HD is not among them: a stream in Full HD reaches the viewers whose player needs it, in a big window or full screen, on **Auto**. A stream from OBS sends no sizes, so its choices read **High**, **Medium** and **Low**. ## Sound The microphone is tuned for speech unless you choose otherwise. The browser removes echo and background noise and evens out the level, and the voice goes out clearly at 48 kbps. For music, choose **Original sound**: **Original sound, for music** in the setup before going live, or **Original sound** in the menu of the microphone in the bar, where **Speech** goes back. Then: - The microphone goes out as it hears. Echo and noise removal take instruments for noise, and level control makes singing pump, so neither is used. - It goes out at 128 kbps, and in stereo where your microphone has two channels. - Use headphones. Without echo removal, what your speakers play goes back into the microphone. Switching while live sends the microphone again, and viewers miss a moment of the sound. A shared screen always sends its sound this way, and a stream from OBS sends the sound OBS is set to. ## When a stream plays badly The settings of the player also open **Statistics** over the picture, or press **i**: what arrives (its size and layer, frame rate, bitrate, codec, packet loss, jitter and freezes), the sound, the way to the server and the round trip, how long the picture took to start, its stalls, reconnects and errors, and what happened last. **Copy** puts all of it on the clipboard, to paste into a support request. Nothing of it leaves the browser otherwise. While the picture stops, a spinner shows over it, and when the connection of the viewer drops, the player says they are offline and picks the stream up again as soon as they are back. ### When your stream goes out badly While you are live, **Statistics** at the end of the figures under the picture opens the same panel for you, as do the settings of the player and **i**. It starts with what you send: what the camera or screen gives, the codec and whether the computer encodes it in hardware, each size the stream goes out in (such as 720p, 540p and 360p) with its frame rate and bitrate, or off while no viewer needs it, whether the computer or the connection holds the picture back and for how long, the packet loss and round trip the server reports, what was sent again, and the sound with the level of your microphone. The connection shows how much the browser estimates it can upload. **Copy** puts all of it on the clipboard for a support request. ## The keys of the player Viewers can use the player from the keyboard alone, and screen readers say each moment of the stream as it comes: joining, waiting for the host, ended, or what went wrong. Press **?** on the player for the list of its keys. | Key | What it does | |---|---| | **M** | Mute or unmute | | **↑** **↓** | Volume up or down, with the picture in focus | | **F** | Full screen | | **C** | Show or hide the chat beside the player | | **P** | Picture-in-picture | | **I** | Statistics | | **Esc** | Close a menu or a dialog | | **?** | The list of these keys | In a menu, the arrow keys, **Home** and **End** move between its items, and a letter goes to the next one starting with it. ## Ending the stream Press **End stream**, then **End for everyone**. Everyone watching sees that it has ended and how long it ran. The studio then sums it up: time on air, the most watching at once, the messages and the reactions. You can go live again with the same stream later. --- # Streaming from OBS Address: https://stream.wordplus.cloud/docs/obs/ Stream from OBS when you want scenes, overlays or several cameras. Live Stream takes OBS 30 or later, and any other encoder that streams over WHIP. You still go live from the studio: OBS sends the picture, and the studio decides when viewers see it. ## Connect OBS 1. **Open the studio of the stream** (**Live Stream → Studio**, then **Go live** beside the stream) and choose **Stream from OBS**. With the camera already on, it is under **More**. 2. The studio shows the steps, with "Waiting for OBS…": 1. In OBS, open **Settings → Stream** and choose **WHIP** as the service. 2. Copy **Server** from the studio into the **Server** field of OBS. 3. Copy **Bearer token** from the studio into the **Bearer Token** field of OBS. **Show** reveals it, **Copy** copies it. 4. In the same window, set **Total Layers** to **3** if your OBS has it (OBS 32.1 or newer). 5. Set the output of OBS as the studio says (below), then press **Start Streaming** in OBS. 3. Once the picture from OBS arrives, the studio says **OBS is connected** and shows the picture, with what arrives: its size, frame rate and bitrate. Only you see it so far. 4. Press **Go live**. Viewers see the whole picture from OBS. ![The studio with OBS connected: the picture from OBS previewed, what arrives from it, the steps, the server address and the bearer token](https://stream.wordplus.cloud/img/shots/studio-obs.webp) ## What to set OBS to ### Layers With **Total Layers** at **3** (**Settings → Stream**, OBS 32.1 and newer), OBS sends the full picture and two smaller copies of it, at once. Each viewer gets the largest their screen and connection take, and a viewer whose connection slows down steps down to a smaller copy instead of stopping to wait. It needs an encoder for each copy, and more upload from your computer than one picture: OBS gives the full picture the bitrate you set and the copies two thirds and one third of it, so 4,500 kbps takes about 9 Mbit/s of upload in all. If your upload cannot carry that, viewers see the picture freeze: set a lower bitrate, or 2 layers. Without it, OBS sends one picture, the same to every viewer, so choose a size every connection can take. ### Size and bitrate The studio gives this advice, word for word: > In Settings → Video, set Output (Scaled) Resolution to 1920×1080 and 30 FPS. Without layers, 1280×720 lets viewers on slow connections keep up. > In Settings → Output, choose the Advanced output mode. Under Streaming, keep the video encoder Simple mode had, and set the bitrate to about 4,500 kbps (2,500 kbps without layers), Keyframe Interval to 1 s and Max B-frames to 0. Viewers coming in then get the picture within a second, and it plays smoothly in their browsers. Then press Start Streaming in OBS. > These settings are a starting point. Try them on your own stream and connection: watch it from another device, and change the bitrate, Total Layers or the preset until it plays smoothly. If OBS sends a bigger picture than the stream takes, the studio says so and does not go live until it is changed. For example: > OBS sends 2560×1440, more than the 1080p a stream takes. In OBS, set Settings → Video → Output (Scaled) Resolution to 1920×1080. ### Keyframes and B-frames: the Advanced output mode Two settings decide how soon viewers see the picture and how smoothly it plays, and only the **Advanced** output mode of OBS has them (**Settings → Output → Output Mode**, then the **Streaming** tab): - **Keyframe Interval: 1 s.** A viewer sees the picture from the next keyframe on, when they come in and when they come back to the page from another tab. OBS sends a keyframe only at its interval, and the Simple output mode leaves it on auto, about one every 8 seconds, so viewers wait up to 8 seconds. At 1 s they wait a second at most. - **Max B-frames: 0.** Browsers cannot play B-frames and skip them, so a picture with B-frames stutters. The Simple output mode sends none, but the Advanced mode has a setting of its own, which some encoders start at 2. The Advanced mode also has its own **Video Encoder**. Keep the one the Simple mode had, a hardware encoder of your graphics card where there is one, and the same preset. Leave the rest as it is. The studio checks both while OBS sends: > OBS sends a keyframe every 8 seconds, so viewers wait up to that long for the picture as they come in and when they come back to the page. In OBS, choose the Advanced output mode in Settings → Output and set Keyframe Interval to 1 s under Streaming. > OBS sends 22 frames a second, fewer than it should, and viewers see the picture stutter. In OBS, set Max B-frames to 0 under Settings → Output → Streaming, in the Advanced output mode, since browsers skip B-frames. If it is 0 already, the encoder cannot keep up: choose a faster preset or fewer Total Layers. Neither stops you going live. ### Try them on your stream These numbers are a starting point. What suits a stream depends on what it shows, on the computer that sends it and on its connection, so try them before you go live: 1. Make a stream for trying, on a page nobody else knows, start streaming in OBS and press **Go live** in its studio. Viewers see the picture only once it is live. 2. Open the page of the stream on another device, on another network if you can, and watch it for a few minutes, with the kind of picture you will stream. 3. Keep **View → Stats** open in OBS. It shows frames skipped by the encoder and frames dropped on the way out. Then change one thing at a time: - **The picture freezes and catches up again:** your upload cannot carry what OBS sends. Lower the bitrate, or set **Total Layers** to **2**. - **The picture stutters, and Stats shows frames skipped due to encoding lag:** the encoder cannot keep up. Choose a faster preset, or fewer layers. Another program using the graphics card, such as a remote desktop, can take its share too. - **Detail pulses once a second on a busy picture:** each keyframe takes a large share of the bits. Raise the bitrate if your upload carries it, or set **Keyframe Interval** to **2 s**, which makes viewers wait up to 2 seconds for the picture. - **Everything plays smoothly:** keep it, or try a higher bitrate for a sharper picture while it still does. ## The bearer token - Only the hosts of the stream see it, in the studio. - **New key** makes a new one. OBS stops streaming until it has the new one, so do this if the token was seen by someone it should not have been. - Each stream has one, the same every time you go live with it, until you make a new one. ## Back to the camera **Use the camera instead** leaves OBS and goes back to the preview of the camera. ## Going live on its own For a stream that runs by itself, such as a demo sent from a computer that is always on, open the stream in **Live Stream → Studio → Streams** and turn on **Go live when OBS connects**. Then: - The stream goes live as soon as OBS starts streaming with its token, with nobody in the studio. - If OBS stops for a while, the stream stays live while anyone watches. With nobody watching for five minutes it ends, and it goes live again as soon as OBS is back. - It stays live for as long as OBS sends, for days too. - When you end it in the studio, it stays ended, even if OBS tries again. Choose **Stream from OBS** in its studio to let OBS take it live again. Take the token from the studio once, as above. A change of the setting reaches the stream the next time a host opens it, so open its studio after you change it. ## When something is wrong - **"Nothing has come from OBS yet. Start streaming there first":** press **Start Streaming** in OBS, and check the server and the token. - **The studio stays on "Waiting for OBS…":** check that the service in OBS is WHIP, and that the server and the token were copied whole. - **OBS says it could not access the stream key:** OBS says this whatever the cloud answered. Check that the token was copied whole and is the one the studio shows now. - **OBS cannot connect after the stream ended:** an ended stream keeps OBS out. Choose **Stream from OBS** in its studio again, then start streaming in OBS and go live. - **Viewers wait several seconds for the picture,** as they come in or come back to the page: set **Keyframe Interval** to **1 s** in the Advanced output mode (above). - **The picture stutters for viewers:** set **Max B-frames** to **0** in the Advanced output mode (above). If it is 0 already, OBS cannot encode fast enough: choose a faster preset, or fewer **Total Layers**. **View → Stats** in OBS shows frames skipped by the encoder and frames dropped on the way out. - **The picture freezes and catches up again:** your upload cannot carry what OBS sends. Lower the bitrate, keeping in mind that three layers take about twice it in all. --- # Background blur, backgrounds and noise removal Address: https://stream.wordplus.cloud/docs/effects/ When you go live from the browser, you choose what viewers see behind you: your own room, the room blurred, or a picture. **AI noise removal** takes typing, fans and other sounds around your voice out of the microphone. Both are set up in the studio before you go live, and can be changed while you are live. Everything runs in your own browser. Your camera and microphone are processed on your computer or phone before anything is sent, so no picture or sound goes to a server for it. Viewers get the stream as it already looks, with the background in place, and your voice without the noise. A stream from OBS sends what OBS makes: set up backgrounds and filters there instead. ## Choosing a background In the studio of the stream, turn on your camera. Under it, **Background** offers: - **None:** the camera as it is. - **Blur:** the room blurred, you sharp. - The pictures the site offers ([Setting them up](#setting-them-up)). - **Add your own picture**, where the site allows it ([Your own picture](#your-own-picture)). A choice applies at once to your preview. Your browser keeps it, and your video calls on the site share it, so the next stream starts with the same background. When you press **Go live**, the stream waits a few seconds at most for an effect still loading, so it goes out with the effect from its first frame. ### Effect settings Once the blur or a picture is on, **Effect settings** tunes it for your room: | Setting | From | To | |---|---|---| | **Outline** | Tighter | Wider | | **Edge** | Sharp | Soft | | **Steadiness** | Quick | Steady | | **Blur strength** (with Blur) | Light | Strong | **Reset** puts them back. Even light on your face and a plain wall behind you help most. If your picture stutters or your device gets warm, turn the background off. ### Your own picture Where the site allows it, **Add your own picture** lets you pick a JPEG, PNG or WebP from your own device, under 40 MB. It stays in your browser and is never uploaded to the site. **Remove this picture** takes it away. A browser that keeps no site data, such as a private window, keeps it until the page is closed. ## AI noise removal Under **Sound**, **Noise** has **AI noise removal**. With it on, your microphone carries your voice without the typing, fans and other sounds the browser leaves in. If your voice breaks up or your device gets warm, turn it off. It is for speech. With **Original sound, for music** ([Sound](https://stream.wordplus.cloud/docs/going-live/#sound)) the microphone goes out as it hears, so AI noise removal is off. ## While you are live **Effects** in the bar under the picture opens the background and the noise removal. Everyone watching sees and hears each change at once. ## Setting them up The effects are not part of the plugin. An administrator downloads them to the site once, from WordPlus Cloud, in **Live Stream → Appearance → Studio effects**, and the studio offers them from then on: | Row | What it does | |---|---| | **Background effects** | Downloads the blur and the pictures behind the host. Until then, the studio offers no background. | | **AI noise removal** | A download of its own. Until then, the studio offers no noise removal. | | **Built-in backgrounds** | Pictures from WordPlus Cloud for hosts to choose. Each one picked is downloaded to the site. | | **Pictures of the site** | Your own pictures from the Media Library, offered after the built-in ones. Wide pictures work best, at least 1280 by 720. | | **Pictures of the hosts** | Lets hosts pick a picture of their own device as the background ([Your own picture](#your-own-picture)). Nobody on the site sees it before viewers do, so turn it on only for hosts you trust. Off at first. | Each host then turns the effects on in the studio. Better Messages shares these settings, so its calls offer the same. ## What they need - A browser with WebGL 2 and WebAssembly SIMD, which current Chrome, Edge, Firefox and Safari have. - For the blur and the pictures, a device with at least four processor cores. Where a device cannot run an effect, the studio says **The effect could not start on this device**. --- # Recording and replays Address: https://stream.wordplus.cloud/docs/recording/ A stream can be recorded while it is live. Everything viewers see and hear is recorded, until you stop it or the stream ends. Once it ends, its page can play the replay, so those who missed it can catch up. ## Recording a stream In the studio of the stream, press **Record**, then **Start recording**. **Stop recording** stops it, or ending the stream does. A host can also start and stop it while live. To record every time, turn on **Record every time this stream goes live** in the studio before going live: the recording then starts as you go live and stops as the stream ends. Recording takes 1 credit a minute from the credits of the site ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). ## What viewers are told The recording settings of the site choose what viewers see while one runs: - **REC** over the picture. - **REC** over the picture, and a notice that the stream is recorded. - Nothing: viewers are not told. ## The replay A few minutes after the stream ends, the recording is ready. Where it is for viewers, the page of the stream plays it in its player, to everyone who may watch the stream ([Who can watch](https://stream.wordplus.cloud/docs/on-a-page/#who-can-watch)). Otherwise only site administrators can watch it, in **Live Stream → Recordings**. A transcript can be made with it too. ## Where recordings are kept WordPlus Cloud makes the recording while the stream is live, then your site takes the files: into the storage of the site where one is set up, or else into its uploads folder. --- # Chat and moderation Address: https://stream.wordplus.cloud/docs/chat/ Each stream can have a chat beside the player, below it, or anywhere on the page as a block of its own ([Putting a stream on a page](https://stream.wordplus.cloud/docs/on-a-page/)). ## Which chat In **Live Stream → Studio → Streams**, each stream chooses its chat: - **Better Messages chat room**, with Better Messages 3.1 or later: the chat is a [Better Messages](https://www.better-messages.com/) chat room made for the stream. Its messages are saved on your site, with history and export, files, GIFs and stickers, and the moderation and notifications of Better Messages. Visitors chat as guests on a public stream. Who writes, guests, files and moderators are settings of the room, under **Better Messages → Chat Rooms**. The room shows wherever the chat of the stream does, and in the studio. A new stream gets one where Better Messages runs its WebSocket version with an active licence: its free version has no realtime connection, so every viewer would keep asking your site for new messages. The stream shows in its room too, the way a group video call does: beside the messages of the room, wherever Better Messages shows the room. It opens by itself while the stream is live, and a **Live** banner over the messages and a button in the header of the room bring it back once closed. Viewers have the controls of the player among those of the call: sound, the volume and the quality of the picture under **Settings**, reactions, picture-in-picture and full screen. A viewer who closes the stream is not counted as watching until they open it again. Hosts go live right from the room: the button opens their preview, with the camera, microphone, screen sharing, **Go live** and **End stream** in the controls of the call. While live, how the picture goes out and how many watch show where a call shows its connection, the numbers under **Settings**, and a summary once it ends. Streaming from OBS stays in **Live Stream → Studio**. This needs Better Messages 3.1 or later, and its docs describe it from its side: [Live streaming in chat rooms](https://www.better-messages.com/docs/websocket/live-streaming/). **Always on screen in the room**, a setting of the stream, keeps it beside the messages of the room while it is live: viewers cannot close it. The room editor of Better Messages (**Better Messages → Chat Rooms**) has a **Live streaming** section too: **Stream in this room** makes a stream for a room that has none (named after it, the room its chat), and the stream of a room shows **Go live**, **Stream settings**, **Always on screen in the room** and **Stop streaming here** (the stream keeps a light chat). - **Light chat:** text and emoji for the moment, run by WordPlus Cloud. It is not saved: messages are gone a day after the last one. The rest of this page is about it. - **No chat.** Reactions come with every choice. ## Who writes Logged-in users write in the chat. Visitors who are not logged in read it and get **Log in to chat**, which brings them back to the stream after logging in, unless the stream lets them write too, as "Guest". ## The chat settings of a stream With the light chat, each stream has these: | Setting | What it does | |---|---| | **Visitors may write** | Visitors who are not logged in write too, as "Guest". | | **While not live** | Keeps the chat open before the stream starts and after it ends. Otherwise only moderators write then: others read "The chat opens when the stream goes live" or "The chat closed when the stream ended". | | **Links** | Lets everyone post links. Otherwise only moderators can, which keeps spam out. | | **Start empty** | Clears the chat each time the stream goes live. Otherwise it goes on from the last time. | | **Who is here** | Shown to moderators, or to everyone. | | **Moderators** | Roles that moderate the chat of this stream, besides its hosts and those who moderate the comments of the site. | ## In the chat - **Who is who:** each message shows the name and avatar of its sender, with **Host** or **Guest** beside it. Messages that mention you stand out. - **Times:** the time of each message shows on hover, or beside it where the Appearance tab says so. - **Links** open safely. - **New messages:** scrolled up to read, you get a "new messages" note instead of a jump. - **Length:** up to 500 characters, with a counter near the limit. - **Emoji:** an emoji picker beside the field, and emoji drawn in the style of the site (below). ### Reactions Under the player, viewers send **Heart**, **Applause**, **Laughter**, **Surprise** or **Fire** with one tap, and they rise over the picture. The Appearance tab chooses which are offered and whether they rise over the picture. They stay still for visitors whose device asks for reduced motion. The **Reactions** setting of each stream turns them off, during the stream too, if viewers start to spam them: the buttons go at once for everyone watching, and nothing more rises over the picture until you turn them on again. ### Emoji style The **Emoji style** in the Appearance tab is **Native**, the emoji of each device, or Apple, Google, Twitter or Facebook images, the same on every device. Choosing a set downloads its images to your site at once, and the preview beside the settings draws it before you save. Better Messages shares this choice, so both plugins draw emoji alike. With a set chosen, the chat field draws emoji in it too, typed, picked or pasted. ## Who is here The people button in the header of the chat shows the logged-in people watching or on the stream, with their names, avatars and roles, hosts first, and how many visitors besides. Moderators always see it, and everyone does where the **Who is here** setting of the stream says so. ## Moderating Moderators are the hosts of the stream, the comment moderators of the site, and the roles the stream names. Each message has a menu for them, and so does each person in **Who is here**: - **Pin message** holds it over the chat for everyone, and **Unpin message** takes it down. Deleting a pinned message unpins it. - **Delete message** removes it for everyone. - **Mute** keeps someone from writing for **1 minute**, **10 minutes**, **an hour** or **a day**, and tells them when they can write again. **Unmute** lets them write at once. - **Remove from the stream** puts them out now. They read "A moderator removed you from this stream" and can join again. - **Ban from this stream** keeps them out of the stream and its chat until a moderator lets them back. The banned are listed under **Who is here** for moderators, each with **Let back**. Hosts cannot be muted, removed or banned. ![The menu of a moderator on a message: pin, delete, mute for a minute, ten minutes, an hour or a day, remove from the stream, ban](https://stream.wordplus.cloud/img/shots/chat-moderation.webp) ### Chat settings The sliders button in the header of the chat, for moderators: - **Slow mode:** off, or one message every 5, 10, 30 or 60 seconds. Writers see the wait on the Send button. - **Clear the chat:** every message goes, the pinned one too, for everyone. This cannot be undone. Moderators can also moderate the chat of a stream after it has ended. --- # Putting a stream on a page Address: https://stream.wordplus.cloud/docs/on-a-page/ A stream shows on any page, post or template: with the **Live stream** block, with the blocks of the stream laid out as you like, or with shortcodes for page builders, widgets and themes. ## Create a page The quickest way: in **Live Stream → Studio**, press **Create a page** beside a stream that no page shows yet. Live Stream publishes a page with the stream on it, wide, the chat beside the player, and the Live now list links to it. The **Stream** tab in the studio of the stream offers the same. ## The Live stream block Add the **Live stream** block and choose the stream. Administrators can also make a new one right there. Then choose how it is laid out: | Layout | What it shows | |---|---| | **Chat beside** | The player and its details, with the chat beside them, or under them on a phone. | | **Chat below** | The player, its details, then the chat, in one column. | | **Player only** | The player and its details, without the chat. | | **Vertical video** | An upright player, as from a phone, with the chat beside it. | | **With blocks** | The player, the details and the chat as blocks of their own, in columns to move and change. | **Lay it out with blocks** turns a ready layout into the blocks of the stream, which you can move, change, and mix with any other block. **Use a ready layout instead** goes back. **Width:** a new Live stream block starts wide, so the chat has room beside the player. Its **Width** setting (the same as Align in the toolbar of the block) is the width of the content, wide, or the full width of the window, where your theme has wide blocks. The editor draws every block with the player itself, as visitors will see it, with the title, cover and planned start of the stream and the look of your site. The toolbar of the block switches between the moments (before it starts, live, after it ends) and between the view of a viewer and that of the host. ## The blocks of a stream Each part of a stream is a block of its own, inside a Live stream block or anywhere on its own (then it asks which stream). The parts of one stream on a page share one connection. | Block | What it shows | Its choices | |---|---|---| | **Stream player** | The picture and its controls, the countdown before the start and the screen after the end. | Shape: automatic, taking the shape of the picture, or fixed at 16:9, 4:3 or 9:16. The time on air (shown, hidden, or as the appearance of the site), and keeping the picture in sight at the top of the screen of a phone while live. | | **Stream chat** | The chat, with its moderation. | Its height, 240 to 1200 pixels. Without one, as tall as the player beside it, or the chat height of the site under it. | | **Stream details** | The title, when it started and how many watch, with reactions and sharing. | Each of the three shown or not. | | **Stream studio** | The controls for going live from this page. Only the hosts of the stream see them, and everyone else sees nothing. | None. | In a **Row** block, the player and the details take the room there is and the chat the width of a sidebar beside them, wrapping under them where the row is too narrow. ## Shortcodes Every block has a shortcode, for page builders, widgets, templates, and anywhere else shortcodes work. That of each stream is shown in its settings. | Shortcode | What it shows | |---|---| | `[wordplus_stream id="12"]` | The stream in one piece: the player, and the chat beside it where there is room. Its hosts see the way to the studio over it. To go live from the page itself, add the Studio block or `[wordplus_stream_studio id="12"]` beside it. Add `layout="side"`, `"below"`, `"player"` or `"vertical"` for a ready layout. | | `[wordplus_stream_player id="12"]` | The player, which takes the shape of the picture, or one fixed with `shape="16:9"`, `"4:3"` or `"9:16"`. `clock="show"` or `"hide"`. `sticky="yes"` keeps it at the top of the screen of a phone while live. | | `[wordplus_stream_chat id="12" height="600"]` | The chat, with a height in pixels if you like. | | `[wordplus_stream_details id="12"]` | The details. `title="no"`, `meta="no"` or `actions="no"` leaves a part out. | | `[wordplus_stream_studio id="12"]` | Going live from the page, for the hosts of the stream only. | | `[wordplus_stream_live]` | The Live now list (below). | A deleted stream shows nothing, and administrators find an HTML comment saying why. ## Live now The **Live now** block, or `[wordplus_stream_live]`, lists your streams that are live right now, the latest first, each with how many watch and a link to its page. It changes the moment a stream goes live or ends, without reloading the page, and it lists only the streams each visitor may watch. | Choice | Block | Shortcode | |---|---|---| | What it lists | Streams live now, streams coming up, or both | `show="live"`, `"upcoming"` or `"both"` | | How it looks | A list, cards with the cover of each stream, or a small Live badge for a header or a menu | `display="list"`, `"cards"` or `"badge"` | | While nothing is live | "No streams are live right now", or nothing at all | `hide_when_none="yes"` hides it | The streams coming up are those with a time planned, the soonest first, each at its next time with the title of that time. **Which page it links to:** the **Live now link** of a stream, in its settings, or else the first public page found showing it. A stream that no public page shows yet is left out. ## Block patterns In the **Live Stream** patterns of the block inserter, a page starts from one of these: **Live event**, **Webinar**, **Vertical stream** and **Go live on the page**. ## Who can watch The **Who can watch** setting of each stream: - **Everyone:** anyone with the page, logged in or not. - **Logged-in users.** - **Selected roles.** With none chosen, every logged-in user. Membership plugins can narrow it further with the `wordplus_stream_can_watch` filter, which gets the answer of the stream itself, its rules and the ID of the user, and returns whether that user may watch. The hosts of the stream can always watch. ```php add_filter( 'wordplus_stream_can_watch', function ( $can, $rules, $user_id ) { // Your membership check here. return $can && my_membership_is_active( $user_id ); }, 10, 3 ); ``` ## A schedule Give a stream a time in its **Schedule** setting, and until a host goes live its player shows: - The cover, that of the stream or the one set in the Appearance tab. - "The stream starts soon", with a countdown to the start and its date and time. - **Add to calendar**, for Google Calendar, or a calendar file for Apple Calendar and Outlook. ![The page of a scheduled stream: the countdown over the cover of the stream, with a line of its own and Add to calendar, and the chat open beside it](https://stream.wordplus.cloud/img/shots/countdown.webp) ### A show that goes live again and again A stream can have many times planned, like a trading room every weekday or a weekly Q&A. It keeps one page, one OBS key and one chat, so there is nothing to change between times. - **A title for each time:** give a time its own title, such as "Weekly Q&A, No. 12", and the player and the countdown say it. Without one, the title of the stream. - **Add a time** adds one a day after the last, and **Repeat these weekly** copies every time on for the weeks you choose. - **After a time ends,** viewers see the thanks with the next time under it, then after 15 minutes the countdown to the next time. After the last one, the stream says it has ended. - **A late host:** a time stays the next one until 12 hours after its start, and its viewers see "Starting any moment now". After that it is gone from the schedule. - **Going live any time:** a host can go live without a time planned, or early. Going live up to an hour before a time counts as that time. The Studio list says the next time with its title, and how many more are planned. An automation can plan the times for you ([From an automation](https://stream.wordplus.cloud/docs/developers/javascript/#automation)). ## Page caching The page of a public stream carries what a visitor needs to join, so a page cache can serve it and a crowd of viewers does not mean a crowd of requests to WordPress. --- # Appearance Address: https://stream.wordplus.cloud/docs/appearance/ **Live Stream → Studio → Appearance** sets how every stream on the site looks. A preview beside the settings is drawn by the player itself, and changes as you do: switch it between the moments (**Before**, **Live**, **Ended**), between the view of a **Viewer** and that of the **Host**, and between a **Wide** screen and a **Phone**, or press **Full size** to see it as large as a wide page shows it. On a smaller screen the preview sits above the settings. Press **Save changes** to keep what you set, or **Reset all to defaults** to start over. ![The Appearance tab: theme, accent colour, Live badge, corners and font, beside a live preview of the player and its chat](https://stream.wordplus.cloud/img/shots/appearance.webp) ## Colours and type | Setting | Choices | |---|---| | **Theme** | Light, Dark, or Automatic: light or dark as the device of each visitor is set. Dark paints a card of its own around the player. | | **Accent color** | Buttons and highlights. | | **Live badge color** | The colour of the badge on the picture while a stream is live. | | **Corners** | How round the player, the chat and the buttons are. | | **Font** | **Site font**, as the theme sets it, or **Device font**, that of the phone or computer each visitor uses. | The video itself always sits on black. ## Player The player takes the shape of the picture as it arrives: wide for cameras, screens and OBS, standard for a 4:3 camera, and upright for a phone held upright. With guests on stage beside the host it stays wide. | Setting | Choices | |---|---| | **Live badge** | The Live badge on the picture while a stream is live, shown or left out. | | **Title** | The title of the stream under the player. | | **Time on air** | How long the stream has been live, in the controls of the player. | | **Viewer count** | Shows everyone how many are watching. Hosts always see it. | | **Logo** | Your logo over the picture, with its size and opacity, from 1% to fully solid. Its size and place are shares of the picture, so it covers the same part of it in every player, whatever its size, in full screen too. In the preview, drag it to place it and pull its round handle to size it, or choose its size, its corner and its distance from the sides of that corner, each in per cent of the picture. In the studio, before you go live, you can drag and size it over your own camera or screen, and it is saved for every stream. A PNG or SVG with a see-through background looks best. | | **Cover** | Shown before a stream starts and after it ends. A stream can have its own, in its settings. | A **Stream player** block can fix a shape of its own, which keeps the player the same size whatever arrives, and its own time on air ([Putting a stream on a page](https://stream.wordplus.cloud/docs/on-a-page/)). ## Chat | Setting | Choices | |---|---| | **Position** | Beside the stream, as tall as the player and below it on narrow screens, or below the stream. | | **Height** | Of the chat below the stream, and on narrow screens. | | **Avatars** | The picture of each sender beside their messages. | | **Times** | When each message was sent, beside its sender. Otherwise it shows on hover. | | **Emoji picker** | The emoji button beside the chat field. | | **Emoji style** | **Native**, the emoji of each device, or Apple, Google, Twitter or Facebook images, the same on every device, each shown with a sample of its emoji. The images of a set are downloaded to your site as you choose it, and the preview draws the stream with them before you save. Better Messages shares this choice. | ## Reactions | Setting | Choices | |---|---| | **Offered** | The emoji viewers can send with one tap: any emoji, up to 12, added one at a time with **Add a reaction** from the emoji picker, removed with their **×**, and dragged into the order they show in. A new site offers ❤️ 👏 😂 😮 🔥. None leaves reactions out. They show in the emoji style of the site. | | **Over the picture** | Reactions rise over the stream as they come. Only the ones offered rise, whatever a viewer tries to send. | ## Your own CSS There is no CSS box of its own: restyle streams with the **Additional CSS** of WordPress (in the Customizer, or in the Styles of the Site Editor with a block theme), or in the stylesheet of your theme. Every class starts with `wplus-live-stream-`, and every colour is a CSS custom property starting with `--wplus-live-stream-`. Up to version 0.1.9 the prefix was `estream-`: CSS written for those keeps working once each `estream-` in it reads `wplus-live-stream-`. --- # Translations Address: https://stream.wordplus.cloud/docs/translations/ Every word Live Stream shows goes through WordPress translations: the admin, the blocks, the player, the chat and the studio. Your visitors read them in the language of your site, and plurals follow the rules of each language. ## How it is translated - **The text domain** is `wordplus-live-stream`, for the PHP and for the scripts alike. - **The scripts** (the player, the studio, the admin and the blocks) take their words from the `.mo` file of the plugin too: as a page shows one, Live Stream translates the words it needs in PHP and hands them to the browser in a small script it caches in `wp-content/uploads/wordplus-stream/i18n/`. There are no separate JSON files to make. - **The plugin ships its template**, `languages/wordplus-live-stream.pot`, with every word in it. ## Translating it yourself Live Stream is on WordPress.org, so its translations are made by volunteers on [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/wordplus-live-stream/), and WordPress installs the language pack of your site by itself once a language is translated far enough. Help translate it there, or translate it for your own site with a translation plugin, or with the POT file and your own tools: 1. Make a `.po` file for your language from `languages/wordplus-live-stream.pot` and translate it. 2. Compile it to `wordplus-live-stream-.mo`, such as `wordplus-live-stream-de_DE.mo`. 3. Put the `.mo` in `wp-content/languages/plugins/`. The scripts take their words from it too. Visitors see the language of the site. In the admin, each user sees the language set in their profile. --- # Viewers and credits Address: https://stream.wordplus.cloud/docs/viewers-and-credits/ The streams of each site are **unmetered up to 50 viewers at once**, however long they watch. Only the viewers above that take credits: **one credit for each minute a viewer watches**, in HD or Full HD alike. A stream has no limit of viewers at once. - **Unmetered:** up to 50 viewers at once on each site, across all its live streams. - **Included:** each WordPress site adds **5,000 credits a month** to its WordPlus Cloud account, and every site of the account draws on them. - **Who counts:** the audience, while the stream is live. The hosts count for nothing, and neither does waiting for the start. - **Recording:** a stream being recorded takes 1 credit a minute besides ([Recording and replays](https://stream.wordplus.cloud/docs/recording/)). - **More:** buy credits on [WordPlus Cloud](https://www.wordplus.cloud/pricing). Bought credits are spent after those of the month, and never expire while you have a subscription. - **When they run out:** an account may borrow up to a month of its credits ahead. Past that, viewers within the 50 still join, and those above them wait until credits are bought. Those watching are never cut off. - **Where to see it:** the licence details in the header of **Live Stream → Studio** show the viewers you stream to unmetered, the credits left, and what is borrowed. ## Your credits in the admin The licence details in the header of every **Live Stream** screen show the credits of your WordPlus Cloud account: those left, those from the plan this month, those bought, what is borrowed from next month and what can still be borrowed, with **Buy credits**. While all of them are used up, a notice on the Dashboard, the Plugins screen and the screens of Live Stream says so, until credits are bought or the next month adds its own. Those who may buy credits see it, and can dismiss it. --- # The beta Address: https://stream.wordplus.cloud/docs/beta/ Live Stream is in beta: it works, and it still changes. The header of **Live Stream → Studio** says so. In your Plugins list it is called WordPlus Live Stream, its name on [WordPress.org](https://wordpress.org/plugins/wordplus-live-stream/). What streaming costs is not a beta matter: see [Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/). ## What is not there yet These are planned, with no dates yet: - Streaming in over RTMP (OBS and other encoders stream over WHIP today). ## Telling us what you think Write to us from **Live Stream → Support** in your WordPress admin, which sends your message with the details of the site, or through [WordPlus Cloud](https://www.wordplus.cloud/contact). --- # Changelog Address: https://stream.wordplus.cloud/docs/changelog/ What each release of Live Stream changed, newest first. The versions up to 0.1.9 were betas, offered from WordPlus Cloud before Live Stream came to WordPress.org. ## Live Stream 0.2.0 * The first version on WordPress.org. * A test stream without a subscription. Start it in the studio and watch it on the page of the stream in another tab of the same browser, as your viewers will see it. Only you can see it, and nothing of it leaves your computer. * Background blur, background pictures and AI noise removal for hosts, in the studio and in a Better Messages chat room. An administrator downloads them under Appearance → Studio effects. * Recording and replays: record a stream from the studio, or every time it goes live, for a credit a minute, and its page plays the recording with captions and a transcript after it ends. * The build from WordPlus Cloud takes the translations of Live Stream on translate.wordpress.org, as WordPress updates them. * While the credits of your account are used up, a notice says so on the Dashboard, the Plugins screen and the screens of Live Stream, until they are back. * The build from WordPress.org and the build from WordPlus Cloud can both be installed on one site. The second stays inactive and says which one runs, and deleting one keeps the streams and settings for the other. * No invitation to share usage data any more. * The CSS classes of the player, the chat and the studio start with `wplus-live-stream-` in place of `estream-`. Check any CSS of your own that styles them. * The licences of the code a script bundles are at the top of that script. * For developers: `wordplus_streams()->config()` gives the hosts of a stream its config on a site without a licence too, for a test stream. ## Live Stream 0.1.9 * Every picture a host sends goes out in several sizes, so each viewer gets the size their connection can take. As the stream goes live, the camera is checked and sends in H.264 when the computer keeps up with it, then VP9, then VP8. * On a good connection a viewer waits one second for the picture, and on a connection that loses video on the way up to three seconds, so the picture freezes less. It comes back down after five minutes without trouble, and the sound stays with the picture. The player Statistics show each change as Buffer. * The player tells WordPlus Cloud how the stream plays for each viewer, so a stream that stutters can be traced to the host, the servers or the viewer. * The round trip in the player Statistics is that of the connection the player is using. * The words of the player, the admin and the blocks are translated with each word written out in the PHP of the plugin, as WordPress.org asks. ## Live Stream 0.1.8 * Viewers who come back to a stream from another tab or a minimized window see the picture move at once, not a few seconds later. While the page is hidden, a computer keeps receiving the picture at its smallest size, and it is sharp again within seconds of coming back. A phone or tablet, a stream with 50 viewers or more, and a picture sent without a small size, such as one from OBS, pause it as before. WordPlus Cloud sets the number of viewers, and pages already open follow it. ## Live Stream 0.1.7 * The Pricing page buys the plan at the checkout of Live Stream, not of Better Messages. * On the Pricing page, the number of viewers has an icon of its own. ## Live Stream 0.1.6 * Full screen on a computer fills the browser window, not the whole screen. Escape or the button leaves it. * On an iPhone, Full screen fills the window with the player controls and the chat, not the iPhone video player with the picture alone. * On a phone in full screen, the picture takes the whole width, with the chat under it when held upright and beside it when held sideways. Hide chat gives the picture the whole screen. * Hide chat and Show chat on the player also work for a Chat block of its own, on the page and in full screen. In a Row, the player then takes the whole width. * After a stream ends in full screen, Exit full screen stays on the screen. * A Better Messages chat room beside the stream opens and closes again on a phone. ## Live Stream 0.1.5 * A schedule for a stream that goes live again and again, like a weekly show. Plan its times, each with a title of its own if you like, add a time a day after the last, or repeat them weekly. It keeps one page, one OBS key and one chat. Viewers see the countdown to the next time with its title, and after a time ends, the thanks with the next time under them. * An automation can plan the times of a stream over REST, signed in with an application password. * The logo keeps its place and size on the picture in every player, at any size and in full screen. Before going live, drag and size it over your own camera or screen in the studio. Check the place of your logo after updating. * An ended stream no longer hides a start planned after it. * The studio says when OBS stopped sending, and that the stream ends by itself after 5 minutes unless OBS comes back. * On Auto, a viewer of OBS sending two layers gets the layer their player needs, not always the largest. * A viewer whose connection is too slow for the picture keeps clear sound. The player says so over the last picture and tries the picture again by itself, or at once with Try again. * Without a licence, everything on the site works. The studio sets up the camera, microphone and screen, with Connect to go live in place of Go live. * An Upgrade page with the plans of WordPlus Cloud. * The admin works on a phone, and a player and chat side by side wrap on a phone. * A Better Messages chat room beside the stream is as tall as the picture in full screen. * Named WordPlus Live Stream. ## Live Stream 0.1.4 * The picture of a stream comes sooner for viewers coming in. The video connects to the media server at once, and its part of the player loads while the chat connects. * The studio says when OBS sends its keyframes far apart, which each viewer coming in or back to the page waits for, and what to set in OBS. * The OBS steps in the studio say where Keyframe Interval is, in the Advanced output mode of OBS, and set it to 1 second, with Max B-frames at 0 and the video encoder of the Simple mode. * The studio says when the picture from OBS arrives at fewer frames a second than it should, which B-frames or an encoder that cannot keep up cause, and what to set. * The OBS steps end saying their numbers are a starting point, to try on your own stream and connection from another device. * A studio reloaded while live from OBS shows OBS again, with what arrives from it, and not the camera. * Original sound, for music: the microphone as it hears, with no echo or noise removal, at 128 kbps. Turn it on in the setup before going live, or choose it in the menu of the microphone. ## Live Stream 0.1.3 * A stream can go live on its own as soon as OBS connects, with nobody in the studio. Turn on Go live when OBS connects in its settings. It stays live through a short break of OBS while anyone watches, and goes live again when OBS is back. * OBS can take a stream that has ended live again, once Stream from OBS is chosen in its studio. * The OBS steps in the studio say to set Total Layers to 3 where OBS has it, so viewers on slow connections get a smaller copy, and suggest Full HD with it. * The controls of the player stay while the mouse rests on them. * The plugin names itself and its version to the media server, as Better Messages does. * The Live now list follows its streams over the connection the page already holds, where it opened one of its own. * The plugin reaches the cloud under the name Live Stream. Sites on earlier versions keep working as they are. * The WordPlus SDK with the newest realtime client. ## Live Stream 0.1.2 * A host sharing a screen with its sound is heard once. A page of the stream open beside the studio no longer plays the host back, and the sound of the screen is taken without the sound of the page itself. * A shared screen in H.264 goes out in three sizes, so each viewer gets the largest their screen and connection take, and on sharp screens, a Mac with Retina among them, a player of ordinary size shows it in Full HD. * The logo can be placed exactly. Drag it in the preview of the Appearance tab, or set its corner and its distance from that corner. * The logo can be sized by pulling its round handle in the preview, shown when the logo is hovered, and its opacity goes down to 1%. * The Appearance tab lists its settings in one column, with the settings of the logo grouped under it. * Where the site hides the viewer count, only the hosts and moderators of a stream receive it. * In the layouts of the block with the chat beside or below the player, the player hides and shows the chat, and takes the whole width while it is hidden. * A Better Messages chat room beside the stream comes into the full screen of the player in every layout of the block, dark there and meeting the edges of the screen, with no buttons that lead away from the stream. * A page of the stream open in another tab of the host shows the picture as soon as the stream goes live from the studio, where it waited for a reload. * The plugin shows its own icon in the updates of WordPress. * The WordPlus SDK 1.0.3, and the newest WordPlus Mesh client, which reconnects to the same server first after a short drop. ## Live Stream 0.1.1 * A shared screen fills the player, with the camera of the host in its corner, where the camera stood in a narrow strip beside a smaller screen. * The host drags that camera anywhere over the screen, or moves it with the arrow keys, and viewers see it where it is put. * The camera goes out in H.264 from the hardware of the computer where it has an encoder, Chrome on a Mac among them, else in VP9, with VP8 behind it for viewers whose browsers take neither. * A shared screen goes out smoother, as moving pictures that keep their size, in one picture in VP8 and with a smaller second one in H.264 for viewers on slow connections. * The studio starts at 1080p, Full HD, where the plan allows it, until the host chooses HD. * The picture of the host stays on screen as the stream goes live, where it blinked. * The WordPlus SDK 1.0.2, with Check now for updates on the Licence page, the browser named in messages sent from the Support page, and the newest copy of the SDK loaded where several plugins carry it. ## Live Stream 0.1.0 * The first beta, under the working name Live Stream. * Streams configured on the Streams tab, and going live from Live Stream → Studio, from the browser or from OBS. * The Live stream block with ready layouts, and the blocks of the stream and shortcodes (the player, the chat, the details, the studio), drawn in the editor as on the page. * Who watches, the player, the chat and its moderation, and words of its own in each stream for viewers before, during and after it. * A player that takes the shape of the picture, with the picture quality by the sizes the stream sends, statistics that show why a stream plays badly and copy it all for a support request, a spinner while the picture stops, and a notice while a viewer is offline. * Statistics for the host too, from the studio while live: each size the camera or screen goes out in, what holds it back, the sound and the connection. * The player from the keyboard alone, its keys listed with ?, and each moment of a stream said by screen readers. * Reactions are any emoji you choose, in the emoji style of the site, and the Appearance tab shows a sample of each style and previews the stream in the one chosen before it is saved. * The buttons of the stream keep their own colours on themes that colour every button under the pointer or in focus. * The chat of a stream can be a Better Messages chat room, beside the stream and in the studio, with history and export. The stream shows in its Better Messages room too, which the room editor of Better Messages can start, with the controls of a Better Messages call: the chat shown or hidden beside it, and the rest in a More menu where the room is narrow. * A host who reloads the studio while live sends again by itself, and the studio asks before a host leaves it while live, from its tabs and links too. * The Live now block with the streams coming up, block patterns, the Appearance tab and the WordPlus Cloud licence. * For developers, under names that stay whatever the plugin is called: wordplus_streams() to make, find and show streams of members and streams made for the groups, courses or events of other plugins, wordplus_stream hooks for who hosts, watches, chats, moderates and makes streams and where streams are watched, actions as streams go live and end, with how many watched, and as they are made, changed and deleted, actions as members start and stop watching, with how long they watched, the streams live now, REST routes, and window.wordplusStreams to show a stream, make one from a Go live button and hear it go live and end. --- # FAQ Address: https://stream.wordplus.cloud/docs/faq/ ## Getting it ### What does Live Stream need? WordPress 6.0 or later, PHP 7.4 or later, and a [WordPlus Cloud](https://www.wordplus.cloud) subscription that includes live streaming. Hosts going live from the browser need the site on HTTPS. See [Getting started](https://stream.wordplus.cloud/docs/). ### Where do I download it? In your WordPress admin, under **Plugins → Add New Plugin**: search for **WordPlus Live Stream**, its name on [WordPress.org](https://wordpress.org/plugins/wordplus-live-stream/). Or [download the zip](https://www.wordplus.cloud/download/live-stream) of version 0.2.0 and upload it there. ### Can I try it before I subscribe? Yes. Everything on your site works without a subscription. In Live Stream → Studio, turn on your camera and choose Start a test stream, then Watch it as viewers do. The page of the stream opens in another tab of the same browser and shows your stream as your viewers will see it, with its chat. Only you can see a test stream, and nothing of it leaves your computer. To go live for everyone, connect the site to WordPlus Cloud. See [A test stream](https://stream.wordplus.cloud/docs/going-live/#test-stream). ### How much does it cost? The plugin comes with a [WordPlus Cloud](https://www.wordplus.cloud) subscription, which streams to 50 viewers at once on each site unmetered, however long they watch. Above that, each viewer takes a credit a minute, while hosts take none. Each WordPress site adds 5,000 credits a month to its account, and more are on the [pricing page of WordPlus Cloud](https://www.wordplus.cloud/pricing). See [Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/). ### My site runs Better Messages. Is it connected already? Yes, if Better Messages runs its WebSocket version with an active licence: Live Stream uses the same licence, a Better Messages WebSocket licence or a WordPlus Cloud subscription. The header of **Live Stream → Studio** says where the site stands. ### Does it need Better Messages? No. Live Stream is a plugin of its own and works without Better Messages, with its light chat. With Better Messages 3.1 or later, the chat of a stream can be a Better Messages chat room instead, saved on your site with history and export ([Which chat](https://stream.wordplus.cloud/docs/chat/#which-chat)). The two also share the emoji style. ## Streaming ### Where does the video go? To the servers of WordPlus Cloud, which pass it on to everyone watching, with the chat. Your WordPress server does not carry the video. ### How many people can watch? As many as come: a stream has no limit of viewers at once. The first 50 at once on each site are unmetered. Above that, each minute a viewer watches takes a credit, and each WordPress site adds 5,000 credits a month to its WordPlus Cloud account. See [Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/). ### Do viewers need an app? No. They watch in the browser, on the page that shows the stream. ### What quality does a stream go out in? HD (720p) or Full HD (1080p). The host chooses before going live, and each viewer gets what the size of their player and their connection need. See [Quality](https://stream.wordplus.cloud/docs/going-live/#quality). ### Can I stream from OBS? Yes, from OBS 30 or later or any encoder that streams over WHIP. See [Streaming from OBS](https://stream.wordplus.cloud/docs/obs/). ### Can I stream with RTMP? Not yet. OBS and other encoders stream in over WHIP. RTMP is planned. ### Can I record a stream, or play it back later? Yes. A stream can be recorded while live, and its page plays the replay after it ends. See [Recording and replays](https://stream.wordplus.cloud/docs/recording/). ### Can I blur my background? Yes, when you go live from the browser: blur the room behind you, put a picture there, and remove the noise around your voice with AI noise removal. It all runs in your own browser. See [Background blur, backgrounds and noise removal](https://stream.wordplus.cloud/docs/effects/). ### Can hosts go live without being administrators? Not yet: administrators host every stream. ### Can more than one person be on camera? Not in the first release: the host is the one on camera. Bringing viewers on stage with their own camera and microphone comes later. ## Your site ### Can a stream be private? Yes. Each stream is for everyone, for logged-in users, or for chosen roles, and membership plugins can decide with the `wordplus_stream_can_watch` filter. See [Who can watch](https://stream.wordplus.cloud/docs/on-a-page/#who-can-watch). ### Can I put the chat in a sidebar? Yes. Use the **Stream chat** block or `[wordplus_stream_chat id="12"]` wherever you like. Beside the player it is as tall as the player, and elsewhere it takes the height you choose. ### Does it work with page builders? Every block has a shortcode, which works wherever shortcodes do: page builders, widgets and templates. See [Shortcodes](https://stream.wordplus.cloud/docs/on-a-page/#shortcodes). ### Does it work with page caching? Yes. The page of a public stream carries what a visitor needs to join, so a cached page works. ### How do I show which streams are live? With the **Live now** block or `[wordplus_stream_live]`. See [Live now](https://stream.wordplus.cloud/docs/on-a-page/#live-now). ### Is it translated? Every word goes through WordPress translations, with the `wordplus-live-stream` text domain. See [Translations](https://stream.wordplus.cloud/docs/translations/). --- # Live streams in your plugin Address: https://stream.wordplus.cloud/docs/developers/ Live streaming anywhere on a site: your plugin can let every member go live, give each of its groups, courses, events or rooms a stream of its own, put a post in a feed while someone is live, and show any stream on its own screens, with your rules for who goes live and who watches. Live Stream shows its streams in the chat rooms of Better Messages the way they show a group call ([Chat](https://stream.wordplus.cloud/docs/chat/)), and your plugin can do the same. ## What you can build - **Streams of your users.** Every member, or those you choose, goes live in a stream of their own, which they host, from a page or a screen of yours: made in PHP, or from the browser with a **Go live** button. - **A stream for each thing of yours.** Make, change and delete streams from PHP, each one made for a thing of your plugin, and find it again by that thing. - **Live posts and notices.** PHP actions as a stream goes live and ends, for a post in a feed while a member is live, a notice to their followers, or how long it lasted. - **The stream on your screens.** In one piece, in a ready layout, or in parts (the player, the chat, the studio, the details), from PHP or from JavaScript, and shared and listed as live from the page you say it is watched on. - **Your rules.** Who hosts each stream, who watches it, who writes in its chat and who moderates it, and who makes streams of their own. - **Going live where your people are.** Hosts go live from the studio you put on your pages, with no access to the WordPress admin. - **What is live.** In PHP, and in the browser the moment a stream goes live or ends, with how many watch. ## The pieces | Piece | What it is for | |---|---| | [PHP](https://stream.wordplus.cloud/docs/developers/php/) | Making streams, of your users or for things of yours, and finding them, showing them, asking who may do what and what is live. | | [Hooks](https://stream.wordplus.cloud/docs/developers/hooks/) | Your rules for who hosts, watches, chats, moderates and makes streams, and where streams are watched. Actions as streams go live and end, and as they are made, changed and deleted. | | [JavaScript](https://stream.wordplus.cloud/docs/developers/javascript/) | Showing a stream from your script, a **Go live** button that makes a stream of the user, and hearing when a stream goes live or ends, how many watch and its messages. | | [REST](https://stream.wordplus.cloud/docs/developers/javascript/#rest) | The config of a stream, for a screen drawn in the browser, and the streams of a user. | Two whole plugins built on them, each about 100 lines: [members going live](https://stream.wordplus.cloud/docs/developers/members/), with a post up while they are live, and [live events](https://stream.wordplus.cloud/docs/developers/example/), each with a stream its organiser hosts and the people going watch. ## Start Live Stream may be missing or turned off on a site, so check that it is there once plugins have loaded: ```php add_action( 'plugins_loaded', function () { if ( ! function_exists( 'wordplus_streams' ) ) { return; // No live streams on this site. } // Your integration. } ); ``` `wordplus_streams()->can_stream()` says whether the site can stream: it has its licence, and the licence includes live streaming. Leave your own **Go live** buttons out until it does. ## A stream for a thing of yours ```php $stream_id = wordplus_streams()->create( array( 'title' => 'Weekly class', 'object_type' => 'my_course', 'object_id' => 42, 'settings' => array( 'access' => 'logged_in', 'chat_with' => 'light' ), ) ); // Later, on the page of the course. $stream = wordplus_streams()->get_object_stream( 'my_course', 42 ); if ( $stream ) { echo wordplus_streams()->render( $stream['id'], array( 'layout' => 'side' ) ); } ``` It is a stream like any other: administrators find it in **Live Stream → Studio**, change its settings there, and go live in it. Your hooks decide who else does ([Hooks](https://stream.wordplus.cloud/docs/developers/hooks/)). ## Names Everything you build on is named for WordPlus, which makes Live Stream, so it stays whatever the plugin is called: | | | |---|---| | PHP | `wordplus_streams()` | | Hooks | `wordplus_stream_…`, as `wordplus_stream_live` | | Script handles | `wordplus-streams`, `wordplus-streams-live` | | JavaScript | `window.wordplusStreams` | | REST | `/wp-json/wordplus/v1/streams` | ## Viewers The viewers of the streams on your screens are viewers of the site, as on any page, and those of your members too: every stream of the site shares its unmetered viewers and its credits ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). ## In the beta Live Stream is in beta, and so is what you build on. Tell us what you build and what you miss: [contact us](https://www.wordplus.cloud/contact). --- # PHP Address: https://stream.wordplus.cloud/docs/developers/php/ Everything here is a method of `wordplus_streams()`, there once Live Stream has loaded. Check with `function_exists( 'wordplus_streams' )` ([Overview](https://stream.wordplus.cloud/docs/developers/#start)). ```php $streams = wordplus_streams(); $id = $streams->create( array( 'title' => 'Weekly class' ) ); echo $streams->render( $id ); ``` ## Streams ### create() ```php wordplus_streams()->create( array $args ): int|WP_Error ``` Makes a stream and answers its ID. | Argument | | |---|---| | `title` | Its title, plain text, up to 120 characters. Required. | | `settings` | The [settings](#settings) to change from those of a new stream. | | `object_type` | What it is made for: a kind of thing of your plugin, in lower case letters, digits, `_` and `-`, up to 64 characters. Prefix it with the name of your plugin, as `my_course`. | | `object_id` | And the ID of that thing, a positive number. | | `host` | The user it is the stream of, a member going live: they host it, as administrators do, and go live where you put its [studio](#render). | ```php $stream_id = wordplus_streams()->create( array( 'title' => $group->name, 'object_type' => 'my_group', 'object_id' => $group->id, 'settings' => array( 'access' => 'logged_in', 'chat_with' => 'light', 'scheduled' => strtotime( '2026-11-02 18:00:00' ), ), ) ); if ( is_wp_error( $stream_id ) ) { // wordplus_stream_no_title, or wordplus_stream_object for a wrong object_type or object_id. } ``` [`wordplus_stream_created`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_created) runs once it is made. ### update() ```php wordplus_streams()->update( int $id, array $args ): true|WP_Error ``` Changes the title, the settings given, what the stream is made for and its `host`. The settings not given stay as they are. Give an empty `object_type` and `object_id` to make it a stream of its own again, and `host` `0` for a stream of no one. Errors: `wordplus_stream_not_found`, `wordplus_stream_no_title`, `wordplus_stream_object`, `wordplus_stream_host`. ```php wordplus_streams()->update( $stream_id, array( 'settings' => array( 'reactions' => false ) ) ); ``` Turning reactions off or on tells everyone watching at once, during a stream too. [`wordplus_stream_updated`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_updated) runs after. ### delete() ```php wordplus_streams()->delete( int $id ): bool ``` Deletes a stream for good. Pages, blocks and shortcodes that showed it show nothing. Answers whether it was deleted. [`wordplus_stream_deleted`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_deleted) runs after. ### get() ```php wordplus_streams()->get( int $id ): ?array ``` A stream, or `null` when there is none with that ID: | Key | | |---|---| | `id` | Its ID on the site. | | `stream` | Its ID on the cloud, `s12`, which JavaScript names it by too. | | `title` | Its title. | | `settings` | Its [settings](#settings), all of them. | | `object_type`, `object_id` | What it was made for, `''` and `0` for nothing. | | `host` | The user it is the stream of, `0` for no one. | | `page` | Where viewers watch it, which the Live now list links to and the player shares: the page chosen in its settings, the first public page found showing it, or what [`wordplus_stream_page_url`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_page_url) says. `''` while there is none. | | `shortcode` | Its shortcode, `[wordplus_stream id="12"]`. | | `created` | When it was made, a timestamp. | ### get_object() ```php wordplus_streams()->get_object( int $id ): ?array ``` What a stream was made for, `array( 'type' => 'my_group', 'id' => 5 )`, without the rest of it. `null` for a stream made for nothing, or no stream. Quick enough for [hooks](https://stream.wordplus.cloud/docs/developers/hooks/), which are asked often. ### get_host() ```php wordplus_streams()->get_host( int $id ): int ``` The user a stream is the stream of, `0` for no one or no stream. Quick enough for hooks, and the one to read in [`wordplus_stream_page_url`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_page_url), which `wordplus_streams()->get()` asks. ### get_object_stream() ```php wordplus_streams()->get_object_stream( string $object_type, int $object_id ): ?array ``` The stream made for a thing of yours, as `wordplus_streams()->get()` gives it, the newest when there are more. `null` for none. ### get_streams() ```php wordplus_streams()->get_streams( array $args = array() ): array ``` Streams, the newest first, each as `wordplus_streams()->get()` gives it. | Argument | | |---|---| | `object_type` | Only those made for things of this kind. | | `object_id` | With `object_type`, only those made for this thing. | | `host` | Only the streams of this user. | | `search` | Words in the title. | | `number` | How many, up to 100. 20 when not given. | | `page` | Which page of them, from 1. | ## Settings The settings of a stream, as its page in **Live Stream → Studio → Streams** has them. | Setting | | A new stream | |---|---|---| | `access` | Who watches: `public` (everyone), `logged_in`, or `roles` (those in `watch_roles`). | `public` | | `watch_roles` | The roles that watch, for `roles`. | None | | `chat` | Whether it has chat. | `true` | | `chat_with` | `light`, the chat of WordPlus Cloud, never saved, or `better_messages`, a Better Messages chat room made for it ([Chat](https://stream.wordplus.cloud/docs/chat/#which-chat)). | `better_messages` where Better Messages can show a room, otherwise `light` | | `guest_chat` | Whether visitors who are not logged in write in the light chat. | `false` | | `chat_offline` | Whether the light chat is open while the stream is not live. Its moderators always write. | `false` | | `chat_links` | Whether everyone may post links, or only moderators. | `true` | | `chat_fresh` | Whether the light chat starts empty each time the stream goes live. | `false` | | `people` | Who sees who is here: `mods` or `all`. | `mods` | | `mod_roles` | Roles that moderate it, besides its hosts and those who moderate the comments of the site. | None | | `reactions` | Whether viewers send reactions over the picture. | `true` | | `autostart` | Whether it goes live as OBS connects with its token, with nobody in the studio, and again when OBS comes back after a break ([From OBS](https://stream.wordplus.cloud/docs/obs/#going-live-on-its-own)). | `false` | | `sessions` | When it is planned to go live: a list of times, each `at` (a timestamp) and its own `title` (`''` for the title of the stream), the soonest first, at most 100. A time is the next one until 12 hours after its start, and gone after ([A schedule](https://stream.wordplus.cloud/docs/on-a-page/#a-scheduled-start)). Sent, it replaces the times planned. `at` may also be a date and time in the time zone of the site, `2026-10-26T08:15`, and a time may be its timestamp alone. | None | | `scheduled` | The start of the next time planned, a timestamp. `0` for none. Sent without `sessions`, it moves the next time, and `0` removes it. | `0` | | `cover` | The image before it starts, a URL. `''` for the cover of the site. | `''` | | `page` | The post the Live now list links to. `0` for the first public page found showing it. | `0` | | `texts` | Words of its own in place of those of the player: `soon`, `soon_note`, `waiting`, `full`, `ended`, `thanks`, `chat_before`, `chat_after`. | None | | `room_locked` | In its Better Messages chat room, whether it stays on screen while live. | `false` | A setting with a value it cannot take keeps the one it had. **A Better Messages chat room** is made for a stream when it is saved by an administrator, through Better Messages. A stream your code makes while someone else is logged in has the light chat until then. Set `chat_with` to `light` when your plugin has a chat of its own to show beside it, or none. ## On your screens ### render() ```php wordplus_streams()->render( int $id, array $args = array() ): string ``` A stream, or a part of it, as HTML for the page being made, with its script and styles. `''` when there is no such stream. ```php echo wordplus_streams()->render( $stream_id ); // In one piece. echo wordplus_streams()->render( $stream_id, array( 'layout' => 'side' ) ); // The player with the chat beside it. echo wordplus_streams()->render( $stream_id, array( 'part' => 'player', 'shape' => '9:16' ) ); ``` | `part` | What it shows | Its choices | |---|---|---| | `all` | The stream in one piece: the player, and the chat beside it where there is room. Its hosts get the way to their [studio](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_studio_url) over it, or the studio itself where they have none to go to. | `layout`: `side`, `below`, `player` or `vertical` for a ready layout of the parts below. | | `player` | The picture and its controls, the countdown before the start and the screen after the end. | `shape`: `16:9`, `4:3` or `9:16`, otherwise the shape of the picture. `sticky`: keeps it at the top of the screen of a phone while live. `clock` and `names`: shown or hidden. | | `chat` | The chat, with its moderation. | `height`: 240 to 1200 pixels. | | `studio` | Going live from the page, for the hosts of the stream. Everyone else sees nothing. | None. | | `details` | The title, when it started, how many watch, reactions and sharing. | `title`, `meta`, `actions`: each `false` to leave it out. | Each one is the block and the shortcode of the same part ([Putting a stream on a page](https://stream.wordplus.cloud/docs/on-a-page/)). The parts of one stream on a page share one connection. ### config() ```php wordplus_streams()->config( int $id, array $args = array() ): ?array ``` What `wordplusStreams.mount()` takes in the browser to show a stream or a part of it for the current user ([JavaScript](https://stream.wordplus.cloud/docs/developers/javascript/)). It takes `part` and its choices, as `wordplus_streams()->render()`, and `url`, the address of the page it is shown on, to share and to come back to after logging in. `null` when there is no such stream, or when the site has no WordPlus Cloud key yet and the current user is not one of the hosts of the stream. Its hosts get it there too, to set up their camera and watch a test stream that only they can see. ### enqueue() ```php wordplus_streams()->enqueue(): bool ``` Puts the player on the page for a script of yours that shows streams itself: its handle is `wordplus-streams`, which your script depends on. `wordplus_streams()->render()` needs none of this. ### enqueue_live() ```php wordplus_streams()->enqueue_live(): bool ``` Puts `wordplusStreams.live` on the page, which tells your script the streams live now and again each time that changes ([JavaScript](https://stream.wordplus.cloud/docs/developers/javascript/#live)): its handle is `wordplus-streams-live`. Answers `false` on a site whose licence does not include live streaming. ## Who may do what ### user_can() ```php wordplus_streams()->user_can( int $id, string $action, ?int $user_id = null ): bool ``` Whether a user may `watch`, `host`, `moderate` or `chat` (write in the light chat) in a stream, as its settings and [your hooks](https://stream.wordplus.cloud/docs/developers/hooks/) decide. `0` for a visitor, the current user when not given. ```php if ( wordplus_streams()->user_can( $stream_id, 'host' ) ) { echo wordplus_streams()->render( $stream_id, array( 'part' => 'studio' ) ); } ``` ### studio_url() ```php wordplus_streams()->studio_url( int $id, ?int $user_id = null ): string ``` Where a host goes live in a stream: **Live Stream → Studio** for administrators, or what [`wordplus_stream_studio_url`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_studio_url) says. `''` for a user who does not host it, or has nowhere to go. ## What is live ### live_streams() ```php wordplus_streams()->live_streams(): array|WP_Error ``` The streams live now, the latest first, by their IDs: ```php array( 12 => array( 'id' => 12, 'stream' => 's12', 'started' => 1793638800, 'viewers' => 31 ), ) ``` It asks WordPlus Cloud, at most once every 15 seconds, and keeps the answer for the requests between. A page a cache keeps shows what was live when it was cached: [`wordplusStreams.live`](https://stream.wordplus.cloud/docs/developers/javascript/#live) tells the page itself as it changes. An error when the licence of the site does not include live streaming (`wordplus_stream_not_licensed`), or the cloud did not answer (`wordplus_stream_no_answer`). ### is_live() ```php wordplus_streams()->is_live( int $id ): bool ``` Whether a stream is live now, as `wordplus_streams()->live_streams()` tells. `false` too when the cloud did not answer. ### can_stream() ```php wordplus_streams()->can_stream(): bool ``` Whether the site can stream: it has its licence, and the licence includes live streaming. --- # Hooks Address: https://stream.wordplus.cloud/docs/developers/hooks/ ## How a stream decides For each person and each stream, Live Stream decides in this order: 1. **Hosts:** administrators host every stream, the user a stream is the stream of hosts it (its [`host`](https://stream.wordplus.cloud/docs/developers/php/#create)), and those [`wordplus_stream_can_host`](#wordplus_stream_can_host) adds. A host goes live, moderates and writes in the chat, and is asked nothing more. 2. **Viewers:** the **Who can watch** setting of the stream, then [`wordplus_stream_can_watch`](#wordplus_stream_can_watch). 3. **The chat:** logged-in viewers write in the light chat, and visitors where the stream lets them. [`wordplus_stream_can_chat`](#wordplus_stream_can_chat) has the last word. 4. **Moderators:** those who moderate the comments of the site and the roles chosen in the stream, then [`wordplus_stream_can_moderate`](#wordplus_stream_can_moderate). What it decides goes into the grant each person joins with, which WordPlus Cloud holds them to. A page a cache keeps carries the grant of a visitor for a public stream, so a filter that keeps visitors out takes effect on the pages made after it. Filters are asked often, on each page that shows a stream and for each stream of the Live now list. Keep them quick: [`wordplus_streams()->get_object()`](https://stream.wordplus.cloud/docs/developers/php/#get_object) reads what a stream was made for without the rest of it. ## Filters ### wordplus_stream_can_host Whether a logged-in user hosts a stream. Not asked for administrators, who host every stream. ```php apply_filters( 'wordplus_stream_can_host', bool $can, int $stream_id, int $user_id ) ``` `$can` is `false`. A host goes live from the studio of the stream where your page shows it ([`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render) with `'part' => 'studio'`), or from the studio [`wordplus_stream_studio_url`](#wordplus_stream_studio_url) links them to. **Live Stream → Studio** in the admin stays for administrators. ```php // The organisers of a group host its stream. add_filter( 'wordplus_stream_can_host', function ( $can, $stream_id, $user_id ) { $group = wordplus_streams()->get_object( $stream_id ); if ( $group && 'my_group' === $group['type'] ) { return my_group_is_organiser( $group['id'], $user_id ); } return $can; }, 10, 3 ); ``` ### wordplus_stream_can_watch Whether a user may watch a stream: how membership plugins make a stream paid or for members. Not asked for its hosts. ```php apply_filters( 'wordplus_stream_can_watch', bool $can, array $rules, int $user_id, int $stream_id ) ``` `$can` is `true`, the answer of the **Who can watch** setting, which already kept out those it does not let in. `$rules` are those of the stream (`s`, its ID on the cloud, `t` its title, `a` its access). `$user_id` is `0` for a visitor. Someone kept out sees **You do not have access to this stream** in the player. ```php // Only the members of the group watch its stream. add_filter( 'wordplus_stream_can_watch', function ( $can, $rules, $user_id, $stream_id ) { $group = wordplus_streams()->get_object( $stream_id ); if ( $group && 'my_group' === $group['type'] ) { return $can && my_group_is_member( $group['id'], $user_id ); } return $can; }, 10, 4 ); ``` ### wordplus_stream_can_chat Whether a viewer writes in the light chat of a stream, or only reads it. Not asked for its hosts, who always write, nor for a stream whose chat is a Better Messages chat room, which decides that itself. ```php apply_filters( 'wordplus_stream_can_chat', bool $can, int $stream_id, int $user_id ) ``` `$can` says what the stream lets them: logged-in users write, and visitors where **Visitors may write** is on. Returning `true` for a visitor lets them write too, as "Guest". ### wordplus_stream_can_moderate Whether a logged-in viewer moderates a stream: pins and deletes messages, mutes, removes and bans people, turns on slow mode. Not asked for its hosts, who always moderate, nor for visitors. ```php apply_filters( 'wordplus_stream_can_moderate', bool $can, int $stream_id, int $user_id ) ``` `$can` is `true` for those who moderate the comments of the site and for the roles chosen in the stream. ### wordplus_stream_studio_url Where the player sends a host to go live. ```php apply_filters( 'wordplus_stream_studio_url', string $url, int $stream_id, int $user_id ) ``` `$url` is **Live Stream → Studio** for administrators, and `''` for the hosts your plugin names, who may not open the admin. With `''`, the stream in one piece carries the studio for them. Send them to the page where you put the studio: ```php add_filter( 'wordplus_stream_studio_url', function ( $url, $stream_id, $user_id ) { $group = wordplus_streams()->get_object( $stream_id ); return $group && 'my_group' === $group['type'] ? my_group_url( $group['id'] ) . 'live/' : $url; }, 10, 3 ); ``` ### wordplus_stream_page_url Where a stream is watched: the page the Live now list links to, which the player shares and puts in calendars from wherever it is shown, as in a feed. ```php apply_filters( 'wordplus_stream_page_url', string $url, int $stream_id ) ``` `$url` is the page chosen in the settings of the stream, or the first public page found showing it, `''` for none. A stream with no page is left out of the Live now list. `wordplus_streams()->get()` asks this filter for its `page`, so read the stream here with [`wordplus_streams()->get_host()`](https://stream.wordplus.cloud/docs/developers/php/#get_host) or `wordplus_streams()->get_object()`. ```php // The stream of a member is watched on their profile. add_filter( 'wordplus_stream_page_url', function ( $url, $stream_id ) { $member = wordplus_streams()->get_host( $stream_id ); return $member ? my_profile_url( $member ) : $url; }, 10, 2 ); ``` ### wordplus_stream_can_create Whether a logged-in user makes a stream of their own from the browser ([`wordplusStreams.create()`](https://stream.wordplus.cloud/docs/developers/javascript/#wordplusstreamscreate)), which they then host. ```php apply_filters( 'wordplus_stream_can_create', bool $can, int $user_id, array $args ) ``` `$can` is `true` for administrators only. `$args` are `title`, `settings`, `object_type` and `object_id`, as the browser sent them: check that what it names is theirs, a group they organise, say. ```php // Every member makes streams of their own, for nothing of yours. add_filter( 'wordplus_stream_can_create', function ( $can, $user_id, $args ) { return $can || empty( $args['object_type'] ); }, 10, 3 ); ``` ### wordplus_stream_user_settings The settings a user gives a stream of their own from the browser, before they are checked. They send only `access`, `watch_roles`, `chat`, `guest_chat`, `chat_offline`, `chat_links`, `chat_fresh`, `people`, `reactions`, `sessions`, `scheduled`, `cover` and `texts`: the Better Messages chat room, the roles that moderate and the page of the Live now list are the site to choose. ```php apply_filters( 'wordplus_stream_user_settings', array $settings, int $user_id, int $stream_id ) ``` `$stream_id` is `0` for a stream being made. Return the settings to keep: ```php // The streams of members are for logged-in users, whatever they choose. add_filter( 'wordplus_stream_user_settings', function ( $settings ) { return array( 'access' => 'logged_in' ) + $settings; } ); ``` ### wordplus_stream_can_edit Whether a user changes and deletes a stream from the browser (`wordplusStreams.update()`, `wordplusStreams.delete()`). ```php apply_filters( 'wordplus_stream_can_edit', bool $can, int $stream_id, int $user_id ) ``` `$can` is `true` for the user it is the stream of, and for administrators. ### wordplus_stream_grant_claims The claims of the grant a person joins with, after everything above. To change the name or the avatar shown in the chat, add the origins of pages on other domains that show the stream to `org`, or shorten `ttl`. Return anything but an array to refuse the grant. ```php apply_filters( 'wordplus_stream_grant_claims', array $claims, array $rules, int $user_id ) ``` ### wordplus_stream_track_watch Whether the site hears of the watch of a signed-in person, in [`wordplus_stream_joined`](#wordplus_stream_joined) and [`wordplus_stream_left`](#wordplus_stream_left). Asked as they join a stream, and only while anything listens to either action. ```php apply_filters( 'wordplus_stream_track_watch', bool $track, int $stream_id, int $user_id ) ``` ```php // Only the streams of members, not those the site runs. add_filter( 'wordplus_stream_track_watch', function ( $track, $stream_id ) { return $track && wordplus_streams()->get_host( $stream_id ) > 0; }, 10, 2 ); ``` ## Actions ### wordplus_stream_live A stream went live: for a post in a feed as a member goes live, or a notice to their followers. ```php do_action( 'wordplus_stream_live', int $stream_id, array $stream, array $times ) ``` `$stream` is as [`wordplus_streams()->get()`](https://stream.wordplus.cloud/docs/developers/php/#get) gives it, and `$times` holds `started`, when it went live (a timestamp). ```php add_action( 'wordplus_stream_live', function ( $stream_id, $stream ) { if ( $stream['host'] ) { my_notify_followers( $stream['host'], $stream['title'], $stream['page'] ); } }, 10, 2 ); ``` ### wordplus_stream_ended A stream ended, after `wordplus_stream_live` told it went live. ```php do_action( 'wordplus_stream_ended', int $stream_id, array $stream, array $times ) ``` `$times` holds `started` and `ended` (timestamps), `seconds` on air, and who watched while it was live: - `peak`: the most people watching at once. - `viewer_seconds`: the seconds they all watched, added up. Divide by 60 for viewer minutes, or by `seconds` for how many watched on average. The hosts and the guests on stage are not counted in either. Both are `null` when the site heard of the end by asking the cloud, as below. ```php // A live stream post keeps how many watched each time it was on air. add_action( 'wordplus_stream_ended', function ( $stream_id, $stream, $times ) { if ( 'post' === $stream['object_type'] && null !== $times['peak'] ) { add_post_meta( $stream['object_id'], 'my_stream_audience', array( 'ended' => $times['ended'], 'peak' => $times['peak'], 'minutes' => round( $times['viewer_seconds'] / 60 ), ) ); } }, 10, 3 ); ``` **When they come:** WordPlus Cloud tells the site the moment a stream goes live or ends, at the webhook of the site, and these come within a second. Where the cloud cannot reach the site, on a private network or behind a firewall, the site asks the cloud every minute while anything listens to them, and they come within a minute. Each comes once for each time a stream is on air, whichever way it was heard. A stream that was live for less than a minute on a site the cloud cannot reach may not be told at all. ### wordplus_stream_joined Someone signed in started watching a live stream: they opened it while it was live, or it went live with them on its page. Also its hosts and the guests on stage, as they present it. ```php do_action( 'wordplus_stream_joined', int $stream_id, int $user_id, array $watch ) ``` `$watch` holds `role` (`viewer`, `host` or `guest`), `watch`, an id for this watch that its `wordplus_stream_left` has too, and `joined` (a timestamp). ### wordplus_stream_left Someone signed in stopped watching a live stream: they left, or it ended. ```php do_action( 'wordplus_stream_left', int $stream_id, int $user_id, array $watch ) ``` `$watch` holds what `wordplus_stream_joined` had, plus `left` (a timestamp) and `seconds` watched. Only the time the stream was live counts: waiting on its page for it to start counts nothing, and a stream that goes live again starts another watch. ```php // How long each member watched, added up, for a badge or a report. add_action( 'wordplus_stream_left', function ( $stream_id, $user_id, $watch ) { if ( 'viewer' === $watch['role'] ) { $total = (int) get_user_meta( $user_id, 'my_watched_seconds', true ); update_user_meta( $user_id, 'my_watched_seconds', $total + $watch['seconds'] ); } }, 10, 3 ); ``` **Who is told of:** only people signed in on the site. Visitors are counted in `peak` and `viewer_seconds` but never told of one by one. While anything listens to either action, the grants of signed-in people ask WordPlus Cloud to tell the site of their watches, and [`wordplus_stream_track_watch`](#wordplus_stream_track_watch) narrows that down. Nobody else costs the site a request. **When they come:** within a second, at the webhook of the site, each once. A site the cloud cannot reach hears none of them. ### wordplus_stream_created A stream was made: by an administrator, in a Better Messages chat room, or by your code. ```php do_action( 'wordplus_stream_created', int $stream_id, array $stream ) ``` `$stream` is as [`wordplus_streams()->get()`](https://stream.wordplus.cloud/docs/developers/php/#get) gives it. ### wordplus_stream_updated The title or the settings of a stream were saved. ```php do_action( 'wordplus_stream_updated', int $stream_id, array $stream, array $before ) ``` ### wordplus_stream_deleted A stream was deleted, by an administrator or by your code. Forget what you keep of it. ```php do_action( 'wordplus_stream_deleted', int $stream_id, array $stream ) ``` `$stream` is as it was. In the browser, a page hears the same as it happens: the stream it shows (`wordplusStreams.on`) and the streams of the site (`wordplusStreams.live`), in [JavaScript](https://stream.wordplus.cloud/docs/developers/javascript/). --- # JavaScript Address: https://stream.wordplus.cloud/docs/developers/javascript/ The player puts `window.wordplusStreams` on the page. Your script shows streams with it, and hears what happens in them. ## On the page Put the player on the page with [`wordplus_streams()->enqueue()`](https://stream.wordplus.cloud/docs/developers/php/#enqueue), and make your script depend on its handle, `wordplus-streams`: ```php add_action( 'wp_enqueue_scripts', function () { if ( function_exists( 'wordplus_streams' ) && wordplus_streams()->enqueue() ) { wp_enqueue_script( 'my-plugin-live', plugins_url( 'live.js', __FILE__ ), array( 'wordplus-streams' ), '1.0.0', true ); } } ); ``` A page where [`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render) drew a stream has it already. ## Showing a stream ### wordplusStreams.show() ```js wordplusStreams.show( element, id, options ): Promise ``` Shows a stream, or a part of it, in the element, asking the site for its config for whoever looks ([REST](#rest)). `options` are `part` and its choices, as [`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render) takes them. It rejects with an error whose `code` says why: `not_found`, or `not_set_up` on a page without `wordplus_streams()->enqueue()`. ```js const stream = await wordplusStreams.show( element, 12, { part: 'player', shape: '9:16' } ); ``` ### wordplusStreams.mount() ```js wordplusStreams.mount( element, config ): Stream ``` The same, from a config your PHP gave the page with [`wordplus_streams()->config()`](https://stream.wordplus.cloud/docs/developers/php/#config), with no request to the site: ```php wp_add_inline_script( 'my-plugin-live', 'window.myLive = ' . wp_json_encode( wordplus_streams()->config( $stream_id, array( 'part' => 'chat' ) ) ) . ';', 'before' ); ``` ```js wordplusStreams.mount( document.querySelector( '#my-chat' ), window.myLive ); ``` ### wordplusStreams.unmount() ```js wordplusStreams.unmount( element ) ``` Takes the stream out of the element. With its last part gone from the page, the page leaves the stream. Call it before your screen removes the element. ### wordplusStreams.mountAll() ```js wordplusStreams.mountAll( scope ) ``` Shows the streams in the HTML of `wordplus_streams()->render()` that your script added to the page after it loaded, within `scope` (the whole page when not given). The player shows those on the page as it loads by itself. ## Streams of your users A **Go live** button anywhere: a user makes a stream of their own, then goes live in its studio, right there. Your PHP decides who may, with [`wordplus_stream_can_create`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_can_create), and what they may choose, with [`wordplus_stream_user_settings`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_user_settings). ### wordplusStreams.create() ```js wordplusStreams.create( { title, settings, object_type, object_id } ): Promise ``` Makes a stream the user hosts, and answers it as [`wordplus_streams()->get()`](https://stream.wordplus.cloud/docs/developers/php/#get) gives it. It rejects with an error whose `code` says why: `wordplus_stream_cannot_create` where your PHP does not let them, `wordplus_stream_no_title`, `not_set_up`. ```js button.addEventListener( 'click', async () => { const made = await wordplusStreams.create( { title: 'Live with ' + myName } ); await wordplusStreams.show( studio, made.id, { part: 'studio' } ); await wordplusStreams.show( player, made.id, { part: 'player' } ); } ); ``` ### wordplusStreams.update() and wordplusStreams.delete() ```js wordplusStreams.update( id, { title, settings } ): Promise wordplusStreams.delete( id ): Promise<{ deleted, id }> ``` Changes or deletes a stream of the user, or any stream for an administrator ([`wordplus_stream_can_edit`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_can_edit)). Settings not sent stay as they are. ## A stream on the page `wordplusStreams.show()` and `wordplusStreams.mount()` answer the stream, one for all its parts on the page. `wordplusStreams.stream( 12 )` finds it by its ID, and `wordplusStreams.stream( element )` by an element that shows it. Both give `null` while no part shows it. Its names are those of the stream in the WordPlus apps SDK. | | | |---|---| | `id` | Its ID on the site, `12`. | | `stream` | Its ID on the cloud, `s12`. | | `title` | Its title. | | `state` | `idle` before it starts, `live`, or `ended`. | | `viewers` | How many watch. | | `startedAt` | When it went live, in milliseconds, or `null`. | | `role` | `host` or `viewer` for this person, once joined, or `null` before. | ### Events ```js stream.on( 'state', ( state ) => { badge.hidden = state !== 'live'; } ); stream.off( 'state' ); // Every listener of the event, or one with stream.off( 'state', fn ). ``` | Event | Its value | |---|---| | `state` | `idle`, `live` or `ended`, as it changes. A stream live as the page joins it tells `live`. | | `viewers` | How many watch, as it changes. | | `message` | Each new message of its light chat: `{ id, from: { name, avatar, role }, text, at }`. | | `error` | `{ code }`, when it cannot be joined: `forbidden` (the person may not watch it), `not_found`, `not_licensed`, `not_included`, `banned`, `expired`. | | `change` | Any of these, with the stream. | Each listener gets the value and the stream. `on` and `off` answer the stream, so they chain. ### wordplusStreams.on() ```js wordplusStreams.on( event, listener ) wordplusStreams.off( event, listener ) ``` Hears every stream on the page, those `wordplus_streams()->render()` drew included, with the same events: ```js wordplusStreams.on( 'state', ( state, stream ) => { if ( state === 'live' ) { myNotify( stream.title + ' is live' ); } } ); ``` ## What is live ### wordplusStreams.live() ```js wordplusStreams.live( listener ): () => void ``` Tells your listener the streams of the site live now, and again each time one goes live or ends, without joining any: `[ { stream: 's12', id: 12, viewers: 31, startedAt } ]`, the latest first. It answers a function that stops it. For a **Live** badge in a list of your groups, say: ```js wordplusStreams.live( ( live ) => { const on = new Set( live.map( ( s ) => s.id ) ); document.querySelectorAll( '[data-stream-id]' ).forEach( ( el ) => { el.classList.toggle( 'is-live', on.has( Number( el.dataset.streamId ) ) ); } ); } ); ``` It is the way the Live now list hears it: one connection for every tab of the browser, shared with the player and the other WordPlus plugins on the page. Put it on the page with [`wordplus_streams()->enqueue_live()`](https://stream.wordplus.cloud/docs/developers/php/#enqueue_live), and make your script depend on `wordplus-streams-live`. On a site whose licence does not include live streaming, it tells nothing. ## REST ### GET /wp-json/wordplus/v1/streams/12/config The config of a stream for whoever asks, as `wordplusStreams.mount()` takes it: what `wordplusStreams.show()` asks for. Logged-in users send the `X-WP-Nonce` header with a `wp_rest` nonce. The query takes `part` and its choices, as [`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render), and `url`, the address of the page. ``` GET /wp-json/wordplus/v1/streams/12/config?part=player&shape=16:9 ``` It answers for anyone, as the page of the stream would: the grant inside it is that of the person asking, and a person who may not watch gets none, so the player says so. `404` for no such stream. ### The streams of a user For logged-in users, with the nonce: | Route | | |---|---| | `GET /wp-json/wordplus/v1/streams` | Their own streams, the newest first: `page` and `per_page`. | | `POST /wp-json/wordplus/v1/streams` | Makes one: `title`, `settings`, `object_type`, `object_id`. `201` with the stream, `403` where [`wordplus_stream_can_create`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_can_create) does not let them. | | `PUT /wp-json/wordplus/v1/streams/12` | Changes it: `title`, `settings`. | | `DELETE /wp-json/wordplus/v1/streams/12` | Deletes it. | ### From an automation A tool such as Make, Zapier or n8n, or a script of your own, plans the times of a stream with `PUT /wp-json/wordplus/v1/streams/12`, signed in with a WordPress [application password](https://wordpress.org/documentation/article/application-passwords/) of an administrator, made in **Users → Profile → Application Passwords**. An application password needs no nonce. The number of the stream is the one in its shortcode, in **Streams**. `settings.sessions` replaces the times planned ([`sessions`](https://stream.wordplus.cloud/docs/developers/php/#settings)): each `at`, a timestamp or a date and time in the time zone of the site, and its own `title`. One stream keeps its page, its OBS key and its chat, so an automation that plans a week never makes a stream a day. ```bash curl -X PUT https://example.com/wp-json/wordplus/v1/streams/12 \ --user 'admin:abcd efgh ijkl mnop qrst uvwx' \ --header 'Content-Type: application/json' \ --data '{"settings":{"sessions":[ {"at":"2026-10-26T08:15","title":"Trading room, No. 1121"}, {"at":"2026-10-27T08:15","title":"Trading room, No. 1122"}, {"at":"2026-10-28T08:15","title":"Trading room, No. 1123"} ]}}' ``` It answers with the stream, its times as timestamps, the soonest first, and `scheduled` the next one. A time gone by more than 12 hours is left out. From PHP, the same is `wordplus_streams()->update( 12, array( 'settings' => array( 'sessions' => $times ) ) )`. --- # Example: live events Address: https://stream.wordplus.cloud/docs/developers/example/ Say your plugin has events, a post type `event`, and keeps the people going to each in its `attendees` meta, a list of user IDs. This plugin gives each event a live stream: - **Made with the event,** once it is published, and named after it. It goes when the event is deleted. - **Hosted by its organiser,** the author of the event, who goes live on the page of the event. No access to the WordPress admin is needed. - **Watched by the people going,** and nobody else but the administrators. - **On the page of the event,** under its text: the player with the chat beside it, and the studio over them for the organiser. - **A Live badge** beside the event in the list of events, the moment its stream goes live and gone when it ends. ```php post_status ) { return; } $stream = wordplus_streams()->get_object_stream( 'live_event', $event_id ); if ( $stream ) { wordplus_streams()->update( $stream['id'], array( 'title' => $event->post_title ) ); return; } wordplus_streams()->create( array( 'title' => $event->post_title, 'object_type' => 'live_event', 'object_id' => $event_id, 'settings' => array( 'access' => 'logged_in', 'chat_with' => 'light' ), ) ); }, 10, 2 ); // The stream goes with its event. add_action( 'before_delete_post', function ( $event_id ) { if ( function_exists( 'wordplus_streams' ) && 'event' === get_post_type( $event_id ) ) { $stream = wordplus_streams()->get_object_stream( 'live_event', $event_id ); if ( $stream ) { wordplus_streams()->delete( $stream['id'] ); } } } ); // The organiser of an event, its author, hosts its stream. add_filter( 'wordplus_stream_can_host', function ( $can, $stream_id, $user_id ) { $event = wordplus_streams()->get_object( $stream_id ); if ( $event && 'live_event' === $event['type'] ) { return (int) get_post_field( 'post_author', $event['id'] ) === $user_id; } return $can; }, 10, 3 ); // Only the people going to an event watch its stream. add_filter( 'wordplus_stream_can_watch', function ( $can, $rules, $user_id, $stream_id ) { $event = wordplus_streams()->get_object( $stream_id ); if ( $event && 'live_event' === $event['type'] ) { $going = array_filter( array_map( 'intval', (array) get_post_meta( $event['id'], 'attendees', true ) ) ); return $can && in_array( $user_id, $going, true ); } return $can; }, 10, 4 ); // The stream under the text of the event, and the studio over it for the organiser. add_filter( 'the_content', function ( $content ) { if ( ! function_exists( 'wordplus_streams' ) || ! is_singular( 'event' ) || get_the_ID() !== get_queried_object_id() ) { return $content; } $stream = wordplus_streams()->get_object_stream( 'live_event', get_the_ID() ); if ( ! $stream ) { return $content; } if ( wordplus_streams()->user_can( $stream['id'], 'host' ) ) { $content .= wordplus_streams()->render( $stream['id'], array( 'part' => 'studio' ) ); } return $content . wordplus_streams()->render( $stream['id'], array( 'layout' => 'side' ) ); } ); // In the list of events, a Live badge beside each event whose stream is live. add_filter( 'the_title', function ( $title, $post_id = 0 ) { if ( is_admin() || ! is_post_type_archive( 'event' ) || 'event' !== get_post_type( $post_id ) || ! function_exists( 'wordplus_streams' ) ) { return $title; } $stream = wordplus_streams()->get_object_stream( 'live_event', (int) $post_id ); return $stream ? $title . ' ' : $title; }, 10, 2 ); add_action( 'wp_enqueue_scripts', function () { if ( ! function_exists( 'wordplus_streams' ) || ! is_post_type_archive( 'event' ) || ! wordplus_streams()->enqueue_live() ) { return; } wp_add_inline_script( 'wordplus-streams-live', 'wordplusStreams.live( function ( live ) { var on = live.map( function ( stream ) { return stream.id; } ); document.querySelectorAll( ".live-event-badge" ).forEach( function ( badge ) { badge.hidden = on.indexOf( Number( badge.getAttribute( "data-stream-id" ) ) ) === -1; } ); } );' ); } ); ``` ## How it works - **The stream of each event** is made for it (`object_type` and `object_id`), so [`wordplus_streams()->get_object_stream()`](https://stream.wordplus.cloud/docs/developers/php/#get_object_stream) finds it again, and the hooks read what it was made for with [`wordplus_streams()->get_object()`](https://stream.wordplus.cloud/docs/developers/php/#get_object). Streams made for other things, and those the administrators make, keep their own rules. - **Its settings** keep visitors out (`logged_in`), and give it the light chat. Everything else is as in a new stream, and administrators can change it in **Live Stream → Studio → Streams**, where the stream shows like any other. - **The organiser** gets the studio on the page of the event, since [`wordplus_streams()->user_can()`](https://stream.wordplus.cloud/docs/developers/php/#user_can) says they host the stream. They go live there with the camera, a screen or OBS, and nobody else sees the studio. - **Someone not going** sees **You do not have access to this stream** in the player. - **The badge** hears the streams of the site going live and ending ([`wordplusStreams.live`](https://stream.wordplus.cloud/docs/developers/javascript/#live)), on one connection for every tab of the browser, without joining any. ## Going further - **A screen your script draws:** show the stream with [`wordplusStreams.show()`](https://stream.wordplus.cloud/docs/developers/javascript/#wordplusstreamsshow), and hear when it goes live and how many watch from the stream it answers. - **A tab of its own:** put the parts where you like with [`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render): the player in the main column and the chat in a sidebar, say. - **A chat of your own:** set `chat` to `false` and show yours beside the player. - **When it starts:** set `scheduled` from the date of the event, and the player counts down to it, with **Add to calendar**. --- # Example: members going live Address: https://stream.wordplus.cloud/docs/developers/members/ Live streams of your users, the way a community has them: every member goes live, and their followers find them in the feed. This plugin does it with WordPress alone, so it runs on any site: - **A stream of their own** for each member, made the first time they open the **Go live** page, a page with the `[go_live]` shortcode. They host it, and only they do, besides the administrators. - **They go live on that page,** with the camera, a screen or OBS, in the studio of their stream. No access to the WordPress admin is needed. - **A post goes up as they go live,** with the stream in it, the chat beside the player. It is their post, and the Live now list links to it. - **As it ends,** the post says how long they were live. ```php get_object_stream( 'member', $user_id ); if ( $stream ) { return $stream['id']; } $made = wordplus_streams()->create( array( 'title' => get_the_author_meta( 'display_name', $user_id ), 'host' => $user_id, 'object_type' => 'member', 'object_id' => $user_id, 'settings' => array( 'access' => 'logged_in', 'chat_with' => 'light' ), ) ); return is_wp_error( $made ) ? 0 : $made; } // [go_live]: the studio of the member, and their stream as viewers see it. add_shortcode( 'go_live', function () { if ( ! function_exists( 'wordplus_streams' ) || ! is_user_logged_in() ) { return ''; } $stream_id = members_live_stream( get_current_user_id() ); if ( ! $stream_id ) { return ''; } return wordplus_streams()->render( $stream_id, array( 'part' => 'studio' ) ) . wordplus_streams()->render( $stream_id, array( 'part' => 'player' ) ); } ); // As a member goes live, a post goes up, which shows the stream while it is live. add_action( 'wordplus_stream_live', function ( $stream_id, $stream ) { if ( 'member' !== $stream['object_type'] ) { return; } $post_id = wp_insert_post( array( 'post_status' => 'publish', 'post_author' => $stream['host'], /* translators: %s: the name of a member. */ 'post_title' => sprintf( __( '%s is live', 'members-live' ), $stream['title'] ), 'meta_input' => array( 'members_live_stream' => $stream_id ), ) ); update_user_meta( $stream['host'], 'members_live_post', $post_id ); }, 10, 2 ); add_filter( 'the_content', function ( $content ) { $stream_id = (int) get_post_meta( get_the_ID(), 'members_live_stream', true ); if ( ! $stream_id || ! function_exists( 'wordplus_streams' ) || get_the_ID() !== get_queried_object_id() ) { return $content; } return $content . wordplus_streams()->render( $stream_id, array( 'layout' => 'side' ) ); } ); // The Live now list and the links the player shares go to that post. add_filter( 'wordplus_stream_page_url', function ( $url, $stream_id ) { $member = wordplus_streams()->get_host( $stream_id ); $post_id = $member ? (int) get_user_meta( $member, 'members_live_post', true ) : 0; return $post_id ? get_permalink( $post_id ) : $url; }, 10, 2 ); // As it ends, the post says how long it lasted, without the stream. add_action( 'wordplus_stream_ended', function ( $stream_id, $stream, $times ) { $post_id = 'member' === $stream['object_type'] ? (int) get_user_meta( $stream['host'], 'members_live_post', true ) : 0; if ( ! $post_id ) { return; } $minutes = max( 1, (int) round( $times['seconds'] / 60 ) ); wp_update_post( array( 'ID' => $post_id, /* translators: %s: the name of a member. */ 'post_title' => sprintf( __( '%s was live', 'members-live' ), $stream['title'] ), /* translators: %d: how many minutes. */ 'post_content' => sprintf( _n( 'Live for %d minute.', 'Live for %d minutes.', $minutes, 'members-live' ), $minutes ), ) ); delete_post_meta( $post_id, 'members_live_stream' ); delete_user_meta( $stream['host'], 'members_live_post' ); }, 10, 3 ); ``` ## How it works - **The stream of each member** is made with them as its `host`, and for them (`object_type` `member`, `object_id` their ID), so [`wordplus_streams()->get_object_stream()`](https://stream.wordplus.cloud/docs/developers/php/#get_object_stream) finds it again each time. They host it, and nobody else but the administrators. It stays out of the studio of the administrators, who still find it in **Live Stream → Studio → Streams**. - **The post** comes from [`wordplus_stream_live`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_live), and the end from [`wordplus_stream_ended`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_ended): within a second where WordPlus Cloud reaches the site, else within a minute. The post shows the stream through [`render()`](https://stream.wordplus.cloud/docs/developers/php/#render) while it is live, and [`wordplus_stream_page_url`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_page_url) makes it the page the Live now list links to and the player shares, read with [`get_host()`](https://stream.wordplus.cloud/docs/developers/php/#get_host), which that filter calls for. - **Viewers** are logged-in users (`access`), as on any stream, and a membership plugin narrows it further with [`wordplus_stream_can_watch`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_can_watch). - **Every stream of the site counts toward its viewers.** The audiences of your members are viewers of the site like any other ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). ## Going further - **A feed of your own:** put your post, activity or status in place of the WordPress post, with the stream in it from [`wordplus_streams()->render()`](https://stream.wordplus.cloud/docs/developers/php/#render). - **Followers told:** send your notices from `wordplus_stream_live`, with the page of the stream (`$stream['page']`). - **Go live in a screen drawn in the browser:** [`wordplusStreams.create()`](https://stream.wordplus.cloud/docs/developers/javascript/#wordplusstreamscreate) makes the stream from your script, where [`wordplus_stream_can_create`](https://stream.wordplus.cloud/docs/developers/hooks/#wordplus_stream_can_create) lets the user. - **A stream for each live:** make a new stream each time, and delete it with its post when you like. --- # How to Live Stream on a WordPress Site Address: https://stream.wordplus.cloud/blog/how-to-live-stream-on-wordpress/ Live streaming on a WordPress site sounds like one feature, and it is several. Someone goes live with a camera or an encoder. The picture travels to everyone watching, close enough to the moment that they can react. A player shows it on your page, a chat sits beside it, and your site decides who may watch and who may go live. WordPress itself does none of that, so every way to stream on it hands the video to something else. This guide goes through each of them, what it takes to set up and to run, and then walks through going live with Live Stream, the plugin we make for it. ![A stream on a WordPress page: the host live on camera with hearts and fire rising over the picture, and the chat beside it](https://stream.wordplus.cloud/img/shots/stream-page.webp) ## The ways at a glance | Way | What viewers get | What it takes | |---|---|---| | [Embed a stream from YouTube, Facebook or Twitch](#embed) | The player and chat of that platform, on your page | A channel there. Free | | [A paid streaming service](#streaming-service) | An embedded player, often without the platform around it | A plan, usually priced by viewing hours | | [Your own streaming server](#own-server) | Whatever player you build | Servers, bandwidth and someone to run them | | [A meeting tool](#meeting-tool) | A meeting or webinar, usually in its own app | A licence for each host | | [A live streaming plugin](#plugin) | A player and chat on your pages, for the people your site lets in | The plugin and the service behind it | ## 1. Embed a stream from YouTube, Facebook or Twitch The quickest way needs no plugin at all. Go live on YouTube, Facebook or Twitch, copy the embed code of the stream, and paste it into a **Custom HTML** block. For YouTube, pasting the address of the stream into a **YouTube** block works too. **Good:** it costs nothing, these platforms carry any audience, and many people already know how to watch there. **Not so good:** - The stream lives on the platform. Viewers watch in its player, the chat and the audience belong to its account, and its rules decide what you may stream. - Your site cannot say who watches. Anyone with the link can, and a members only stream needs the private or unlisted settings of the platform, which know nothing of your members. - These platforms deliver video in segments of a few seconds, so viewers see the host several seconds after it happens, and a question in the chat is about a moment the host has already moved past. **Fits:** a public show that should also reach people on the platform itself. ## 2. A paid streaming service Hosted streaming services give you an ingest address for your encoder and a player to embed, without the branding and suggestions of a social platform. Many are priced by the hours watched, or by a plan with a monthly allowance. **Good:** a clean player on your page, and the service handles the scale. **Not so good:** the player still knows nothing of your members, so access needs tokens or passwords from the service. The chat is a separate product, if there is one. Most deliver over HLS, with the same few seconds of delay as the platforms above. **Fits:** a company that streams events to a large public audience and wants its own look. ## 3. Your own streaming server Open source servers take an RTMP or WebRTC stream in and send it out to players. You rent a server, install one, and embed its player. **Good:** full control, and no service in between. **Not so good:** you run it. Every viewer is a stream out of your server, so bandwidth grows with the audience, and a crowd needs more servers in more places. The player, the chat, who may watch and keeping it all up to date are yours to build. **Fits:** a team with someone who runs servers, and a reason to. ## 4. A meeting tool Zoom, Google Meet and Microsoft Teams run webinars, and a WordPress plugin can create the meetings for you and put the link on a page. **Good:** everyone can come on camera, and these tools record. **Not so good:** people leave your site for the app of the meeting, and a meeting is not a broadcast: it is built for people who talk to each other, and its webinar plans are priced by host and by audience size. **Fits:** a class where students speak on camera, a team meeting. ## 5. A live streaming plugin A plugin can put the whole stream on your own pages: the host goes live from the WordPress admin, viewers watch on a page of your site, and the chat sits beside the player. The plugin needs a service behind it to carry the video, because a WordPress server cannot send a live picture to many viewers at once. This is what Live Stream does. Its video and chat run on WordPlus Cloud, and your site keeps the decisions: - **Hosts go live from the browser**, with a camera, a microphone and a shared screen, in **Live Stream → Studio**, or from **OBS 30 or later** over WHIP. - **Viewers watch in the browser over WebRTC**, with low delay and no app, on any page you put the stream on, with the block or the shortcode. - **Your site decides who watches:** everyone, logged-in users, or the roles you choose, and a membership plugin can decide with a filter. - **The chat is beside the stream**, with reactions and moderation, or a [Better Messages](https://www.better-messages.com/) chat room saved on your site. **Not so good:** it needs a WordPlus Cloud subscription that includes live streaming, and it is a beta. **Fits:** streams for your own audience, on your own site: classes, members only shows, Q&A sessions, launches, community streams. ## Going live on WordPress with Live Stream ### What you need - WordPress 6.0 or later and PHP 7.4 or later. - Your site on HTTPS. Browsers let a page use the camera and the microphone only over HTTPS. - A [WordPlus Cloud](https://www.wordplus.cloud) subscription that includes live streaming. Each site streams to 50 viewers at once unmetered, however long they watch, and each viewer above that takes a credit a minute ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). - An upload that carries your picture: up to about 4 Mbps for HD, up to about 8 Mbps for Full HD. ### 1. Install the plugin In WordPress, go to **Plugins → Add New Plugin**, search for **WordPlus Live Stream**, press **Install Now**, then **Activate**. A **Live Stream** menu appears in the admin. ### 2. Activate the licence Go to **Live Stream → Licence** and enter your WordPlus Cloud licence key. A site that already runs Better Messages on the subscription is connected already. ### 3. Create a stream Open **Live Stream → Studio → Streams** and press **Create stream**. Give it a title, a start time if you like, a cover, and choose who can watch. Press **Save changes**. ![The settings of a stream: its title, shortcode, start, cover, Live now link and who can watch](https://stream.wordplus.cloud/img/shots/stream-settings.webp) ### 4. Put it on a page Press **Create a page** beside the stream in the Studio tab, and Live Stream publishes a page with the stream on it, the chat beside the player. Or add the **Live stream** block to any page, or paste its shortcode, such as `[wordplus_stream id="12"]`, into a page builder. A stream with a start time shows a countdown until you go live, with **Add to calendar**. ### 5. Go live In **Live Stream → Studio**, choose **Go live** beside the stream to open its studio. Choose **Turn on camera and microphone**, pick your devices and the quality, and press **Go live**. Everyone on the page sees the stream begin, without reloading. ![The studio while live: the camera of the host, the statistics, the controls and the chat beside them](https://stream.wordplus.cloud/img/shots/studio-live.webp) For scenes, overlays and several cameras, stream from OBS instead: [How to stream from OBS to WordPress over WHIP](https://stream.wordplus.cloud/blog/stream-from-obs-to-wordpress/). ## Before your first stream - **Try it on a page nobody else knows.** Go live, and watch it from another device, on another network if you can. - **Watch the statistics.** While you are live, the studio shows how your picture goes out, and **Statistics** opens the details ([When your stream goes out badly](https://stream.wordplus.cloud/docs/going-live/#when-your-stream-goes-out-badly/)). - **Plan the start.** A start time gives viewers a countdown and a calendar entry, and your page can collect them before you begin. - **Choose the chat.** The light chat is for the moment and is gone a day after. A Better Messages chat room keeps every message ([Chat and moderation](https://stream.wordplus.cloud/docs/chat/)). ## Frequently asked questions ### Can I live stream on WordPress for free? Embedding a stream from YouTube, Facebook or Twitch costs nothing. Live Stream is free to download, and streaming with it needs a WordPlus Cloud subscription, which streams to 50 viewers at once on each site unmetered. ### Will live streaming slow down my WordPress server? Not with a plugin built on a streaming service. The video goes from the host to WordPlus Cloud and from there to each viewer, never through your server, and the page of a public stream works with page caching, so a crowd of viewers is not a crowd of requests to WordPress. ### Do viewers need an account? Only if you want them to. Each stream is for everyone, for logged-in users, or for the roles you choose. ### Can I go live from my phone? Yes. The studio works in the browser of a phone, with its front or back camera. ### Can I record the stream? Yes. A stream can be recorded while live, and its page then plays the replay ([Recording and replays](https://stream.wordplus.cloud/docs/recording/)). --- # How to Stream from OBS to WordPress over WHIP Address: https://stream.wordplus.cloud/blog/stream-from-obs-to-wordpress/ OBS Studio is where most streams are made: scenes, overlays, a second camera, a slide deck beside your face. Since version 30, OBS can also send its stream over **WHIP**, the standard way to push a stream into a WebRTC service. That makes a new route possible: from OBS straight to a page of your WordPress site, watched in the browser with low delay, with no RTMP server in between. This guide sets it up with Live Stream, step by step, with the OBS settings that decide how soon viewers see the picture and how smoothly it plays. ![The studio with OBS connected: the picture from OBS previewed at 720p and 31 fps, with the steps, the server address and the bearer token to copy](https://stream.wordplus.cloud/img/shots/studio-obs.webp) ## What WHIP is, and why it matters For years, encoders sent streams over **RTMP**. RTMP takes the stream to a server, which repackages it for viewers, usually as HLS: short files of a few seconds each, which players download one after another. It works at any scale, and it puts viewers several seconds behind the host. **WHIP**, the WebRTC-HTTP Ingestion Protocol, sends the stream over WebRTC instead, the technology browsers use for video calls. It is an IETF standard (RFC 9725). The encoder asks a WHIP server address, with a bearer token, to take its stream, and from then on the picture flows as WebRTC packets. A WebRTC service can pass those packets on to viewers as they arrive, so they see the host with low delay, close enough to react in the chat while the moment is still on screen. More on why: [Low latency live streaming: why WebRTC](https://stream.wordplus.cloud/blog/low-latency-live-streaming-webrtc/). OBS has had WHIP since version 30. FFmpeg has a WHIP output as well, from version 8. ## What you need - **OBS 30 or later.** For layers (below), OBS 32.1 or later. - **A WordPress site with Live Stream** and a WordPlus Cloud subscription that includes live streaming ([How to live stream on a WordPress site](https://stream.wordplus.cloud/blog/how-to-live-stream-on-wordpress/) covers installing it). - **A stream** in **Live Stream → Studio → Streams**, on a page of your site. ## Connect OBS, step by step 1. **Open the studio of the stream.** In **Live Stream → Studio**, choose **Go live** beside the stream, then **Stream from OBS**. With the camera already on, it is under **More**. The studio shows the steps, with "Waiting for OBS…". 2. **In OBS, open Settings → Stream** and choose **WHIP** as the service. 3. **Copy Server** from the studio into the **Server** field of OBS. 4. **Copy Bearer token** from the studio into the **Bearer Token** field of OBS. 5. **Set Total Layers to 3**, in the same window, if your OBS has it (32.1 or newer). 6. **Set the output of OBS** as below, then press **Start Streaming** in OBS. 7. **Check the picture.** Once it arrives, the studio says **OBS is connected** and previews it with its size, frame rate and bitrate. Only you see it so far. 8. **Press Go live** in the studio. Viewers see the whole picture from OBS. The token is the key of the stream. Only its hosts see it, and **New key** in the studio makes a new one if it was seen by someone it should not have been. ## The OBS settings that matter ### Layers: one picture in three sizes With **Total Layers** at **3**, OBS sends the full picture and two smaller copies of it at once. Each viewer gets the largest their screen and connection take, and a viewer whose connection slows down steps down to a smaller copy instead of stopping to wait. Layers cost upload. OBS gives the full picture the bitrate you set and the copies two thirds and one third of it, so 4,500 kbps takes about 9 Mbit/s of upload in all. If your upload cannot carry that, set a lower bitrate, or 2 layers. Without layers, every viewer gets the same picture, so choose a size that every connection can take. ### Size and bitrate - **Settings → Video:** Output (Scaled) Resolution **1920×1080** at **30 FPS** with layers. Without layers, **1280×720** lets viewers on slow connections keep up. - **Settings → Output:** choose the **Advanced** output mode, and under **Streaming** set the bitrate to about **4,500 kbps** with layers, or **2,500 kbps** without. These are a starting point. What suits a stream depends on what it shows, on the computer that sends it and on its connection. ### Keyframes and B-frames Two settings decide how soon viewers see the picture and how smoothly it plays, and only the **Advanced** output mode of OBS has them (**Settings → Output → Output Mode**, then the **Streaming** tab): - **Keyframe Interval: 1 s.** A viewer sees the picture from the next keyframe on, when they arrive and when they come back to the page from another tab. The Simple output mode leaves the interval on auto, about one keyframe every 8 seconds, so viewers can wait that long. At 1 s, they wait a second at most. - **Max B-frames: 0.** Browsers skip B-frames, so a picture with them stutters. Some encoders start this setting at 2 in the Advanced mode. Keep the **Video Encoder** the Simple mode had, a hardware encoder of your graphics card where there is one, and leave the rest as it is. The studio checks both while OBS sends, and says what to change, without stopping you from going live. ## Try it before your audience does 1. Make a stream for trying, on a page nobody else knows, start streaming in OBS and press **Go live**. 2. Open its page on another device, on another network if you can, and watch for a few minutes, with the kind of picture you will stream. 3. Keep **View → Stats** open in OBS: it shows frames skipped by the encoder and frames dropped on the way out. Then change one thing at a time: | What you see | What it means | What to do | |---|---|---| | The picture freezes and catches up | Your upload cannot carry what OBS sends | Lower the bitrate, or 2 layers | | It stutters, and Stats shows frames skipped due to encoding lag | The encoder cannot keep up | A faster preset, or fewer layers | | Detail pulses once a second on a busy picture | Each keyframe takes a large share of the bits | A higher bitrate, or a 2 s keyframe interval | | Viewers wait seconds for the picture | Keyframes too far apart | Keyframe Interval 1 s | | Everything plays smoothly | | Keep it, or try a higher bitrate | ## A stream that runs by itself For a stream sent from a computer that is always on, such as a demo or a camera on a view, turn on **Go live when OBS connects** in the settings of the stream. It then goes live as soon as OBS starts streaming with its token, with nobody in the studio, and stays live for as long as OBS sends. If OBS stops, the stream stays live while anyone watches, ends after five minutes with nobody watching, and goes live again as soon as OBS is back. ## When OBS does not connect - **The studio stays on "Waiting for OBS…":** check that the service in OBS is WHIP, and that the server and the token were copied whole. - **OBS says it could not access the stream key:** OBS says this whatever the server answered. Check that the token is the one the studio shows now. - **OBS cannot connect after the stream ended:** an ended stream keeps OBS out. Choose **Stream from OBS** in its studio again, then start streaming in OBS. The full reference is in the docs: [Streaming from OBS](https://stream.wordplus.cloud/docs/obs/). ## Frequently asked questions ### Can I stream to WordPress from OBS over RTMP? Not with Live Stream yet. It takes OBS and other encoders over WHIP. Streaming in over RTMP is planned. ### Do I need OBS to go live? No. Live Stream also goes live from the browser, with a camera, a microphone and a shared screen. OBS is for scenes, overlays and several cameras. ### What quality reaches viewers? Up to the picture OBS sends, and no more than 1080p. If OBS sends a bigger picture than the stream takes, the studio says so and waits until it is changed. Each viewer gets the largest layer that their player and connection need. --- # Low Latency Live Streaming: Why WebRTC Address: https://stream.wordplus.cloud/blog/low-latency-live-streaming-webrtc/ Every live stream runs a little behind the moment it shows. The camera sees the host wave, and viewers see the wave some time later: that gap is the **latency**, or delay, of the stream. For a stream that nobody answers, a few seconds do not matter. For a stream whose audience talks back, a Q&A, a class, a launch with questions, an auction, the delay decides whether the chat is a conversation or a string of answers to questions the host has already moved past. This post goes through where the delay comes from, why the usual way of delivering video runs many seconds behind, and how WebRTC, the technology of video calls, brings it down. It is also how Live Stream delivers its streams. ## Where the delay comes from A live picture passes through five stages, and each adds to the delay: 1. **Capture and encoding.** The camera takes the frame, and the encoder, a browser or OBS, compresses it. 2. **The way in.** The stream travels to a server. 3. **The server.** It may change the stream into other sizes or formats before passing it on. 4. **The way out.** The stream travels to each viewer. 5. **The player.** It holds some of the stream before playing it, a buffer, so that a late packet does not stop the picture. The network part is usually the small part: a fraction of a second, even across an ocean. The big differences come from what the server does with the stream, and how much the player holds. ## HLS and DASH: built for scale Most video on the web is delivered with **HLS** or **DASH**. The server cuts the stream into short files, **segments** of a few seconds each, and lists them in a playlist. The player downloads one segment after another, like any other file, and holds a few of them before it starts, so the picture never runs dry. That is why it scales so well: segments are plain files, which a CDN caches near every viewer, for any number of them. It is also why it runs behind. A segment exists only once its seconds have been recorded, and the player waits for several. An HLS stream often plays ten seconds or more behind the host. **Low-Latency HLS** and **Low-Latency DASH** cut segments into smaller parts and bring it down to a few seconds. ## RTMP: the way in, not the way out **RTMP** is how encoders have sent streams to servers for years. It once played in browsers too, through Flash, and today it carries the stream only to the server, which repackages it for viewers as HLS. So an RTMP workflow has the delay of HLS. ## WebRTC: built for conversation **WebRTC** is what browsers use for video calls, where a delay of seconds would make talking impossible. It sends the picture as a stream of small packets, which the receiving side plays as they arrive, holding only enough to smooth out the network. There are no segments to wait for. For a stream with an audience, a **media server** sits in the middle: the host sends one stream to it, and it passes the packets on to each viewer. Two techniques make that work for many viewers with different screens and connections: - **Layers.** The host sends the picture in several sizes at once, such as 720p, 540p and 360p, and the media server gives each viewer the size their player and connection need. Nothing is re-encoded on the server, so nothing waits for it. - **Repair.** When a packet is lost, the viewer asks for it again, and the media server keeps the last moments of the stream to resend it. The cost is on the side of whoever runs the media servers. A CDN cannot cache a WebRTC stream: every viewer has a live connection, and the servers must be close enough to the audience and large enough for it. ## HLS and WebRTC side by side | | HLS and DASH | Low-Latency HLS and DASH | WebRTC | |---|---|---|---| | Delay behind the host | Often ten seconds or more | A few seconds | About a second | | Delivered by | Any CDN, as files | A CDN that supports it | Media servers, a connection for each viewer | | Rewinding and catching up | Yes | Yes | No, always at the live moment | | A chat in step with the picture | No | Almost | Yes | | Plays in | Every browser, with a player script in some | Every browser, with a player script in some | Every current browser | ## How Live Stream streams over WebRTC Live Stream delivers every stream over WebRTC, through the media servers of WordPlus Cloud: - **The host sends in layers.** A host going live from the browser sends the picture in several sizes, and OBS sends up to three with its **Total Layers** setting ([How to stream from OBS to WordPress over WHIP](https://stream.wordplus.cloud/blog/stream-from-obs-to-wordpress/)). Each viewer gets the size their player and connection need, so a phone gets less than a big screen. - **The camera is checked as it goes live.** The browser of the host tries H.264 first, which plays on the most devices, and moves to VP9, then VP8, if the computer cannot keep up with it. - **Each viewer holds about a second** while their connection plays smoothly. If the picture freezes while packets of it are lost, the player holds two seconds, then three, and comes back down after minutes without trouble. The sound follows the picture, so lips and voice stay together. The **Statistics** of the player show the buffer as it changes. - **No app.** Viewers watch on the page of your site, in the browser. The whole delay is that buffer plus the way through the network, so on a smooth connection viewers stay within a couple of seconds of the host, and the chat beside the picture is about what is on screen. ## When HLS is the better choice WebRTC is not always the answer: - **Rewinding.** HLS players can go back to an earlier moment of a live stream. A WebRTC stream is always at the live moment. - **A passive audience of millions.** If nobody needs to talk back, files on a CDN are the cheapest way to reach a huge crowd. - **Recordings.** A recorded stream is played as files anyway. Live Stream plays over WebRTC only today. Its replays are recordings, played after the stream ends. ## Frequently asked questions ### Is WebRTC only for small audiences? No. With media servers passing the stream on, one host reaches many viewers. A stream in Live Stream has no limit of viewers: each site streams to 50 at once unmetered, and each viewer above that takes a credit a minute ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). ### Does a lower delay cost picture quality? A small buffer leaves less time to ask for a lost packet again. That is why the buffer of a Live Stream player grows when its connection loses packets, and why layers let a slow connection step down to a smaller picture instead of stopping. ### Do viewers need a special browser? No. Every current browser plays WebRTC, on computers and phones. ### What delay can I expect from YouTube or Facebook Live? These platforms deliver over HLS or DASH, and some offer a low latency mode. Expect a few seconds at best, more for viewers far away or on slow connections. --- # A Live Stream Inside a Better Messages Chat Room Address: https://stream.wordplus.cloud/blog/live-stream-in-a-better-messages-chat-room/ A community already talks in its chat rooms. When someone goes live, the natural place to watch is right there, beside the conversation the members are already in. With Live Stream and [Better Messages](https://www.better-messages.com/), a chat room can host a live stream: it shows in the room the way a group video call does, and the room is the chat of the stream, with its history, its moderation and its members. This post shows what members see, how a host goes live from the room, and how to set it up. ![A Better Messages chat room with a live stream: the host on camera with a Live badge and seven watching, the messages of the room beside the stream, and the controls of the player among those of a call](https://stream.wordplus.cloud/img/blog/better-messages-room.webp) ## Why stream in a chat room Live Stream has its own **light chat**: text and emoji for the moment, with moderation, run by WordPlus Cloud and gone a day after the last message. That suits a public show. A community usually wants more: - **The conversation stays.** Messages are saved on your site, with history and export, so what was said during the stream is there the next day. - **Everything a chat room has:** files, GIFs, stickers, mentions, and the notifications and moderation of Better Messages. - **The people are already there.** Members do not go to another page to watch, and the room is where they talk about the stream before it starts and after it ends. ## What members see - **The stream beside the messages.** While the stream of a room is live, it opens by itself where a group video call would, beside the messages of the room. - **A Live banner** over the messages and a button in the header of the room bring it back after someone closes it. - **The player among the call controls:** sound and volume, the quality of the picture, reactions, picture-in-picture and full screen. - **On a phone,** the stream sits on top and the chat under it. A member who closes the stream stays in the chat, and is not counted as watching until they open it again. Where the stream should not be closed while it is live, **Always on screen in the room** keeps it there. ## Going live from the room The host goes live without leaving the conversation. The button in the header of the room opens their preview, with the camera, the microphone and screen sharing in the call controls, then **Go live** and, at the end, **End stream**. While live, the host sees how the picture goes out and how many watch, and a summary once it ends. For scenes, overlays and several cameras, the host streams from OBS in **Live Stream → Studio** instead, and the stream still shows in the room ([How to stream from OBS to WordPress over WHIP](https://stream.wordplus.cloud/blog/stream-from-obs-to-wordpress/)). ## Setting it up ### What you need - **Better Messages 3.1 or later, its WebSocket version** with an active licence. Its free version has no realtime connection, so every viewer would keep asking your site for new messages. - **Live Stream**, on the same WordPlus Cloud subscription. A site whose Better Messages already runs on it is connected without entering a key again. ### From the room 1. Open **Better Messages → Chat Rooms** and edit the room. 2. Below the group call settings, choose **Stream in this room**. Live Stream makes a stream for the room, named after it, with the room as its chat. 3. The room now has a **Live streaming** section with **Go live**, **Stream settings**, **Always on screen in the room** and **Stop streaming here**. ### From the stream Or start in Live Stream: open **Live Stream → Studio → Streams**, choose the stream, and set its chat to **Better Messages chat room**. The room is made when you save. A new stream gets one by itself where Better Messages runs its WebSocket version with an active licence. **Stop streaming here** takes the stream out of the room, and the stream keeps a light chat of its own. ## Who can watch and who can write Each stream chooses who watches: everyone, logged-in members, or the roles you choose. Who writes in the room, guests, files and moderators are the settings of the room, under **Better Messages → Chat Rooms**. On a public stream, visitors chat as guests where the room allows them. The room shows wherever the chat of the stream does: beside the player on the page of the stream, in the studio of the host, and in Better Messages itself. ## Ideas for a community - **A weekly Q&A** in the main room of the community, the questions saved for those who missed it. - **A members only room** for paying members, with a stream only their role may watch. - **A course cohort** whose teacher goes live in the room of the class, with the files of the lesson shared in the same chat. - **A launch or an event** where the room fills up before the start, and keeps talking after the end. ## Frequently asked questions ### Does Live Stream need Better Messages? No. Live Stream works on its own, with its light chat. Better Messages adds the chat room. ### Does Better Messages carry anything of Live Stream when it is not installed? No. Better Messages shows a row about Live Stream in the room editor of its WebSocket version, and nothing else until Live Stream is installed. ### Can members go live in a room? Administrators host streams. Another plugin can let more people host with the hooks of Live Stream ([Live streams in your plugin](https://stream.wordplus.cloud/docs/developers/)). ### Where are the docs? On both sides: [Chat and moderation](https://stream.wordplus.cloud/docs/chat/) in the docs of Live Stream, and [Live streaming in chat rooms](https://www.better-messages.com/docs/websocket/live-streaming/) in the docs of Better Messages. --- # How to Run Live Classes and Webinars on WordPress Address: https://stream.wordplus.cloud/blog/live-classes-and-webinars-on-wordpress/ A live class and a webinar have the same shape. A teacher or a speaker goes live at a set time, shows their face and their slides, and talks to people who signed up for it. Those people ask questions in a chat, and someone keeps the chat friendly. Afterwards, everyone wants to know when the next one is. Most sites run them on a meeting tool and send people a link. This post shows how to run them on your own WordPress pages instead, with Live Stream, for the people your site already knows: what each part takes, how to set it up, and where a meeting tool is still the better choice. ![The page of a scheduled stream before it starts: a countdown over the cover of the stream, with Add to calendar, and the chat beside it](https://stream.wordplus.cloud/img/shots/countdown.webp) ## What a live class needs - **A time, and a way to remember it.** A countdown on the page, and an entry in the calendar of each student. - **Only the right people in.** Students of the course, members of a plan, or everyone with an account. - **The teacher and the slides.** A camera, and a screen to share, or a produced picture from OBS. - **Questions.** A chat beside the picture, close enough to the moment that the teacher answers while it still matters, and tools to keep it on topic. - **A page for each class**, and a list of what is coming up. ## Schedule the class, with a countdown Create a stream in **Live Stream → Studio → Streams** and give it a time in its **Schedule** setting. Until the teacher goes live, its page shows the cover, a countdown to the start with its date and time, and **Add to calendar**, for Google Calendar or a calendar file for Apple Calendar and Outlook. When the teacher goes live, everyone waiting sees the class begin without reloading. A weekly class or a webinar series keeps one stream with many times: one page, one chat and one OBS key, with nothing to change between sessions. - Give each time a title of its own, such as "Spanish for beginners, lesson 4", and the countdown says it. - **Repeat these weekly** copies the times on for the weeks you choose. - After a session ends, viewers see the thanks with the next time under it, then the countdown to it. The **Live now** block, or `[wordplus_stream_live show="both"]`, lists the classes live right now and those coming up, each at its next time. ## Let only your students in Each stream has a **Who can watch** setting: everyone, logged-in users, or selected roles. For a class of paying members, choose their role. Membership and course plugins can decide more finely with the `wordplus_stream_can_watch` filter, which gets the decision of the stream and the ID of the user, and returns whether that user may watch: ```php add_filter( 'wordplus_stream_can_watch', function ( $can, $rules, $user_id ) { // Only students with an active membership watch. return $can && my_membership_is_active( $user_id ); }, 10, 3 ); ``` Nobody else can join it. ## Teach with your camera and your screen The teacher goes live from **Live Stream → Studio** in the browser: the camera, the microphone, and **Share screen** for slides, a document or a browser tab. The microphone is tuned for speech, with echo and background noise removed by the browser. The room behind the teacher can be blurred or replaced with a picture, and **AI noise removal** takes typing and fans out of the microphone ([Background blur, backgrounds and noise removal](https://stream.wordplus.cloud/docs/effects/)). For a produced class, with the slides and the camera in one picture, a lower third with the name of the teacher, or a second camera on a whiteboard, stream from OBS instead ([How to stream from OBS to WordPress over WHIP](https://stream.wordplus.cloud/blog/stream-from-obs-to-wordpress/)). Viewers watch in the browser over WebRTC, about a second behind the teacher on a smooth connection, so the chat is about what is on screen ([Low latency live streaming: why WebRTC](https://stream.wordplus.cloud/blog/low-latency-live-streaming-webrtc/)). ## Questions, and a chat that stays on topic The chat beside the player is where students ask. For a class, these tools help: - **Pin message** holds the topic, a link to the slides or the question being answered over the chat. - **Slow mode** allows one message every 5, 10, 30 or 60 seconds, so a big class does not drown the questions. - **Links** only from moderators keep spam out. - **Moderators** are the hosts, the comment moderators of the site, and the roles you choose, such as teaching assistants. They delete messages, mute someone for a minute or a day, remove them from the stream or ban them. For a class whose conversation should stay, with files and history, make the chat a Better Messages chat room ([A live stream inside a Better Messages chat room](https://stream.wordplus.cloud/blog/live-stream-in-a-better-messages-chat-room/)). ## A page for each class **Create a page** beside the stream in the Studio publishes a page with the stream and the chat beside it. Or start a page from the **Webinar** or **Live event** block pattern, or add the **Live stream** block to the page of a course or a lesson. Course plugins can go further with the API of Live Stream, which gives each course its own stream, made and found by the course: ```php $stream_id = wordplus_streams()->create( array( 'title' => 'Weekly class', 'object_type' => 'my_course', 'object_id' => 42, 'settings' => array( 'access' => 'logged_in', 'chat_with' => 'light' ), ) ); ``` Hooks decide who hosts each stream, so the teacher of a course can go live from the page of the course, without access to the WordPress admin ([Live streams in your plugin](https://stream.wordplus.cloud/docs/developers/)). ## Where a meeting tool is still better - **Students on camera.** Live Stream is a broadcast: the teacher is on camera, and students write. For a seminar where everyone speaks, use a meeting tool. - **Recordings.** Live Stream records a class and plays the replay on its page ([Recording and replays](https://stream.wordplus.cloud/docs/recording/)). - **Hosts.** Administrators host every stream, unless a plugin lets more people host with the hooks above. ## What it costs Live Stream is free to download and streams on a WordPlus Cloud subscription. Each site streams to 50 viewers at once unmetered, however long the class lasts, and each viewer above that takes a credit a minute. Each WordPress site adds 5,000 credits a month to its account ([Viewers and credits](https://stream.wordplus.cloud/docs/viewers-and-credits/)). ## Frequently asked questions ### Can students join without an account? Yes, if you let them: a stream for everyone needs no account. Students who are not logged in read the chat, and write in it as Guest where the stream allows it. ### How many students can watch? As many as come: a stream has no limit of viewers. The first 50 at once on each site are unmetered. ### Can I run a class every week on the same page? Yes. Give the stream a time for each session, or **Repeat these weekly**, and it keeps its page, its chat and its OBS key. ### Does it work with my LMS? Any course or membership plugin can decide who watches with the `wordplus_stream_can_watch` filter, and its pages can show a stream with the block or the shortcode. The developer API gives each course a stream of its own.