
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Wed, 15 Apr 2026 21:18:29 GMT</lastBuildDate>
        <item>
            <title><![CDATA[MoQ: Refactoring the Internet's real-time media stack]]></title>
            <link>https://blog.cloudflare.com/moq/</link>
            <pubDate>Fri, 22 Aug 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Media over QUIC (MoQ) is a new IETF standard that resolves this conflict, creating a single foundation for sub-second, interactive streaming at a global scale.
 ]]></description>
            <content:encoded><![CDATA[ <p>For over two decades, we've built real-time communication on the Internet using a patchwork of specialized tools. RTMP gave us ingest. <a href="https://www.cloudflare.com/learning/video/what-is-http-live-streaming/"><u>HLS</u></a> and <a href="https://www.mpeg.org/standards/MPEG-DASH/"><u>DASH</u></a> gave us scale. WebRTC gave us interactivity. Each solved a specific problem for its time, and together they power the global streaming ecosystem we rely on today.</p><p>But using them together in 2025 feels like building a modern application with tools from different eras. The seams are starting to show—in complexity, in latency, and in the flexibility needed for the next generation of applications, from sub-second live auctions to massive interactive events. We're often forced to make painful trade-offs between latency, scale, and operational complexity.</p><p>Today Cloudflare is launching the first Media over QUIC (MoQ) relay network, running on every Cloudflare server in datacenters in 330+ cities. MoQ is an open protocol being developed at the <a href="https://www.ietf.org/"><u>IETF</u></a> by engineers from across the industry—not a proprietary Cloudflare technology. MoQ combines the low-latency interactivity of WebRTC, the scalability of HLS/DASH, and the simplicity of a single architecture, all built on a modern transport layer. We're joining Meta, Google, Cisco, and others in building implementations that work seamlessly together, creating a shared foundation for the next generation of real-time applications on the Internet.</p>
    <div>
      <h3><b>An evolutionary ladder of compromise</b></h3>
      <a href="#an-evolutionary-ladder-of-compromise">
        
      </a>
    </div>
    <p>To understand the promise of MoQ, we first have to appreciate the history that led us here—a journey defined by a series of architectural compromises where solving one problem inevitably created another.</p><p><b>The RTMP era: Conquering latency, compromising on scale</b></p><p>In the early 2000s, <b>RTMP (Real-Time Messaging Protocol)</b> was a breakthrough. It solved the frustrating "download and wait" experience of early video playback on the web by creating a persistent, stateful TCP connection between a <a href="https://en.wikipedia.org/wiki/Adobe_Flash"><u>Flash</u></a> client and a server. This enabled low-latency streaming (2-5 seconds), powering the first wave of live platforms like <a href="http://justin.tv"><u>Justin.tv</u></a> (which later became Twitch).</p><p>But its strength was its weakness. That stateful connection, which had to be maintained for every viewer, was architecturally hostile to scale. It required expensive, specialized media servers and couldn't use the commodity HTTP-based <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/"><u>Content Delivery Networks (CDNs)</u></a> that were beginning to power the rest of the web. Its reliance on TCP also meant that a single lost packet could freeze the entire stream—a phenomenon known as <a href="https://blog.cloudflare.com/the-road-to-quic/#head-of-line-blocking"><u>head-of-line blocking</u></a>—creating jarring latency spikes. The industry retained RTMP for the "first mile" from the camera to servers (ingest), but a new solution was needed for the "last mile" from servers to your screen (delivery).</p><p><b>The HLS &amp; DASH era: Solving for scale, compromising on latency</b></p><p>The catalyst for the next era was the iPhone's rejection of Flash. In response, Apple created <a href="https://www.cloudflare.com/learning/video/what-is-http-live-streaming/"><b><u>HLS (HTTP Live Streaming)</u></b></a>. HLS, and its open-standard counterpart <b>MPEG-DASH</b> abandoned stateful connections and treated video as a sequence of small, static files delivered over standard HTTP.</p><p>This enabled much greater scalability. By moving to the interoperable open standard of HTTP for the underlying transport, video could now be distributed by any web server and cached by global CDNs, allowing platforms to reach millions of viewers reliably and relatively inexpensively. The compromise? A <i>significant</i> trade-off in latency. To ensure smooth playback, players needed to buffer at least three video segments before starting. With segment durations of 6-10 seconds, this baked 15-30 seconds of latency directly into the architecture.</p><p>While extensions like <a href="https://developer.apple.com/documentation/http-live-streaming/enabling-low-latency-http-live-streaming-hls"><u>Low-Latency HLS (LL-HLS)</u></a> have more recently emerged to achieve latencies in the 3-second range, they remain complex patches<a href="https://blog.cloudflare.com/the-road-to-quic/#head-of-line-blocking"><u> fighting against the protocol's fundamental design</u></a>. These extensions introduce a layer of stateful, real-time communication—using clever workarounds like holding playlist requests open—that ultimately strain the stateless request-response model central to HTTP's scalability and composability.</p><p><b>The WebRTC Era: Conquering conversational latency, compromising on architecture</b></p><p>In parallel, <b>WebRTC (Web Real-Time Communication)</b> emerged to solve a different problem: plugin-free, two-way conversational video with sub-500ms latency within a browser. It worked by creating direct peer-to-peer (P2P) media paths, removing central servers from the equation.</p><p>But this P2P model is fundamentally at odds with broadcast scale. <a href="https://blog.cloudflare.com/cloudflare-calls-anycast-webrtc/#webrtc-growing-pains"><u>In a mesh network, the number of connections grows quadratically with each new participant</u></a> (the "N-squared problem"). For more than a handful of users, the model collapses under the weight of its own complexity. To work around this, the industry developed server-based topologies like the Selective Forwarding Unit (SFU) and Multipoint Control Unit (MCU). These are effective but require building what is essentially a <a href="https://blog.cloudflare.com/cloudflare-calls-anycast-webrtc/#is-cloudflare-calls-a-real-sfu"><u>private, stateful, real-time CDN</u></a>—a complex and expensive undertaking that is not standardized across infrastructure providers.</p><p>This journey has left us with a fragmented landscape of specialized, non-interoperable silos, forcing developers to stitch together multiple protocols and accept a painful three-way tension between <b>latency, scale, and complexity</b>.</p>
    <div>
      <h3><b>Introducing MoQ</b></h3>
      <a href="#introducing-moq">
        
      </a>
    </div>
    <p>This is the context into which Media over QUIC (MoQ) emerges. It's not just another protocol; it's a new design philosophy built from the ground up to resolve this historical trilemma. Born out of an open, community-driven effort at the IETF, <u>MoQ aims to be a foundational Internet technology, not a proprietary product</u>.</p><p>Its promise is to unify the disparate worlds of streaming by delivering:</p><ol><li><p><b>Sub-second latency at broadcast scale:</b> Combining the latency of WebRTC with the scale of HLS/DASH and the simplicity of RTMP.</p></li><li><p><b>Architectural simplicity:</b> Creating a single, flexible protocol for ingest, distribution, and interactive use cases, eliminating the need to transcode between different technologies.</p></li><li><p><b>Transport efficiency:</b> Building on <a href="https://blog.cloudflare.com/the-road-to-quic/"><u>QUIC</u></a>, a <a href="https://www.cloudflare.com/learning/ddos/glossary/user-datagram-protocol-udp/"><u>UDP</u></a> based protocol to eliminate bottlenecks like TCP<a href="https://blog.cloudflare.com/the-road-to-quic/#head-of-line-blocking"><u> head-of-line blocking</u></a>.</p></li></ol><p>The initial focus was "Media" over QUIC, but the core concepts—named tracks of timed, ordered, but independent data—are so flexible that the working group is now simply calling the protocol "MoQ." The name reflects the power of the abstraction: it's a generic transport for any real-time data that needs to be delivered efficiently and at scale.</p><p>MoQ is now generic enough that it’s a data fanout or pub/sub system, for everything from audio/video (high bandwidth data) to sports score updates (low bandwidth data).</p>
    <div>
      <h3><b>A deep dive into the MoQ protocol stack</b></h3>
      <a href="#a-deep-dive-into-the-moq-protocol-stack">
        
      </a>
    </div>
    <p>MoQ's elegance comes from solving the right problem at the right layer. Let's build up from the foundation to see how it achieves sub-second latency at scale.</p><p>The choice of QUIC as MoQ's foundation isn't arbitrary—it addresses issues that have plagued streaming protocols for decades.</p><p>By building on <b>QUIC</b> (the transport protocol that also powers <a href="https://www.cloudflare.com/learning/performance/what-is-http3/"><u>HTTP/3</u></a>), MoQ solves some key streaming problems:</p><ul><li><p><b>No head-of-line blocking:</b> Unlike TCP where one lost packet blocks everything behind it, QUIC streams are independent. A lost packet on one stream (e.g., an audio track) doesn't block another (e.g., the main video track). This alone eliminates the stuttering that plagued RTMP.</p></li><li><p><b>Connection migration:</b> When your device switches from Wi-Fi to cellular mid-stream, the connection seamlessly migrates without interruption—no rebuffering, no reconnection.</p></li><li><p><b>Fast connection establishment:</b> QUIC's <a href="https://blog.cloudflare.com/even-faster-connection-establishment-with-quic-0-rtt-resumption/"><u>0-RTT resumption</u></a> means returning viewers can start playing instantly.</p></li><li><p><b>Baked-in, mandatory encryption:</b> All QUIC connections are encrypted by default with <a href="https://blog.cloudflare.com/rfc-8446-aka-tls-1-3/"><u>TLS 1.3</u></a>.</p></li></ul>
    <div>
      <h4>The core innovation: Publish/subscribe for media</h4>
      <a href="#the-core-innovation-publish-subscribe-for-media">
        
      </a>
    </div>
    <p>With QUIC solving transport issues, MoQ introduces its key innovation: treating media as subscribable tracks in a publish/subscribe system. But unlike traditional pub/sub, this is designed specifically for real-time media at CDN scale.</p><p>Instead of complex session management (WebRTC) or file-based chunking (HLS), <b>MoQ lets publishers announce named tracks of media that subscribers can request</b>. A relay network handles the distribution without needing to understand the media itself.</p>
    <div>
      <h4>How MoQ organizes media: The data model</h4>
      <a href="#how-moq-organizes-media-the-data-model">
        
      </a>
    </div>
    <p>Before we see how media flows through the network, let's understand how MoQ structures it. MoQ organizes data in a hierarchy:</p><ul><li><p><b>Tracks</b>: Named streams of media, like "video-1080p" or "audio-english". Subscribers request specific tracks by name.</p></li><li><p><b>Groups</b>: Independently decodable chunks of a track. For video, this typically means a GOP (Group of Pictures) starting with a keyframe. New subscribers can join at any Group boundary.</p></li><li><p><b>Objects</b>: The actual packets sent on the wire. Each Object belongs to a Track and has a position within a Group.</p></li></ul><p>This simple hierarchy enables two capabilities:</p><ol><li><p>Subscribers can start playback at <b>Group</b> boundaries without waiting for the next keyframe</p></li><li><p>Relays can forward <b>Objects</b> without parsing or understanding the media format</p></li></ol>
    <div>
      <h5>The network architecture: From publisher to subscriber</h5>
      <a href="#the-network-architecture-from-publisher-to-subscriber">
        
      </a>
    </div>
    <p>MoQ’s network components are also simple:</p><ul><li><p><b>Publishers</b>: Announce track namespaces and send Objects</p></li><li><p><b>Subscribers</b>: Request specific tracks by name</p></li><li><p><b>Relays</b>: Connect publishers to subscribers by forwarding immutable Objects without parsing or <a href="https://www.cloudflare.com/learning/video/video-encoding-formats/"><u>transcoding</u></a> the media</p></li></ul><p>A Relay acts as a subscriber to receive tracks from upstream (like the original publisher) and simultaneously acts as a publisher to forward those same tracks downstream. This model is the key to MoQ's scalability: one upstream subscription can fan out to serve thousands of downstream viewers.</p>
    <div>
      <h5>The MoQ Stack</h5>
      <a href="#the-moq-stack">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4g2MroH24otkzH3LQsFWZe/84ca43ad6c1c933ac395bf4ac767c584/image1.png" />
          </figure><p>MoQ's architecture can be understood as three distinct layers, each with a clear job:</p><ol><li><p><b>The Transport Foundation (QUIC or WebTransport):</b> This is the modern foundation upon which everything is built. MoQT can run directly over raw <b>QUIC</b>, which is ideal for native applications, or over <b>WebTransport</b>, which is required for use in a web browser. Crucially, the<a href="https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-02.html"> <u>WebTransport protocol</u></a> and its corresponding<a href="https://w3c.github.io/webtransport/"> <u>W3C browser API</u></a> make QUIC's multiplexed reliable streams and unreliable datagrams directly accessible to browser applications. This is a game-changer. Protocols like <a href="https://blog.cloudflare.com/stream-now-supports-srt-as-a-drop-in-replacement-for-rtmp/"><u>SRT</u></a> may be efficient, but their lack of native browser support relegates them to ingest-only roles. WebTransport gives MoQ first-class citizenship on the web, making it suitable for both ingest and massive-scale distribution directly to clients.</p></li><li><p><b>The MoQT Layer:</b> Sitting on top of QUIC (or WebTransport), the MoQT layer provides the signaling and structure for a publish-subscribe system. This is the primary focus of the IETF working group. It defines the core control messages—like ANNOUNCE, and SUBSCRIBE—and the basic data model we just covered. MoQT itself is intentionally spartan; it doesn't know or care if the data it's moving is <a href="https://www.cloudflare.com/learning/video/what-is-h264-avc/"><u>H.264</u></a> video, Opus audio, or game state updates.</p></li><li><p><b>The Streaming Format Layer:</b> This is where media-specific logic lives. A streaming format defines things like manifests, codec metadata, and packaging rules.
 <a href="https://datatracker.ietf.org/doc/draft-ietf-moq-warp/"><b><u>WARP</u></b></a> is one such format being developed alongside MoQT at the IETF, but it isn't the only one. Another standards body, like DASH-IF, could define a <a href="https://www.iso.org/standard/85623.html"><u>CMAF</u></a>-based streaming format over MoQT. A company that controls both original publisher and end subscriber can develop its own proprietary streaming format to experiment with new codecs or delivery mechanisms without being constrained by the transport protocol.</p></li></ol><p>This separation of layers is why different organizations can build interoperable implementations while still innovating at the streaming format layer.</p>
    <div>
      <h4>End-to-End Data Flow</h4>
      <a href="#end-to-end-data-flow">
        
      </a>
    </div>
    <p>Now that we understand the architecture and the data model, let's walk through how these pieces come together to deliver a stream. The protocol is flexible, but a typical broadcast flow relies on the <code>ANNOUNCE</code> and <code>SUBSCRIBE </code>messages to establish a data path from a publisher to a subscriber through the relay network.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2iRTJFdtCjIOcyg7ezoYgJ/e303ea8d1eb438328b60fdb28be47e84/image2.png" />
          </figure><p>Here is a step-by-step breakdown of what happens in this flow:</p><ol><li><p><b>Initiating Connections:</b> The process begins when the endpoints, acting as clients, connect to the relay network. The Original Publisher initiates a connection with its nearest relay (we'll call it Relay A). Separately, an End Subscriber initiates a connection with its own local relay (Relay B). These endpoints perform a <code>SETUP</code> handshake with their respective relays to establish a MoQ session and declare supported parameters.</p></li><li><p><b>Announcing a Namespace:</b> To make its content discoverable, the Publisher sends an <code>ANNOUNCE</code> message to Relay A. This message declares that the publisher is the authoritative source for a given <b>track namespace</b>. Relay A receives this and registers in a shared control plane (a conceptual database) that it is now a source for this namespace within the network.</p></li><li><p><b>Subscribing to a Track:</b> When the End Subscriber wants to receive media, it sends a <code>SUBSCRIBE</code> message to its relay, Relay B. This message is a request for a specific <b>track name</b> within a specific <b>track namespace</b>.</p></li><li><p><b>Connecting the Relays:</b> Relay B receives the <code>SUBSCRIBE</code> request and queries the control plane. It looks up the requested namespace and discovers that Relay A is the source. Relay B then initiates a session with Relay A (if it doesn't already have one) and forwards the <code>SUBSCRIBE</code> request upstream.</p></li><li><p><b>Completing the Path and Forwarding Objects:</b> Relay A, having received the subscription request from Relay B, forwards it to the Original Publisher. With the full path now established, the Publisher begins sending the <code>Objects</code> for the requested track. The Objects flow from the Publisher to Relay A, which forwards them to Relay B, which in turn forwards them to the End Subscriber. If another subscriber connects to Relay B and requests the same track, Relay B can immediately start sending them the Objects without needing to create a new upstream subscription.</p></li></ol>
    <div>
      <h5>An Alternative Flow: The <code>PUBLISH</code> Model</h5>
      <a href="#an-alternative-flow-the-publish-model">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6KJYU1eWNyuSZEHNYonDDn/3898003d5a7f5904787c7ef009b22fe0/image3.png" />
          </figure><p>More recent drafts of the MoQ specification have introduced an alternative, push-based model using a <code>PUBLISH</code> message. In this flow, a publisher can effectively ask for permission to send a track's objects to a relay <i>without</i> waiting for a <code>SUBSCRIBE </code>request. The publisher sends a <code>PUBLISH</code> message, and the relay's <code>PUBLISH_OK</code> response indicates whether it will accept the objects. This is particularly useful for ingest scenarios, where a publisher wants to send its stream to an entry point in the network immediately, ensuring the media is available the instant the first subscriber connects.</p>
    <div>
      <h4>Advanced capabilities: Prioritization and congestion control</h4>
      <a href="#advanced-capabilities-prioritization-and-congestion-control">
        
      </a>
    </div>
    <p>MoQ’s benefits really shine when networks get congested. MoQ includes mechanisms for handling the reality of network traffic. One such mechanism is Subgroups.</p><p><b>Subgroups</b> are subdivisions within a Group that effectively map directly to the underlying QUIC streams. All Objects within the same Subgroup are generally sent on the same QUIC stream, guaranteeing their delivery order. Subgroup numbering also presents an opportunity to encode prioritization: within a Group, lower-numbered Subgroups are considered higher priority. </p><p>This enables intelligent quality degradation, especially with layered codecs (e.g. SVC):</p><ul><li><p><b>Subgroup 0</b>: Base video layer (360p) - must deliver</p></li><li><p><b>Subgroup 1</b>: Enhancement to 720p - deliver if bandwidth allows</p></li><li><p><b>Subgroup 2</b>: Enhancement to 1080p - first to drop under congestion</p></li></ul><p>When a relay detects congestion, it can drop Objects from higher-numbered Subgroups, preserving the base layer. Viewers see reduced quality instead of buffering.</p><p>The MoQ specification defines a scheduling algorithm that determines the order for all objects that are "ready to send." When a relay has multiple objects ready, it prioritizes them first by <b>group order</b> (ascending or descending) and then, within a group, by <b>subgroup id</b>. Our implementation supports the <b>group order</b> preference, which can be useful for low-latency broadcasts. If a viewer falls behind and its subscription uses descending group order, the relay prioritizes sending Objects from the newest "live" Group, potentially canceling unsent Objects from older Groups. This can help viewers catch up to the live edge quickly, a highly desirable feature for many interactive streaming use cases. The optimal strategies for using these features to improve QoE for specific use cases are still an open research question. We invite developers and researchers to use our network to experiment and help find the answers.</p>
    <div>
      <h3><b>Implementation: building the Cloudflare MoQ relay</b></h3>
      <a href="#implementation-building-the-cloudflare-moq-relay">
        
      </a>
    </div>
    <p>Theory is one thing; implementation is another. To validate the protocol and understand its real-world challenges, we've been building one of the first global MoQ relay networks. Cloudflare's network, which places compute and logic at the edge, is very well suited for this.</p><p>Our architecture connects the abstract concepts of MoQ to the Cloudflare stack. In our deep dive, we mentioned that when a publisher <code>ANNOUNCE</code>s a namespace, relays need to register this availability in a "shared control plane" so that <code>SUBSCRIBE</code> requests can be routed correctly. For this critical piece of state management, we use <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>.</p><p>When a publisher announces a new namespace to a relay in, say, London, that relay uses a Durable Object—our strongly consistent, single-threaded storage solution—to record that this namespace is now available at that specific location. When a subscriber in Paris wants a track from that namespace, the network can query this distributed state to find the nearest source and route the <code>SUBSCRIBE</code> request accordingly. This architecture builds upon the technology we developed for Cloudflare's real-time services and provides a solution to the challenge of state management at a global scale.</p>
    <div>
      <h4>An Evolving Specification</h4>
      <a href="#an-evolving-specification">
        
      </a>
    </div>
    <p>Building on a new protocol in the open means implementing against a moving target. To get MoQ into the hands of the community, we made a deliberate trade-off: our current relay implementation is based on a <b>subset of the features defined in </b><a href="https://www.ietf.org/archive/id/draft-ietf-moq-transport-07.html"><b><u>draft-ietf-moq-transport-07</u></b></a>. This version became a de facto target for interoperability among several open-source projects and pausing there allowed us to put effort towards other aspects of deploying our relay network<b>.</b></p><p>This draft of the protocol makes a distinction between accessing "past" and "future" content. <code><b>SUBSCRIBE</b></code> is used to receive <b>future</b> objects for a track as they arrive—like tuning into a live broadcast to get everything from that moment forward. In contrast, <code><b>FETCH</b></code> provides a mechanism for accessing <b>past</b> content that a relay may already have in its cache—like asking for a recording of a song that just played.</p><p>Both are part of the same specification, but for the most pressing low-latency use cases, a performant implementation of <code>SUBSCRIBE</code> is what matters most. For that reason, we have focused our initial efforts there and have not yet implemented <code>FETCH</code>.</p><p>This is where our roadmap is flexible and where the community can have a direct impact. Do you need <code>FETCH</code> to build on-demand or catch-up functionality? Or is more complete support for the prioritization features within <code>SUBSCRIBE</code> more critical for your use case? The feedback we receive from early developers will help us decide what to build next.</p><p>As always, we will announce our updates and changes to our implementation as we continue with development on our <a href="https://developers.cloudflare.com/moq"><u>developer docs pages</u></a>.</p>
    <div>
      <h3>Kick the tires on the future</h3>
      <a href="#kick-the-tires-on-the-future">
        
      </a>
    </div>
    <p>We believe in building in the open and interoperability in the community. MoQ is not a Cloudflare technology but a foundational Internet technology. To that end, the first demo client we’re presenting is an open source, community example.</p><p><b>You can access the demo here: </b><a href="https://moq.dev/publish/"><b><u>https://moq.dev/publish/</u></b></a></p><p>Even though this is a preview release, we are running MoQ relays at Cloudflare’s full scale, like we do every production service. This means every server that is part of the Cloudflare network in more than 330 cities is now a MoQ relay.</p><p>We invite you to experience the "wow" moment of near-instant, sub-second streaming latency that MoQ enables. How would you use a protocol that offers the speed of a video call with the scale of a global broadcast?</p>
    <div>
      <h3><b>Interoperability</b></h3>
      <a href="#interoperability">
        
      </a>
    </div>
    <p>We’ve been working with others in the IETF WG community and beyond on interoperability of publishers, players and other parts of the MoQ ecosystem. So far, we’ve tested with:</p><ul><li><p>Luke Curley’s <a href="https://moq.dev"><u>moq.dev</u></a></p></li><li><p>Lorenzo Miniero’s <a href="https://github.com/meetecho/imquic"><u>imquic</u></a></p></li><li><p>Meta’s <a href="https://github.com/facebookexperimental/moxygen"><u>Moxygen</u></a> </p></li><li><p><a href="https://github.com/englishm/moq-rs"><u>moq-rs</u></a></p></li><li><p><a href="https://github.com/englishm/moq-js"><u>moq-js</u></a></p></li><li><p><a href="https://norsk.video/"><u>Norsk</u></a></p></li><li><p><a href="https://vindral.com/"><u>Vindral</u></a></p></li></ul>
    <div>
      <h3>The Road Ahead</h3>
      <a href="#the-road-ahead">
        
      </a>
    </div>
    <p>The Internet's media stack is being refactored. For two decades, we've been forced to choose between latency, scale, and complexity. The compromises we made solved some problems, but also led to a fragmented ecosystem.</p><p>MoQ represents a promising new foundation—a chance to unify the silos and build the next generation of real-time applications on a scalable protocol. We're committed to helping build this foundation in the open, and we're just getting started.</p><p>MoQ is a realistic way forward, built on QUIC for future proofing, easier to understand than WebRTC, compatible with browsers unlike RTMP.</p><p>The protocol is evolving, the implementations are maturing, and the community is growing. Whether you're building the next generation of live streaming, exploring real-time collaboration, or pushing the boundaries of interactive media, consider whether MoQ may provide the foundation you need.</p>
    <div>
      <h3>Availability and pricing</h3>
      <a href="#availability-and-pricing">
        
      </a>
    </div>
    <p>We want developers to start building with MoQ today. To make that possible MoQ at Cloudflare is in tech preview - this means it's available free of charge for testing (at any scale). Visit our <a href="https://developers.cloudflare.com/moq/"><u>developer homepage </u></a>for updates and potential breaking changes.</p><p>Indie developers and large enterprises alike ask about pricing early in their adoption of new technologies. We will be transparent and clear about MoQ pricing. In general availability, self-serve customers should expect to pay 5 cents/GB outbound with no cost for traffic sent towards Cloudflare. </p><p>Enterprise customers can expect usual pricing in line with regular media delivery pricing, competitive with incumbent protocols. This means if you’re already using Cloudflare for media delivery, you should not be wary of adopting new technologies because of cost. We will support you.</p><p>If you’re interested in partnering with Cloudflare in adopting the protocol early or contributing to its development, please reach out to us at <a href="#"><u>moq@cloudflare.com</u></a>! Engineers excited about the future of the Internet are standing by.</p>
    <div>
      <h3>Get involved:</h3>
      <a href="#get-involved">
        
      </a>
    </div>
    <ul><li><p><b>Try the demo:</b> <a href="https://moq.dev/publish/"><u>https://moq.dev/publish/</u></a></p></li><li><p><b>Read the Internet draft:</b> <a href="https://datatracker.ietf.org/doc/draft-ietf-moq-transport/"><u>https://datatracker.ietf.org/doc/draft-ietf-moq-transport/</u></a></p></li><li><p><b>Contribute</b> to the protocol’s development: <a href="https://datatracker.ietf.org/group/moq/documents/"><u>https://datatracker.ietf.org/group/moq/documents/</u></a></p></li><li><p><b>Visit </b>our developer homepage: <a href="https://developers.cloudflare.com/moq/"><u>https://developers.cloudflare.com/moq/</u></a></p></li></ul><p></p> ]]></content:encoded>
            <category><![CDATA[Video]]></category>
            <category><![CDATA[QUIC]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[WebRTC]]></category>
            <category><![CDATA[IETF]]></category>
            <category><![CDATA[Standards]]></category>
            <guid isPermaLink="false">2XgF5NjmAy3cqybLPkpMFu</guid>
            <dc:creator>Mike English</dc:creator>
            <dc:creator>Renan Dincer</dc:creator>
        </item>
        <item>
            <title><![CDATA[Behind the scenes with Stream Live, Cloudflare’s live streaming service]]></title>
            <link>https://blog.cloudflare.com/behind-the-scenes-with-stream-live-cloudflares-live-streaming-service/</link>
            <pubDate>Thu, 02 Jan 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Let’s talk about Stream Live’s design, and how it leverages the distributed nature of Cloudflare’s network, rather than centralized locations as many other live services do. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare announced Stream Live for open beta <a href="https://blog.cloudflare.com/stream-live"><u>in 2021</u></a>, and <a href="https://blog.cloudflare.com/stream-live-ga"><u>in 2022</u></a> we went GA. While we talked about the experience of using it and the value it delivers to customers, we didn’t talk about how we built it. So let’s talk about Stream Live’s design, and how it leverages the distributed nature of Cloudflare’s network, rather than centralized locations as many other live services do. Ultimately, our goals are to keep our content ingest as close to broadcasters as possible, our content delivery as close to viewers as possible, and to retain our ability to handle unexpected use cases.</p><p>At a high level, Stream Live accepts audio/video content from broadcasters and makes that content available to viewers around the world in real time through the <a href="https://www.cloudflare.com/network/"><u>Cloudflare network</u></a>, which reaches more than 330 cities in over 120 countries. Hence, there are two sides to this: ingesting data from broadcasters and delivering encoded content to viewers. Both sides are built on a combination of internal systems and Cloudflare products, including <a href="https://www.cloudflare.com/developer-platform/products/workers/"><u>Cloudflare Workers</u></a>, <a href="https://www.cloudflare.com/developer-platform/products/durable-objects/"><u>Durable Objects</u></a>, <a href="https://www.cloudflare.com/application-services/products/cloudflare-spectrum/"><u>Spectrum</u></a>, and, of course, <a href="https://developers.cloudflare.com/cache/"><u>Cache</u></a>.</p><p>Let’s start on the ingest side.</p>
    <div>
      <h3>Ingesting a broadcast</h3>
      <a href="#ingesting-a-broadcast">
        
      </a>
    </div>
    <p>Broadcasters generate content in real time, as a series of video and audio frames, and it needs to be transmitted to Cloudflare over the Internet. To communicate with us, they choose a protocol such as <a href="https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol"><u>RTMPS</u></a> (Real Time Messaging Protocol Secure), <a href="https://www.ietf.org/archive/id/draft-sharabayko-srt-01.txt"><u>SRT</u></a> (Secure Reliable Transport), or <a href="https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html"><u>WHIP</u></a> (WebRTC-HTTP ingestion protocol) that defines how their content is packaged and transmitted. Each of these protocols is a way to transmit audio and video frames with various tradeoffs.</p><p>Regardless of the chosen protocol, the ingest lifecycle looks fairly similar. Broadcasters connect to an <a href="https://www.cloudflare.com/learning/cdn/glossary/anycast-network/"><u>Anycast</u></a> IP address using either a <a href="https://developers.cloudflare.com/stream/stream-live/custom-domains/"><u>custom ingest domain</u></a> or our default <code>live.cloudflare.com</code>. Both options direct to an IP address advertised from every Cloudflare data center around the world, minimizing the latency for broadcasters (both big and small) to our ingest points.</p><p>When the media content arrives at the Cloudflare server servicing the connection, it is first handled by a <a href="https://www.cloudflare.com/application-services/products/cloudflare-spectrum/"><u>Spectrum application</u></a>. Spectrum saved us time by implementing TLS termination for RTMPS, blocking potential <a href="https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/"><u>DDOS attacks</u></a>, and a few other protocol-specific benefits, such as our ability to support SRT broadcasters whose clients don't support the <a href="https://github.com/Haivision/srt/blob/bcc2f21ec75fcb10a8185857f3bc323bb19619da/docs/features/access-control.md"><u>Stream ID</u></a> portion of the SRT protocol. Those broadcasters assume their connection can be fully identified by connecting to a specific port, which was a challenge for our multitenant service. We use Spectrum to expose many listening ports to specific broadcasters which get wrapped up in <a href="https://developers.cloudflare.com/spectrum/reference/simple-proxy-protocol-header/"><u>Simple Proxy Protocol</u></a> and sent to one ingest service port. This is important, as our SRT implementation spends a non-trivial amount of CPU for each listening port, whereas Spectrum spends effectively nothing. In any case, Spectrum forwards all connections to the ingest service running on the same server.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7Hgz9WilQMf7hiIWgWvzgN/35c46350835d1e9c6d219f1ca2507abf/image3.png" />
          </figure><p>Our ingest service handles receiving content from broadcasters, forwarding to <a href="https://developers.cloudflare.com/stream/stream-live/simulcasting/"><u>live outputs</u></a>, and recording for HLS/DASH viewing. The ingest service is written in Go and acts on configuration and broadcast state stored in our Live Config <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a>. One Durable Object instance represents one live input; it contains both the customer configuration and the ongoing state of each broadcast.</p><p>We chose Durable Objects over a centralized database since they are not coupled to any specific data center, allowing them to be closer to each of our geographically distributed broadcasters while remaining highly available. In terms of customer configuration, we use Durable Objects to store everything defined <a href="https://developers.cloudflare.com/api/operations/stream-live-inputs-create-a-live-input#request-body"><u>when creating</u></a> or <a href="https://developers.cloudflare.com/api/operations/stream-live-inputs-create-a-new-output,-connected-to-a-live-input"><u>modifying the live input</u></a>.</p><p>We store the canonical state of the broadcast in the Durable Object. That includes timestamp metadata for keeping times monotonic, connection status, and which ingest service instance owns the broadcast. Any content received by the ingest service needs to be acknowledged and indexed by the Durable Object before it is made available to viewers. This splits our state into two types, ‘volatile’ and ‘committed’. Volatile state is content the ingest has received but not yet told the Durable Object about. Committed state is content the Durable Object has acknowledged and is used as a sync point for any other ingest service instance in the event they claim ownership of the broadcast.</p><p>This split between volatile and committed states is how we support broadcasters resuming a live broadcast after disconnecting and reconnecting for whatever reason, including a broadcaster network blip. That’s normally a relatively easy problem when you have centralized ingestion and state storage. Since broadcasters connect to an arbitrary server due to Anycast, we needed to get more creative in making sure that whichever server receives the reconnect has the data to continue the broadcast.</p><p>The ingest service itself is written as a relay, taking packets from one input stream and mapping them to multiple output streams. At the top level, the relay is implemented as two coupled ‘for’ loops that communicate over a Go channel, one for sending and one for receiving. When we receive data, we internally normalize it depending on the protocol. For example, some protocols send video packets as delimiter-based (<a href="https://gist.github.com/XueshiQiao/d68bea4a5406dd648664ce66933aeed9"><u>annex B h264 NALU</u></a>), but other protocols or file formats expect length-prefixed packets (<a href="https://gist.github.com/XueshiQiao/d68bea4a5406dd648664ce66933aeed9"><u>avcc h264 NALU</u></a>).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/903kTMKMnnHwms0EL9FNn/62e77098d23fa863c5ec1088367b4f43/image5.png" />
          </figure><p>A special case of relay outputs is our Live Playback and Recording functionality. When this is enabled, we copy and sanitize the incoming packets. Specifically, we issue monotonically increasing timestamps, which solves many issues we’ve encountered with various customer encoders. To ensure everything is aligned, we drop severely misaligned audio/video blocks, something typically seen at the start of broadcasts. Those sanitized packets are packaged into fragmented <a href="https://en.wikipedia.org/wiki/MP4_file_format"><u>MP4s</u></a> on keyframe boundaries.  We call those fragmented MP4s ‘original segments.’ Our ingest service stores the original segments in <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a> and lets the live config Durable Object know the segment exists and how long it is.</p><p>These original segments are considered the canonical copy of the content a customer has uploaded to us, and are reused when transitioning from live to on-demand. Since these are required to serve live viewers, this is why we don’t currently provide an option to decouple live playback from recording. Supporting live playback automatically implements on-demand recording, with some state management overhead.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5GLIyr66cFtbd4jajXYrE0/d098b1347a45e287e2c5ef03fffb264b/image4.png" />
          </figure>
    <div>
      <h3>Viewing the broadcast</h3>
      <a href="#viewing-the-broadcast">
        
      </a>
    </div>
    <p>At this point, we’ve ingested the content, cleaned it up, and durably stored it. Lets talk about how viewers watch this content.</p><p>Most online video is delivered in short 'segments’, multi-second chunks of content. Splitting the output allows content to be progressively emitted and is very cache-friendly. The protocols viewers use to request that content are typically <a href="https://datatracker.ietf.org/doc/html/rfc8216"><u>HLS (HTTP Live Streaming)</u></a> or <a href="https://www.mpeg.org/standards/MPEG-DASH/"><u>MPEG-DASH (Dynamic Adaptive Streaming over HTTP)</u></a>. <a href="https://www.ietf.org/archive/id/draft-murillo-whep-03.txt"><u>WHEP</u></a> (WebRTC-HTTP Egress Protocol) is a non-segmented viewing method available for real-time viewing in some cases. However, we’ll focus here on playback using segmented content with HLS or DASH, since that’s most of Stream Live’s usage today.</p><p>To start viewing, a video player will request an HLS or DASH playlist which describes the attributes of the media content and acts as an index for each segment. The playlist tells us which segments map to what point of the video’s timeline. Those segments are inserted into a playback buffer to be decoded and displayed by a client’s player. Examples here will use HLS, which is a newline delimited format. The typical alternative is DASH, which is XML based.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/43zIdjDFagc4w8HgHNYBPD/1447cb964d9eace73711b31a5f963656/image6.png" />
          </figure><p>First, ‘primary’ playlists describe which renditions of the same content are available, as well as where to get their specific index files. Those renditions can vary in bitrate, codec, framerate, resolution, etc. If you’ve ever picked ‘1080p’ from a video player quality menu, the player knew those qualities were available using this or similar methods. When selecting quality automatically, players choose the best rendition for the viewing machine’s capabilities (such as the ability to decode a certain codec) and network constraints. We use an internal representation of tracks (what kind of content, i.e. video), renditions (content parameters, i.e. 1080p), and muxings (where to find that content, i.e. in R2 bucket N or OTFE with call M) to generate both HLS and DASH, as the two formats contain nearly the same data, except organized differently. Here’s a simplified example of a ‘multi-variant’ or ‘primary’ HLS playlist that Stream generated. It includes some annotations to explain the components.</p>
            <pre><code>#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_audio",NAME="original",LANGUAGE="en-0a76e0ad",DEFAULT=YES,AUTOSELECT=YES,URI="stream_2.m3u8" &lt;- Audio track description + URL path
...
#EXT-X-STREAM-INF:RESOLUTION=426x240,CODECS="avc1.42c015,mp4a.40.2",BANDWIDTH=149084,AVERAGE-BANDWIDTH=145135,SCORE=1.0,FRAME-RATE=30.000,AUDIO="group_audio" &lt;- description of variant contents
stream_1.m3u8 &lt;- URL path to fetch variant</code></pre>
            <p>Second, ‘variant’ or ‘stream’ playlists contain a list of segments that can be downloaded and viewed for each rendition. These are used for both live and on-demand viewing. The difference is on-demand playlists contain a flag indicating no more content will be added to the index whereas live omits that flag to allow it to append content in future requests. As a result, you’ll see video players download <a href="https://en.wikipedia.org/wiki/M3U#M3U8"><u>M3U8</u></a> (HLS) or <a href="https://ottverse.com/structure-of-an-mpeg-dash-mpd/"><u>MPD</u></a> (DASH) files approximately every 1–10 seconds when viewing a broadcast, looking for updated content.</p>
            <pre><code>#EXTM3U
#EXT-X-VERSION:6
#EXT-X-MEDIA-SEQUENCE:89281 &lt;- Indicates position of sliding window
#EXT-X-TARGETDURATION:6
#EXT-X-MAP:URI=".../init.mp4" &lt;- Initialization data
#EXTINF:4.000, &lt;- How long the segment
.../seg_89281.mp4 &lt;- Location of a segment
#EXTINF:4.000,
.../seg_89282.mp4
#EXTINF:4.000,
.../seg_89283.mp4</code></pre>
            <p>To serve all requests from viewers, we use a <a href="https://workers.cloudflare.com/"><u>Cloudflare Worker</u></a> called ‘delivery-worker’. It handles all requests for Stream content, and had its first commit in 2017, making it one of the earliest production-facing workers at Cloudflare. Since it's a worker that executes as close to a viewer as possible, it frees us up to spend more time on content and metadata performance rather than where our logic runs. It delivers content, renders playlists, and performs a variety of other functions. For rendering playlists, the worker transforms the broadcast state from the durable object, as mentioned earlier.</p><p>When clients ask for the encoded media content the playlist advertised to them, delivery-worker will send a subrequest to our OTFE (on-the-fly-encoder) service that transits the Cloudflare network. That request describes the format of content requested, i.e. the video stream of segment 89282 at a 1280x720 resolution encoded using AVC (aka H.264) capped CRF with some specified <a href="https://blog.cloudflare.com/making-video-intuitive-an-explainer/"><u>bitrate cap</u></a>. Then, OTFE will encode the original segment to output the specified configuration.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2PNSBVrMZz3rgiQqzzQcHp/56cd69bc8b64034673d4f15c9e461a1f/image7.png" />
          </figure><p>On-the-fly encoding is more efficient than always-encoding, which is the approach most other platforms take. If there are no viewers watching a specific quality level, or watching the broadcast at all, then we aren’t encoding it. That saves power, CPU time, RAM, network, and cache space. Doing nothing is always more efficient than doing something. This applies to a variety of customer use cases, since not all broadcasts have many viewers widely distributed across a range of connection qualities. For one case, consider when serving live broadcasts that are primarily viewed on high quality connections — encoding 240p or 360p variants would probably go to waste most of the time. For a more extreme case, there are situations where you definitely want recording enabled for live content, but viewing is an exceptional situation, such as for security cameras or dashcams. Of course, we have many customers that have active viewership for their broadcasts and this architecture allows us to serve both use cases.</p><p>On-the-fly encoding has a tradeoff: it is hard to implement for “media-correctness” and performance reasons. Media-correctness is important to ensuring smooth playback; individual segments need to have exactly the right start time and duration, or you get stuttering playback, audio/video desync, or entirely unwatchable content. Perfecting our media output requires fine-tuning our encoding, deep-diving into specs, and adjusting fragmented MP4s — especially since most encoders aren’t designed for per-segment encoding. For performance, we hide encoding delay by aggressively prefetching segments from delivery-worker. When a viewer initiates a request for Segment N, we initiate encoding of segment N+1. Since that logic is implemented as a worker, we can also easily add or iterate the prefetching however we want.</p><p>This encoding flow stands on top of the Cloudflare network, which also provides us with <a href="https://developers.cloudflare.com/cache/how-to/tiered-cache/"><u>tiered caching</u></a> and request coalescing. Request coalescing is the key to supporting many viewers simultaneously but only encoding once by enforcing that, for any number of viewers requesting the same encoded content, only one of those requests will make it to our encoder origin — thanks to <a href="https://developers.cloudflare.com/cache/"><u>Cache</u></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6oLTqFzrQodmQqWrIb91qX/1f1f7eb02fd7efb1830f7d636f54edca/image2.png" />
          </figure><p>That’s how Stream Live works at a high level. We ingest content from users, send it to any desired live outputs, transcode it for viewing, and give viewers a choice of quality levels, with a lot of backend complexity hidden behind a friendly API. All of this is built on top of the Cloudflare network, with Cloudflare as Customer Zero for our own products and services, using the same as the ones available to our customers.</p><p>There’s a lot more we can write about for problems we’ve solved in building Stream Live over the last few years, but those will have to be for a future blog post. If this mix of media and distributed system problems discussed here sound interesting, the Cloudflare Media Platform <a href="https://job-boards.greenhouse.io/cloudflare/jobs/6449185?gh_jid=6449185"><u>is hiring</u></a> for <a href="https://job-boards.greenhouse.io/cloudflare/jobs/6297082?gh_jid=6297082"><u>several roles</u></a>. Apply and join us!</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Stream]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <guid isPermaLink="false">chVlt8JAjFduvvOJ5c1yl</guid>
            <dc:creator>Kyle Boutette</dc:creator>
            <dc:creator>Jacob Curtis</dc:creator>
        </item>
        <item>
            <title><![CDATA[What’s new with Cloudflare Media: updates for Calls, Stream, and Images]]></title>
            <link>https://blog.cloudflare.com/whats-next-for-cloudflare-media/</link>
            <pubDate>Thu, 04 Apr 2024 13:00:40 GMT</pubDate>
            <description><![CDATA[ With Cloudflare Calls in open beta, you can build real-time, serverless video and audio applications. Cloudflare Stream lets your viewers instantly clip from ongoing streams ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Our customers use Cloudflare Calls, Stream, and Images to build live, interactive, and real-time experiences for their users. We want to reduce friction by making it easier to get data into our products. This also means providing transparent pricing, so customers can be confident that costs make economic sense for their business, especially as they scale.</p><p>Today, we’re introducing four new improvements to help you build media applications with Cloudflare:</p><ul><li><p>Cloudflare Calls is in open beta with transparent pricing</p></li><li><p>Cloudflare Stream has a Live Clipping API to let your viewers instantly clip from ongoing streams</p></li><li><p>Cloudflare Images has a pre-built upload widget that you can embed in your application to accept uploads from your users</p></li><li><p>Cloudflare Images lets you crop and resize images of people at scale with automatic face cropping</p></li></ul>
    <div>
      <h3>Build real-time video and audio applications with Cloudflare Calls</h3>
      <a href="#build-real-time-video-and-audio-applications-with-cloudflare-calls">
        
      </a>
    </div>
    <p>Cloudflare Calls is now in open beta, and you can activate it from your dashboard. Your usage will be free until May 15, 2024. Starting May 15, 2024, customers with a Calls subscription will receive the first terabyte each month for free, with any usage beyond that charged at $0.05 per real-time gigabyte. Additionally, there are no charges for inbound traffic to Cloudflare.</p><p>To get started, read the <a href="https://developers.cloudflare.com/calls/">developer documentation for Cloudflare Calls</a>.</p>
    <div>
      <h3>Live Instant Clipping: create clips from live streams and recordings</h3>
      <a href="#live-instant-clipping-create-clips-from-live-streams-and-recordings">
        
      </a>
    </div>
    <p>Live broadcasts often include short bursts of highly engaging content within a longer stream. Creators and viewers alike enjoy being able to make a “clip” of these moments to share across multiple channels. Being able to generate that clip rapidly enables our customers to offer instant replays, showcase key pieces of recordings, and build audiences on social media in real-time.</p><p>Today, <a href="https://www.cloudflare.com/products/cloudflare-stream/">Cloudflare Stream</a> is launching Live Instant Clipping in open beta for all customers. With the new Live Clipping API, you can let your viewers instantly clip and share moments from an ongoing stream - without re-encoding the video.</p><p>When planning this feature, we considered a typical user flow for generating clips from live events. Consider users watching a stream of a video game: something wild happens and users want to save and share a clip of it to social media. What will they do?</p><p>First, they’ll need to be able to review the preceding few minutes of the broadcast, so they know what to clip. Next, they need to select a start time and clip duration or end time, possibly as a visualization on a timeline or by scrubbing the video player. Finally, the clip must be available quickly in a way that can be replayed or shared across multiple platforms, even after the original broadcast has ended.</p><p>That ideal user flow implies some heavy lifting in the background. We now offer a manifest to preview recent live content in a rolling window, and we provide the timing information in that response to determine the start and end times of the requested clip relative to the whole broadcast. Finally, on request, we will generate on-the-fly that clip as a standalone video file for easy sharing as well as an HLS manifest for embedding into players.</p><p>Live Instant Clipping is available in beta to all customers starting today! Live clips are free to make; they do not count toward storage quotas, and playback is billed just like minutes of video delivered. To get started, check out the <a href="https://developers.cloudflare.com/stream/stream-live/live-instant-clipping/">Live Clipping API in developer documentation</a>.</p>
    <div>
      <h3>Integrate Cloudflare Images into your application with only a few lines of code</h3>
      <a href="#integrate-cloudflare-images-into-your-application-with-only-a-few-lines-of-code">
        
      </a>
    </div>
    <p>Building applications with user-uploaded images is even easier with the upload widget, a pre-built, interactive UI that lets users upload images directly into your Cloudflare Images account.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MVN5ibd1UGnokaEm7f1Vq/8efedb285ec93d52867d78ca63cb454b/image3-9.png" />
            
            </figure><p>Many developers use <a href="https://www.cloudflare.com/developer-platform/cloudflare-images/">Cloudflare Images</a> as an end-to-end image management solution to support applications that center around user-generated content, from AI photo editors to social media platforms. Our APIs connect the frontend experience – where users upload their images – to the storage, optimization, and delivery operations in the backend.</p><p>But building an application can take time. Our team saw a huge opportunity to take away as much extra work as possible, and we wanted to provide off-the-shelf integration to speed up the development process.</p><p>With the upload widget, you can seamlessly integrate Cloudflare Images into your application within minutes. The widget can be integrated in two ways: by embedding a script into a static HTML page or by installing a package that works with your favorite framework. We provide a ready-made Worker template that you can deploy directly to your account to connect your frontend application with Cloudflare Images and authorize users to upload through the widget.</p><p>To try out the upload widget, <a href="https://forms.gle/vBu47y3638k8fkGF8">sign up for our closed beta</a>.</p>
    <div>
      <h3>Optimize images of people with automatic face cropping for Cloudflare Images</h3>
      <a href="#optimize-images-of-people-with-automatic-face-cropping-for-cloudflare-images">
        
      </a>
    </div>
    <p>Cloudflare Images lets you dynamically manipulate images in different aspect ratios and dimensions for various use cases. With face cropping for Cloudflare Images, you can now crop and resize images of people’s faces at scale. For example, if you’re building a social media application, you can apply automatic face cropping to generate profile picture thumbnails from user-uploaded images.</p><p>Our existing gravity parameter uses saliency detection to set the focal point of an image based on the most visually interesting pixels, which determines how the image will be cropped. We expanded this feature by using a machine learning model called RetinaFace, which classifies images that have human faces. We’re also introducing a new zoom parameter that you can combine with face cropping to specify how closely an image should be cropped toward the face.</p><p>To apply face cropping to your image optimization, <a href="https://forms.gle/2bPbuijRoqGi6Qn36">sign up for our closed beta</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6JFNk182dDZHu0sxIySMC5/d3821e2f911b7e31bb411addcc10bdb6/image2-10.png" />
            
            </figure><p><i>Photo by</i> <a href="https://unsplash.com/@eyeforebony?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash"><i>Eye for Ebony</i></a> <i>on</i> <a href="https://unsplash.com/photos/photo-of-woman-wearing-purple-lipstick-and-black-crew-neck-shirt-vYpbBtkDhNE?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash"><i>Unsplash</i></a></p>
            <pre><code>https://example.com/cdn-cgi/image/fit=crop,width=500,height=500,gravity=face,zoom=0.6/https://example.com/images/picture.jpg</code></pre>
            
    <div>
      <h3>Meet the Media team over Discord</h3>
      <a href="#meet-the-media-team-over-discord">
        
      </a>
    </div>
    <p>As we’re working to build the next set of media tools, we’d love to hear what you’re building for your users. Come <a href="https://discord.gg/cloudflaredev">say hi to us on Discord</a>. You can also learn more by visiting our developer documentation for <a href="https://developers.cloudflare.com/calls/">Calls</a>, <a href="https://developers.cloudflare.com/stream/">Stream</a>, and <a href="https://developers.cloudflare.com/images/">Images</a>.</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Cloudflare Stream]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[Cloudflare Images]]></category>
            <category><![CDATA[Image Optimization]]></category>
            <category><![CDATA[Image Resizing]]></category>
            <category><![CDATA[Image Storage]]></category>
            <category><![CDATA[Cloudflare Calls]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">4fOMOrJU6Bg9JNkRAThc7c</guid>
            <dc:creator>Deanna Lam</dc:creator>
            <dc:creator>Taylor Smith</dc:creator>
            <dc:creator>Zaid Farooqui</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare Stream Low-Latency HLS support now in Open Beta]]></title>
            <link>https://blog.cloudflare.com/cloudflare-stream-low-latency-hls-open-beta/</link>
            <pubDate>Mon, 25 Sep 2023 13:00:29 GMT</pubDate>
            <description><![CDATA[ Cloudflare Stream’s LL-HLS support enters open beta today. You can deliver video to your audience faster, reducing the latency a viewer may experience on their player to as little as 3 seconds ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Stream Live lets users easily scale their live-streaming apps and websites to millions of creators and concurrent viewers while focusing on the content rather than the infrastructure — Stream manages codecs, protocols, and bit rate automatically.</p><p>For <a href="/recapping-speed-week-2023/">Speed Week</a> this year, we introduced a <a href="/low-latency-hls-support-for-cloudflare-stream/">closed beta of Low-Latency HTTP Live Streaming</a> (LL-HLS), which builds upon the high-quality, feature-rich HTTP Live Streaming (HLS) protocol. Lower latency brings creators even closer to their viewers, empowering customers to build more interactive features like chat and enabling the use of live-streaming in more time-sensitive applications like live e-learning, sports, gaming, and events.</p><p>Today, in celebration of Birthday Week, we’re opening this beta to all customers with even lower latency. With LL-HLS, you can deliver video to your audience faster, reducing the latency a viewer may experience on their player to as little as three seconds. <a href="https://www.cloudflare.com/developer-platform/solutions/live-streaming/">Low Latency streaming</a> is priced the same way, too: $1 per 1,000 minutes delivered, with zero extra charges for encoding or bandwidth.</p>
    <div>
      <h3>Broadcast with latency as low as three seconds.</h3>
      <a href="#broadcast-with-latency-as-low-as-three-seconds">
        
      </a>
    </div>
    <p>LL-HLS is an extension of the <a href="https://www.cloudflare.com/learning/video/what-is-http-live-streaming/">HLS standard</a> that allows us to reduce glass-to-glass latency — the time between something happening on the broadcast end and a user seeing it on their screen. That includes factors like network conditions and transcoding for HLS and adaptive bitrates. We also include client-side buffering in our understanding of latency because we know the experience is driven by what a user sees, not when a byte is delivered into a buffer. Depending on encoder and player settings, broadcasters' content can be playing on viewers' screens in less than three seconds.</p><div>
  
</div><p><i>On the left,</i> <a href="https://obsproject.com/"><i>OBS Studio</i></a> <i>broadcasting from my personal computer to Cloudflare Stream. On the right, watching this livestream using our own built-in player playing LL-HLS with three second latency!</i></p>
    <div>
      <h3>Same pricing, lower latency. Encoding is always free.</h3>
      <a href="#same-pricing-lower-latency-encoding-is-always-free">
        
      </a>
    </div>
    <p>Our addition of LL-HLS support builds on all the best parts of Stream including simple, predictable pricing. You never have to pay for ingress (broadcasting to us), compute (encoding), or egress. This allows you to stream with peace of mind, knowing there are no surprise fees and no need to trade quality for cost. Regardless of bitrate or resolution, Stream costs \$1 per 1,000 minutes of video delivered and \$5 per 1,000 minutes of video stored, billed monthly.</p><p>Stream also provides both a built-in web player or HLS/DASH manifests to use in a compatible player of your choosing. This enables you or your users to go live using the same protocols and tools that broadcasters big and small use to go live to YouTube or Twitch, but gives you full control over access and presentation of live streams. We also provide access control with signed URLs and hotlinking prevention measures to protect your content.</p>
    <div>
      <h3>Powered by the strength of the network</h3>
      <a href="#powered-by-the-strength-of-the-network">
        
      </a>
    </div>
    <p>And of course, Stream is powered by Cloudflare's global network for fast delivery worldwide, with points of presence within 50ms of 95% of the Internet connected population, a key factor in our quest to slash latency. We ingest live video close to broadcasters and move it rapidly through Cloudflare’s network. We run encoders on-demand and generate player manifests as close to viewers as possible.</p>
    <div>
      <h3>Getting started with LL-HLS</h3>
      <a href="#getting-started-with-ll-hls">
        
      </a>
    </div>
    <p>Getting started with Stream Live only takes a few minutes, and by using Live <i>Outputs</i> for restreaming, you can even test it without changing your existing infrastructure. First, create or update a Live Input in the Cloudflare dashboard. While in beta, Live Inputs will have an option to enable LL-HLS called “Low-Latency HLS Support.” Activate this toggle to enable the new pipeline.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3LHUfSgkCln8UFZy12CtHF/17d72972159b165364d5db31c069702f/image1-9.png" />
            
            </figure><p>Stream will automatically provide the RTMPS and SRT endpoints to broadcast your feed to us, just as before. For the best results, we recommend the following broadcast settings:</p><ul><li><p>Codec: h264</p></li><li><p>GOP size / keyframe interval: 1 second</p></li></ul><p>Optionally, configure a Live Output to point to your existing video ingest endpoint via RTMPS or SRT to test Stream while rebroadcasting to an existing workflow or infrastructure.</p><p>Stream will automatically provide RTMPS and SRT endpoints to broadcast your feed to us as well as an HTML embed for our built-in player.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1zFDLgJ0iwEuh0Brat0TXz/da52d22ae28234ecd4390cf4dc518f4d/image3-7-1.png" />
            
            </figure><p>This connection information can be added easily to a broadcast application like OBS to start streaming immediately:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Gn4GlXNvamzD1qnN5vEi2/c503a9c7280c6bc8f88a1bfadf43b876/image2-7.png" />
            
            </figure><p>During the beta, our built-in player will automatically attempt to use low-latency for any enabled Live Input, falling back to regular HLS otherwise. If LL-HLS is being used, you’ll see “Low Latency” noted in the player.</p><p>During this phase of the beta, we are most closely focused on using <a href="https://obsproject.com/">OBS</a> to broadcast and Stream’s built-in player to watch. However, you may test the LL-HLS manifest in a player of your own by appending <code>?protocol=llhls</code> to the end of the HLS manifest URL. This flag may change in the future and is not yet ready for production usage; <a href="https://developers.cloudflare.com/stream/changelog/">watch for changes in DevDocs</a>.</p>
    <div>
      <h3>Sign up today</h3>
      <a href="#sign-up-today">
        
      </a>
    </div>
    <p>Low-Latency HLS is Stream Live’s latest tool to bring your creators and audiences together. All new and existing Stream subscriptions are eligible for the LL-HLS open beta today, with no pricing changes or contract requirements --- all part of building the fastest, simplest serverless live-streaming platform. Join our beta to start test-driving Low-Latency HLS!</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Cloudflare Stream]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[Restreaming]]></category>
            <category><![CDATA[Video]]></category>
            <category><![CDATA[Latency]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">4s1ozw7fIyXQZnMYrnEnX4</guid>
            <dc:creator>Taylor Smith</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Low-Latency HLS Support for Cloudflare Stream]]></title>
            <link>https://blog.cloudflare.com/low-latency-hls-support-for-cloudflare-stream/</link>
            <pubDate>Mon, 19 Jun 2023 13:00:57 GMT</pubDate>
            <description><![CDATA[ Broadcast live to websites and applications with less than 10 second latency with Low-Latency HTTP Live Streaming (LL-HLS), now in beta with Cloudflare Stream ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Stream Live lets users easily scale their live streaming apps and websites to millions of creators and concurrent viewers without having to worry about bandwidth costs or purchasing hardware for real-time encoding at scale. Stream Live lets users focus on the content rather than the infrastructure — taking care of the codecs, protocols, and bitrate automatically. When we launched Stream Live last year, we focused on bringing high quality, feature-rich streaming to websites and applications with HTTP Live Streaming (HLS).</p><p>Today, we're excited to introduce support for <a href="https://www.cloudflare.com/developer-platform/solutions/live-streaming/"><i>Low-Latency</i> HTTP Live Streaming</a> (LL-HLS) in a closed beta, offering you an even faster streaming experience. LL-HLS will reduce the latency a viewer may experience on their player from highs of around 30 seconds to less than 10 in many cases. Lower latency brings creators even closer to their viewers, empowering customers to build more interactive features like Q&amp;A or chat and enabling the use of live streaming in more time-sensitive applications like sports, gaming, and live events.</p>
    <div>
      <h3>Broadcast with less than 10-second latency</h3>
      <a href="#broadcast-with-less-than-10-second-latency">
        
      </a>
    </div>
    <p>LL-HLS is an extension of HLS and allows us to reduce <i>glass-to-glass latency</i> — the time between something happening on the broadcast end and a user seeing it on their screen. This includes everything from broadcaster encoding to client-side buffering because we know the experience is driven by what a user sees, not when a byte is delivered into a buffer. Depending on encoder and player settings, broadcasters' content can be playing on viewers' screens in less than ten seconds.</p><p>Our addition of LL-HLS support builds on all the best parts of Stream including simple, predictable pricing. You never have to pay for ingest (broadcasting to us), compute (encoding), or egress. It costs \$5 per 1,000 minutes of video stored per month and \$1 per 1,000 minutes of video viewed per month. This allows you to stream with peace of mind, knowing there are no surprise fees.</p><p>Other platforms tack on live recordings as a separate add-on feature, and those recordings only become available minutes or even hours after a live stream ends. With Cloudflare Stream, Live segments are automatically recorded and immediately available for on-demand playback.</p><p>Stream also provides both a built-in web player and HLS manifests to use in a compatible player of your choosing. This enables you or your users to go live using the same protocols and tools that broadcasters big and small use to go live to YouTube or Twitch, but gives you full control over access and presentation of live streams.</p><p>We also provide <a href="https://www.cloudflare.com/learning/access-management/what-is-access-control/">access control</a> with signed URLs allowing you to protect your content, sharing with only certain users. This allows you to restrict access so only logged in members can watch a particular video, or only let users watch your video for a limited time period. And of course, Stream is powered by Cloudflare's global network for fast delivery worldwide, with points of presents within 50ms of 95% of the Internet connected population.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/r4I8NvvEb90cCrXRJtGLf/d3e66922eae5e29e7d5b4cd56f66c0ed/image2-8.png" />
            
            </figure><p>Left: Broadcasting to Stream Live using OBS. Right: Watching that same Stream. Note the five second difference in the NIST clock between the source and the playback.</p><p>Powering the LL-HLS experience involved making several improvements to our underlying infrastructure. One of the largest challenges we encountered was that our existing architecture involved a pipeline with multiple buffers as long as the keyframe interval. This meant Stream Live would introduce a delay of up to five times the keyframe interval. To resolve this, we simplified a portion of our pipeline — now, we work with individual frames rather than whole keyframe-intervals, but without giving up the economies of scale our approach to encoding provides. This decoupling of keyframe interval and internal buffer duration lets us dramatically reduce latency in HLS, with a maximum of twice the keyframe interval.</p>
    <div>
      <h3>Getting started with the LL-HLS beta</h3>
      <a href="#getting-started-with-the-ll-hls-beta">
        
      </a>
    </div>
    <p>As we prepare to ship this new functionality, we're <a href="https://docs.google.com/forms/d/e/1FAIpQLSeZ2NBuAXC75aDJllhVA0itW0TZ1w4s48TvFm-eP7R1h9Hc9g/viewform?usp=sf_link">looking for beta testers</a> to help us test non-production workloads. To participate in the beta, your application should be configured with these settings:</p><ul><li><p>H.264 video codec</p></li><li><p>Constant bitrate</p></li><li><p>Keyframe interval (GOP size) of 2s</p></li><li><p>No B Frames</p></li><li><p>Using the Stream built-in player</p></li></ul><p>Getting started with Stream Live only takes a few minutes. Create a Live Input in the Cloudflare dashboard, then Stream will automatically provide RTMPS and SRT endpoints to broadcast your feed to us as well as an HTML embed for our built-in player and the HLS manifest for a custom player.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5luGmhp7Otff4f8T8Bjwoh/3952e7bcb4998a416ad5e8c4e49b189c/image4-6.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/43x3NlJtNgaUAeJnmj3RD7/ee6e9533024c16ecf775813a56d06a2b/image3-7.png" />
            
            </figure><p>This connection information can be added easily to a broadcast application like OBS to start streaming immediately:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/78aLkxTHD6JIknv5Cm8yVw/446ce2661c935560d3e68052b26d284f/image1-9.png" />
            
            </figure><p>Customers in the LL-HLS beta will need to make a minor adjustment to the built-in player embed code, but there are no changes to Live Input configuration, dashboard interface, API, or existing functionality.</p>
    <div>
      <h3>Sign up today</h3>
      <a href="#sign-up-today">
        
      </a>
    </div>
    <p>LL-HLS is Stream Live’s latest tool to bring your creators and audiences together. After the beta period, this feature will be generally available to all new and existing Stream subscriptions with no pricing changes or contract requirements --- all part of building the fastest, simplest serverless live streaming platform. <a href="https://docs.google.com/forms/d/e/1FAIpQLSeZ2NBuAXC75aDJllhVA0itW0TZ1w4s48TvFm-eP7R1h9Hc9g/viewform?usp=sf_link">Join our beta</a> to start test-driving Low-Latency HLS!</p>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div></div> ]]></content:encoded>
            <category><![CDATA[Speed Week]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[Video]]></category>
            <guid isPermaLink="false">1AGHbDsMyWLMDqABUpgMo4</guid>
            <dc:creator>Taylor Smith</dc:creator>
        </item>
        <item>
            <title><![CDATA[Serverless Live Streaming with Cloudflare Stream]]></title>
            <link>https://blog.cloudflare.com/stream-live/</link>
            <pubDate>Thu, 30 Sep 2021 12:59:23 GMT</pubDate>
            <description><![CDATA[ You can now use Cloudflare to do serverless end-to-end live-streaming. Stream Live offers video ingestion, encoding, recording and a player in a single product. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We’re excited to introduce the open beta of Stream Live, an end-to-end scalable <a href="https://www.cloudflare.com/developer-platform/solutions/live-streaming/">live-streaming platform</a> that allows you to focus on growing your live video apps, not your codebase.</p><p>With Stream Live, you can painlessly grow your streaming app to scale to millions of concurrent broadcasters and millions of concurrent users. Start sending live video from mobile or desktop using the industry standard RTMPS protocol to millions of viewers instantly. Stream Live works with the most popular live video broadcasting software you already use, including ffmpeg, <a href="https://obsproject.com/">OBS</a> or Zoom. Your broadcasts are automatically recorded, optimized and delivered using the Stream player.</p><p>When you are building your live infrastructure from scratch, you have to answer a few critical questions:</p><ol><li><p>“<i>Which codec(s) are we going to use to encode the videos?”</i></p></li><li><p><b><i>“Which protocols are we going to use to ingest and deliver videos?”</i></b></p></li><li><p><b><i>“How are the different components going to impact latency?”</i></b></p></li></ol><p>We built Stream Live, so you don’t have to think about these questions and spend considerable engineering effort answering them. Stream Live abstracts these pesky yet important implementation details by automatically choosing the most compatible codec and streaming protocol for the client device. There is no limit to the number of live broadcasts you can start and viewers you can have on Stream Live. Whether you want to make the next viral video sharing app or securely broadcast all-hands meetings to your company, Stream will scale with you without having to spend months building and maintaining video infrastructure.</p>
    <div>
      <h3>Built-in Player and Access Control</h3>
      <a href="#built-in-player-and-access-control">
        
      </a>
    </div>
    <p>Every live video gets an embed code that can be placed inside your app, enabling your users to watch the live stream. You can also use your own player with included support for the two major HTTP streaming formats — HLS and DASH — for a granular control over the user experience.</p><p>You can limit who can view your live videos with self-expiring tokenized links for each viewer. When generating the tokenized links, you can define constraints <a href="https://developers.cloudflare.com/stream/viewing-videos/securing-your-stream">including time-based expiration, geo-fencing and IP restrictions</a>. When building an online learning site or a video sharing app, you can put videos behind authentication, so only logged-in users can view your videos. Or if you are building a live concert platform, you may have agreements to only allow viewers from specific countries or regions. Stream’s signed tokens help you comply with complex and custom rulesets.</p>
    <div>
      <h3>Instant Recordings</h3>
      <a href="#instant-recordings">
        
      </a>
    </div>
    <p>With Stream Live, you don’t have to wait for a recording to be available after the live broadcast ends. Live videos automatically get converted to recordings in less than a second. Viewers get access to the recording instantly, allowing them to catch up on what they missed.</p>
    <div>
      <h3>Instant Scale</h3>
      <a href="#instant-scale">
        
      </a>
    </div>
    <p>Whether your platform has one active broadcaster or ten thousand, Stream Live scales with your use case. You don’t have to worry about adding new compute instances, setting up availability zones or negotiating additional software licenses.</p><p>Legacy live video pipelines built in-house typically ingest and encode the live stream continents away in a single location. Video that is ingested far away makes video streaming unreliable, especially for global audiences. All Cloudflare locations run the necessary software to ingest live video <i>in</i> and deliver video <i>out</i>. Once your video broadcast is in the Cloudflare network, Stream Live uses the <a href="/250-cities-is-just-the-start/">Cloudflare backbone</a> and <a href="https://www.cloudflare.com/products/argo-smart-routing/">Argo</a> to transmit your live video with increased reliability.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3aUAddowRRZXNaqyepq9ey/8509043e6a1a063ee30152199de0e287/unnamed--1--2.png" />
            
            </figure>
    <div>
      <h3>Broadcast with 15 second latency</h3>
      <a href="#broadcast-with-15-second-latency">
        
      </a>
    </div>
    <p>Depending on your video encoder settings, the time between you broadcasting and the video displaying on your viewer’s screens can be as low as fifteen seconds with Stream Live. Low latency allows you to build interactive features such as chat and Q&amp;A into your application. This latency is good for broadcasting meetings, sports, concerts, and worship, but we know it doesn’t cover all uses for live video.</p><p>We’re on a mission to reduce the latency Stream Live adds to near-zero. The Cloudflare network is now <a href="/250-cities-is-just-the-start/">within 50ms for 95% of the world’s population</a>. We believe we can significantly reduce the delay from the broadcaster to the viewer in the coming months. Finally, in the world of live-streaming, latency is only meaningful once you can assume reliability. By using the Cloudflare network spanning over 250 locations, you get unparalleled reliability that is critical for live events.</p>
    <div>
      <h3>Simple and predictable pricing</h3>
      <a href="#simple-and-predictable-pricing">
        
      </a>
    </div>
    <p>Stream Live is available as a pay-as-you-go service based on the duration of videos recorded and duration of video viewed.</p><ul><li><p>It costs $5 per 1,000 minutes of video storage capacity per month. Live-streamed videos are automatically recorded. There is no additional cost for ingesting the live stream.</p></li><li><p>It costs $1 per 1,000 minutes of video viewed.</p></li><li><p>There are no surprises. You never have to pay hidden costs for video ingest, compute (encoding), egress or storage found in legacy video pipelines.</p></li><li><p>You can control how much you spend with Stream using billing alerts and restrict viewing by creating signed tokens that only work for authorized viewers.</p></li></ul><p>Cloudflare Stream encodes the live stream in multiple quality levels at no additional cost. This ensures smooth playback for your viewers with varying Internet speed. As your viewers move from Wi-Fi to mobile networks, videos continue playing without interruption. Other platforms that offer live-streaming infrastructure tend to add extra fees for adding quality levels that caters to a global audience.</p><p>If your use case consists of thousands of concurrent broadcasters or millions of concurrent viewers, <a href="https://www.cloudflare.com/plans/enterprise/contact/">reach out</a> to us for volume pricing.</p>
    <div>
      <h3>Go live with Stream</h3>
      <a href="#go-live-with-stream">
        
      </a>
    </div>
    <p>Stream works independent of any domain on Cloudflare. If you already have a Cloudflare account with a Stream subscription, you can begin using Stream Live by clicking on the “Live Input” tab on the <a href="https://dash.cloudflare.com/?to=/:account/stream">Stream Dashboard</a> and creating a new input:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1iLtxKiyHyGsDb9zkLra2e/804f1abf6a30a86cd214dcc048685705/Stream-Screen.png" />
            
            </figure><p>If you are new to Cloudflare, <a href="https://dash.cloudflare.com/sign-up/stream">sign up for Cloudflare Stream.</a></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[WebRTC]]></category>
            <category><![CDATA[Video]]></category>
            <category><![CDATA[Cloudflare Stream]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">18F1qaXrHhAozgDsfcwjHJ</guid>
            <dc:creator>Zaid Farooqui</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building Cloudflare TV from scratch]]></title>
            <link>https://blog.cloudflare.com/building-cloudflare-tv-from-scratch/</link>
            <pubDate>Tue, 07 Jul 2020 11:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare TV is a 24x7 TV channel that takes you behind-the-scenes and let’s you hear directly from the builders working on your favorite Cloudflare products. This blog post covers the story of why we decided to build Cloudflare TV in-house and some of the technologies that make it possible. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Cloudflare TV is inspired by television shows of the 90s that shared the newest, most exciting developments in computing and music videos. We had three basic requirements for Cloudflare TV:</p><ol><li><p>Guest participation should be as simple as joining a Zoom call</p></li><li><p>There should be 24x7 programming. Something interesting should be playing <i>all the time</i></p></li><li><p>Everything should happen in the cloud and we should never have to ask anyone “to leave their computer on” to have the stream running 24 hours a day</p></li></ol>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/j8JPvjtPqbNC7OMfkqYhK/04f32b8fcc5bd60c87169357f4191cba/image1.png" />
            
            </figure>
    <div>
      <h3>We didn’t set out to build Cloudflare TV from <i>scratch</i></h3>
      <a href="#we-didnt-set-out-to-build-cloudflare-tv-from-scratch">
        
      </a>
    </div>
    <p>Building a lot of the technology behind Cloudflare TV from scratch was not part of the plan, especially given our aggressive timeline. So why did we decide to pursue it? After evaluating multiple live streaming solutions, we reached the following conclusion:</p><ul><li><p>24x7 linear streaming is not something that is a priority for most video streaming platforms. This makes sense: the rise of <a href="https://www.cloudflare.com/developer-platform/solutions/video-on-demand/">video-on-demand</a> and event-based live streaming has come at the expense of linear streaming.</p></li><li><p>Most broadcasting platforms have their own guest apps which must be downloaded and set up in advance. This introduces unnecessary friction compared to clicking a link in the calendar invite to join a video call.</p></li></ul>
    <div>
      <h3><i>“Wait! Can we just use Zoom + Cloudflare?”</i></h3>
      <a href="#wait-can-we-just-use-zoom-cloudflare">
        
      </a>
    </div>
    <p>One of the core goals of Cloudflare TV was to make it easy for presenters, and what’s easier than letting them use the tools they already know? Everyone on our team is familiar with Zoom, and so are many of the guests who will be appearing on Cloudflare TV. Better yet, Zoom almost always "just works".</p><p>So when we discovered that Zoom lets you push live video to any RTMP end point, we started experimenting with the feature.</p><p>“RTMP” stands for Real-Time Messaging Protocol and was originally developed to facilitate low-latency communication using TCP via Macromedia Flash. RTMP has outlived Flash and is widely used by platforms, including YouTube, to enable live video streaming. RTMP is a push protocol and platforms like YouTube provide RTMP endpoints which are simply URLs. Most video broadcast apps will let you configure multiple RTMP endpoints, which tells the app “<i>hey send my live video feed from my phone or computer to these services</i>.” If you find yourself watching a live video that is being broadcasted on multiple services, it is very likely made possible by RTMP.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/31W6iKPpSmg0aAB0PjhDGb/a809f622de9a52b470541484233f5ea4/image3.png" />
            
            </figure><p>Zoom lets you provide RTMP endpoints and instruct it to send the live video feed of Zoom calls to, in our case, Cloudflare TV’s RTMP. Before we could use this feature, we needed to be able to ingest RTMP video feeds.</p><p>First, we set up an NGINX server with the RTMP module:</p>
            <pre><code>apt-get install build-essential libpcre3 libpcre3-dev libssl-dev git zlib1g-dev -y
