Sign inConnect your agent
infochanged

Stream - Ultra-low latency live with WebRTC is now Generally Available in Stream

Announced
Tags
Stream
Severity
info, set by reef/rss-rule-v1
Source
https://developers.cloudflare.com/changelog/post/2026-10-15-stream-live-webrtc-ga/

<p><a href="https://developers.cloudflare.com/stream/webrtc-beta/" target="_blank" rel="noopener">Stream WebRTC support<span class="external-link"> ↗︎</span></a> lets you deliver high quality live video to thousands of concurrent viewers in milliseconds. WebRTC is compatible with native Web APIs and standard protocols, so creators can <a href="https://developers.cloudflare.com/stream/examples/browser-based-webrtc/" target="_blank" rel="noopener">go live from a browser<span class="external-link"> ↗︎</span></a> without needing a separate broadcast application. This powers platforms to build custom experiences with deep feature integration for creators as well as viewers. Here's how to get started with a Stream live input and a browser.</p> <p>Usage-based billing for WebRTC begins today, October 15, 2026 and follows the standard rates for minutes of video delivered. Refer to <a href="https://developers.cloudflare.com/stream/pricing/" target="_blank" rel="noopener">pricing<span class="external-link"> ↗︎</span></a> for rates.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="what-changed">What changed</h4><a class="anchor-link" href="#what-changed"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <p>While in beta, Stream’s WebRTC support was rebuilt from the ground up to leverage <a href="https://developers.cloudflare.com/realtime/" target="_blank" rel="noopener">Cloudflare Realtime<span class="external-link"> ↗︎</span></a>’s primitives for stability and scale while managing these components in Stream’s familiar, unified API that makes it easy to build. We also adopted the latest WHIP and WHEP protocol standards for Trickle ICE, server and client offer modes, and counter-offer support for improved player library compatibility and network traversal adaptability. Finally, WebRTC delivery will now be visible in Stream’s <a href="https://developers.cloudflare.com/stream/getting-analytics/" target="_blank" rel="noopener">analytics<span class="external-link"> ↗︎</span></a> and billable usage charts.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="how-does-this-relate-to-cloudflare-realtime">How does this relate to Cloudflare Realtime</h4><a class="anchor-link" href="#how-does-this-relate-to-cloudflare-realtime"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <p>Realtime exposes a set of tools and primitives to build applications that connect people, AI systems, and devices together in many-to-many experiences powered by WebRTC. Stream leverages these building-blocks to deliver one-to-many broadcast capabilities, controlled and managed by a single, unified API with features like the <a href="https://developers.cloudflare.com/stream/viewing-videos/using-the-stream-player/" target="_blank" rel="noopener">built-in player<span class="external-link"> ↗︎</span></a> and <a href="https://developers.cloudflare.com/stream/getting-analytics/" target="_blank" rel="noopener">analytics<span class="external-link"> ↗︎</span></a> that make it easy to get started.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="how-do-i-get-started">How do I get started</h4><a class="anchor-link" href="#how-do-i-get-started"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <p>First, <a href="https://developers.cloudflare.com/stream/examples/browser-based-webrtc/#1-create-a-live-input" target="_blank" rel="noopener">create a live input<span class="external-link"> ↗︎</span></a> using <a href="https://developers.cloudflare.com/cf/" target="_blank" rel="noopener">cf<span class="external-link"> ↗︎</span></a>, the API, or in the <a href="https://dash.cloudflare.com/?to=/:account/stream/inputs" target="_blank" rel="noopener">Stream Dashboard<span class="external-link"> ↗︎</span></a>:</p> <figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="sh"><figcaption class="nb-code-title"><span class="nb-code-title-name">Creating a live input with cf or API</span><span class="nb-code-title-lang">sh</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="sh" data-nb-lang="sh"><code><span class="line"><span class="nb-shiki-21nrsd"># Using cf, the new Cloudflare CLI</span></span> <span class="line"><span class="nb-shiki-1t8gfj">cf</span><span class="nb-shiki-mdbnqw"> stream</span><span class="nb-shiki-mdbnqw"> live-inputs</span><span class="nb-shiki-mdbnqw"> create</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"># Using an API request,</span></span> <span class="line"><span class="nb-shiki-1t8gfj">curl</span><span class="nb-shiki-mdbnqw"> https://api.cloudflare.com/client/v4/accounts/</span><span class="nb-shiki-140thh">$ACCOUNT_ID</span><span class="nb-shiki-mdbnqw">/stream/live_inputs</span><span class="nb-shiki-dzsirb"> \</span></span> <span class="line"><span class="nb-shiki-dzsirb"> -H</span><span class="nb-shiki-mdbnqw"> 'Content-Type: application/json'</span><span class="nb-shiki-dzsirb"> \</span></span> <span class="line"><span class="nb-shiki-dzsirb"> -H</span><span class="nb-shiki-mdbnqw"> "Authorization: Bearer </span><span class="nb-shiki-140thh">$CLOUDFLARE_API_TOKEN</span><span class="nb-shiki-mdbnqw">"</span><span class="nb-shiki-dzsirb"> \</span></span> <span class="line"><span class="nb-shiki-dzsirb"> -X</span><span class="nb-shiki-mdbnqw"> POST</span></span></code></pre></figure> <p>The response will include <code>webRTC</code> and <code>webRTCPlayback</code> properties, each containing a <code>url</code> for WHIP (broadcast) and WHEP (playback) respectively.</p> <p>Next, you can go live using WHIP directly from a browser or supported broadcast software. Refer to our <a href="https://developers.cloudflare.com/stream/examples/browser-based-webrtc/" target="_blank" rel="noopener">new tutorial<span class="external-link"> ↗︎</span></a> that shows a dependency-free way to broadcast live video with browser-native JavaScript.</p> <p>Finally, you can play using WHEP using Stream’s <a href="https://developers.cloudflare.com/stream/viewing-videos/using-the-stream-player/" target="_blank" rel="noopener">built-in player<span class="external-link"> ↗︎</span></a>, a supported player app/library, or simple JavaScript:</p> <figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="js"><figcaption class="nb-code-title"><span class="nb-code-title-name">Abbreviated JavaScript playback example</span><span class="nb-code-title-lang">js</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="js" data-nb-lang="js"><code><span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> pc</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> RTCPeerConnection</span><span class="nb-shiki-140thh">();</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // 1. Ask to receive one audio track and one video track.</span></span> <span class="line"><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">addTransceiver</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"video"</span><span class="nb-shiki-140thh">, { direction: </span><span class="nb-shiki-mdbnqw">"recvonly"</span><span class="nb-shiki-140thh"> });</span></span> <span class="line"><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">addTransceiver</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"audio"</span><span class="nb-shiki-140thh">, { direction: </span><span class="nb-shiki-mdbnqw">"recvonly"</span><span class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // 2. Attach incoming media to the video element as it arrives.</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> stream</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> MediaStream</span><span class="nb-shiki-140thh">();</span></span> <span class="line"><span class="nb-shiki-140thh"> document.</span><span class="nb-shiki-1t8gfj">getElementById</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"playback-video"</span><span class="nb-shiki-140thh">).srcObject </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> stream;</span></span> <span class="line"><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">ontrack</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> (</span><span class="nb-shiki-1jdh33">event</span><span class="nb-shiki-140thh">) </span><span class="nb-shiki-1itgoe">=&gt;</span><span class="nb-shiki-140thh"> stream.</span><span class="nb-shiki-1t8gfj">addTrack</span><span class="nb-shiki-140thh">(event.track);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // 3. Create the SDP offer and set it as the local description.</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> offer</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">createOffer</span><span class="nb-shiki-140thh">();</span></span> <span class="line"><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">setLocalDescription</span><span class="nb-shiki-140thh">(offer);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // 4. POST the offer to the WHEP endpoint.</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> response</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">WHEP_URL</span><span class="nb-shiki-140thh">, {</span></span> <span class="line"><span class="nb-shiki-140thh"> method: </span><span class="nb-shiki-mdbnqw">"POST"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> headers: { </span><span class="nb-shiki-mdbnqw">"Content-Type"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"application/sdp"</span><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> body: offer.sdp,</span></span> <span class="line"><span class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // 5. Apply the SDP answer returned by Cloudflare.</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> answer</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> response.</span><span class="nb-shiki-1t8gfj">text</span><span class="nb-shiki-140thh">();</span></span> <span class="line"><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> pc.</span><span class="nb-shiki-1t8gfj">setRemoteDescription</span><span class="nb-shiki-140thh">({ type: </span><span class="nb-shiki-mdbnqw">"answer"</span><span class="nb-shiki-140thh">, sdp: answer });</span></span></code></pre></figure> <p>Learn more in the <a href="https://developers.cloudflare.com/stream/webrtc-beta/" target="_blank" rel="noopener">Stream WebRTC<span class="external-link"> ↗︎</span></a> docs or <a href="https://developers.cloudflare.com/stream/examples/browser-based-webrtc/" target="_blank" rel="noopener">try the all-in-one tutorial<span class="external-link"> ↗︎</span></a> for yourself.</p>

The text above is the source's. reef added the severity, the dates it could read from the text, and the endpoints and scopes named in code.