mkdir ~/build &amp;&amp; cd ~/build
git clone git://github.com/arut/nginx-rtmp-module.git
wget http://nginx.org/download/nginx-1.14.1.tar.gz
tar xzf nginx-1.14.1.tar.gz
cd nginx-1.14.1
sudo ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module
sudo make
sudo make install</code></pre>
            <p>Next, we configured <code>nginx.conf</code> so NGINX can not only ingest the RTMP feed, but also make it streamable to the end user. A browser typically can’t stream from an RTMP source. We need NGINX to take the RTMP feed and create HLS/DASH segments.</p><p>We defined an application called <code>live</code> inside <code>nginx.conf.</code> Within the live application, we can add directives to ingest RTMP and output HLS:</p>
            <pre><code>...
rtmp {
    server {
        ...
        application live {
            allow play all;
            live on;

            # sample HLS
            hls on;
            hls_path /mnt/hls/;
            hls_fragment 1;
            hls_playlist_length 4;
            hls_sync 100ms;
        }
    }
}
</code></pre>
            <p>Once we had NGINX set up to ingest RTMP and HLS, we followed Zoom’s instructions on <a href="https://support.zoom.us/hc/en-us/articles/360028478292-Streaming-a-Meeting-or-Webinar-on-YouTube-Live">Custom Live Streaming</a>. And soon enough, we had a basic prototype of live streaming Zoom calls using the Cloudflare network!</p>
    <div>
      <h3>Transitions without interruption</h3>
      <a href="#transitions-without-interruption">
        
      </a>
    </div>
    <p>So we met our number one requirement of making the guest experience as easy as joining a video call. But Cloudflare TV isn't going to be one never-ending call. We needed a way to smoothly transition between multiple calls over the course of the day, and to replay some of our favorite segments.</p><p>For example, we may have live programming from 1000 to 1100 followed by two hours of pre-recorded (or replayed) content. When the live programming ends at 1100, the video experience would break and the user would need to hit refresh to see the next show on the schedule.</p><p>So how do we fix this? We determined we needed the following:</p><ol><li><p>Ability to set the programming (the <i>“what plays when?”)</i> many days in advance</p></li><li><p>Have “virtual rooms” ingesting video from different sources (live events, pre-recorded videos stored using our Cloudflare Stream product)</p></li></ol><p>Once we have a schedule and “virtual rooms”, we can dynamically switch what is currently playing on-air to the appropriate “virtual room” streaming the content.</p><p>To implement this, we used Contentful, Workers, and Brave (an open-source video editor).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5XUFf7AdV7b8Wfh6ZG0hTg/54532516d529bee7c145daa52b931c04/image2.png" />
            
            </figure>
    <div>
      <h3>Brave</h3>
      <a href="#brave">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/32SC1qaxTOiSGmirYSKsdD/b5911f46cdc34b13e829375578b77405/image4.png" />
            
            </figure><p><a href="https://github.com/bbc/brave">Brave</a> is an open-source project started by the BBC. Using Brave, we were able to set up multiple virtual rooms and smoothly make any virtual room go on-air.</p><p>Under the hood, Brave is doing two key things:</p><ol><li><p>pulling multiple video feeds from various sources and placing them in virtual rooms</p></li><li><p>pushing the final (“on air feed”) to NGINX <i>every second of the day</i></p></li></ol>
    <div>
      <h3>Contentful</h3>
      <a href="#contentful">
        
      </a>
    </div>
    <p><a href="http://contentful.com/">Contentful</a> is a headless content management platform designed to be API-first; it eliminated the need for a database and helped us build our scheduling feature rapidly.</p><p>Most of the necessary fields are pretty straightforward for a CMS: title, presenters, and, of course, the time slot. Each of these is automatically synced with the publicly-facing schedule at <a href="https://cloudflare.tv/schedule">cloudflare.tv/schedule</a>.</p><p>We are able to use Workers to fetch events from Contentful:</p>
            <pre><code>export async function fetchEventRaw(id: string) {
  let r = await fetch(`${CONTENTFUL_API}/entries/${id}`, {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${CONTENTFUL_ADMIN}`,
    },
  })
  return unwrap(r, 'Failed to retrieve event')
}</code></pre>
            <p>The more complex piece was integrating this with Zoom. Each segment needs its own Zoom meeting, and it’d be pretty arduous to create these manually. So when we publish in Contentful, Contentful makes a call to a Worker endpoint. The Worker endpoint automatically generates a Zoom meeting — and provides the Programming Team with the customized invite to send to the guest.</p><p>For example, when a new event is added to Contentful, Contentful notifies our Worker endpoint which creates a new meeting and configures it so it is being pushed to Cloudflare TV:</p>
            <pre><code>export async function createMeeting(ev: TVEvent) {
  const headers = await zoomHeaders()

  const alternative_hosts = ev.altHosts ? ev.altHosts.join(',') : ''

  ev.zoomPassword = genPassword()

  let r = await fetch(`https://api.zoom.us/v2/users/${ev.studio}@cloudflare.com/meetings`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      topic: ev.title,
      type: 2,
      start_time: ev.start,
      duration: ev.duration,
      timezone: 'UTC',
      agenda: ev.description,
      password: ev.zoomPassword,
      settings: {
        host_video: true,
        participant_video: false,
        alternative_hosts,
        cn_meeting: false,
        in_meeting: false,
        join_before_host: true,
        mute_upon_entry: true,
        watermark: false,
        use_pmi: false,
        approval_type: 2,
        audio: 'both',
        auto_recording: 'cloud',
        enforce_login: false,
      },
    }),
  })
  let data = await unwrap(r, 'Failed to create ZOOM meeting')
  log('zoom: ', data)

  ev.meetingId = data.id
  ev.zoomUrl = data.join_url

  // push livestream configuration data to meeting
  r = await fetch(`https://api.zoom.us/v2/meetings/${ev.meetingId}/livestream`, {
    method: 'PATCH',
    headers,
    body: JSON.stringify({
      //TODO: make configurable
      stream_url: CFTV_RTMP_ENDPOINT,
      stream_key: ev.studio,
      page_url: 'https://cloudflare.tv',
    }),
  })
  await unwrap(r, 'Failed to update LiveStream config')

  return ev
}</code></pre>
            <p>The other upside to using Contentful is that many members of our team already have familiarity with it, so it reduces the overhead of learning a new tool.</p>
    <div>
      <h3>Workers</h3>
      <a href="#workers">
        
      </a>
    </div>
    <p>So far, we’ve described the different pieces of the backend (NGINX, Brave, Contentful) that make Cloudflare TV possible. How do we bring them all together? Cloudflare Workers serves as the glue that brings these systems together. The <a href="https://cloudflare.tv/">Cloudflare TV frontend</a> is built on Worker Sites. The frontend calls our Worker endpoints to fetch data, such as the programming calendar.</p>
    <div>
      <h3>Thinking Ahead...</h3>
      <a href="#thinking-ahead">
        
      </a>
    </div>
    <p>We’re just getting started with Cloudflare TV. We have a long wish list of features we’d really like to see. Here are some of the features we can’t wait to work on:</p><ul><li><p>Improve the viewing experience by adding closed-caption support</p></li><li><p>Enable our viewers to call in and ask questions and contribute to the conversation</p></li><li><p>Bring Cloudflare TV to platforms like Apple TV and Roku</p></li></ul> ]]></content:encoded>
            <category><![CDATA[Live Streaming]]></category>
            <category><![CDATA[Cloudflare Stream]]></category>
            <category><![CDATA[Life at Cloudflare]]></category>
            <category><![CDATA[Cloudflare TV]]></category>
            <guid isPermaLink="false">6n1f4DWW7cUcgbNbTHcqFR</guid>
            <dc:creator>Oliver Yu</dc:creator>
        </item>
    </channel>
</rss>