HLS

HLS

HTTP Live Streaming with adaptive bitrate, transcoding, and distributed support

Overview

github.com/xraph/forge/extensions/hls provides an HTTP Live Streaming (HLS) server with adaptive bitrate streaming, multi-variant playlists, FFmpeg transcoding, and optional distributed mode. It registers an HLS service in the DI container and mounts streaming and management endpoints on the Forge HTTP router.

What It Registers

ServiceDI KeyType
HLS servicehls*Manager (satisfies HLS)

Dependencies

  • Required: storage extension -- segments and playlists are stored via the storage manager.
  • Optional: consensus extension -- required for distributed mode with leader election and stream ownership.

Quick Start

package main

import (
    "context"

    "github.com/xraph/forge"
    "github.com/xraph/forge/extensions/hls"
    "github.com/xraph/forge/extensions/storage"
)

func main() {
    app := forge.NewApp(forge.AppConfig{Name: "video-app", Version: "1.0.0"})

    // Storage extension is required for segment storage
    app.RegisterExtension(storage.NewExtension(
        storage.WithDefault("media"),
        storage.WithLocalBackend("media", "/var/data/media"),
    ))

    // HLS extension
    app.RegisterExtension(hls.NewExtension(
        hls.WithBasePath("/hls"),
        hls.WithBaseURL("https://cdn.example.com/hls"),
        hls.WithTranscoding(true,
            hls.Profile360p,
            hls.Profile720p,
            hls.Profile1080p,
        ),
        hls.WithDVRWindow(30), // 30 segments DVR window
    ))

    ctx := context.Background()
    app.Start(ctx)
    defer app.Stop(ctx)

    // Resolve the HLS service
    hlsSvc, _ := forge.Inject[hls.HLS](app.Container())

    // Create a live stream
    stream, _ := hlsSvc.CreateStream(ctx, hls.StreamOptions{
        Title:          "Live Event",
        Type:           hls.StreamTypeLive,
        TargetDuration: 6,
        DVRWindowSize:  30,
        TranscodeProfiles: []hls.TranscodeProfile{
            hls.Profile360p,
            hls.Profile720p,
        },
    })

    // Start the live stream
    hlsSvc.StartLiveStream(ctx, stream.ID)

    // Ingest a segment (typically called by your media pipeline)
    hlsSvc.IngestSegment(ctx, stream.ID, &hls.Segment{
        StreamID:    stream.ID,
        VariantID:   "720p",
        SequenceNum: 1,
        Duration:    6.0,
        Data:        segmentData,
    })

    // Get the master playlist URL
    masterURL := fmt.Sprintf("/hls/%s/master.m3u8", stream.ID)
}

VOD (Video on Demand)

// Create a VOD stream from an existing video file
stream, _ := hlsSvc.CreateVOD(ctx, hls.VODOptions{
    Title:    "Training Video",
    SourceURL: "/path/to/video.mp4",
    Profiles: []hls.TranscodeProfile{hls.Profile480p, hls.Profile720p, hls.Profile1080p},
})

// Or transcode an existing video
hlsSvc.TranscodeVideo(ctx, stream.ID, hls.TranscodeProfile{
    Name:       "720p",
    Width:      1280,
    Height:     720,
    Bitrate:    2500000,
    AudioBitrate: 128000,
})

Using HLS in Your Services

type VideoService struct {
    hls    hls.HLS
    logger forge.Logger
}

func NewVideoService(h hls.HLS, logger forge.Logger) *VideoService {
    return &VideoService{hls: h, logger: logger}
}

func (vs *VideoService) StartLiveEvent(ctx context.Context, title string) (string, error) {
    stream, err := vs.hls.CreateStream(ctx, hls.StreamOptions{
        Title: title,
        Type:  hls.StreamTypeLive,
    })
    if err != nil {
        return "", err
    }
    return stream.ID, vs.hls.StartLiveStream(ctx, stream.ID)
}

func (vs *VideoService) GetStreamStats(ctx context.Context, streamID string) (*hls.StreamStats, error) {
    return vs.hls.GetStreamStats(ctx, streamID)
}

HTTP Endpoints

Routes are mounted under BasePath (default /hls):

MethodPathPurpose
GET/:streamID/master.m3u8Master playlist
GET/:streamID/variants/:variantID/playlist.m3u8Media playlist
GET/:streamID/variants/:variantID/segment_:num.tsMedia segment
POST/streamsCreate a stream
GET/streams/:streamIDGet stream info
DELETE/streams/:streamIDDelete a stream
GET/streamsList streams
POST/streams/:streamID/startStart live streaming
POST/streams/:streamID/stopStop live streaming
POST/streams/:streamID/ingestIngest a segment
GET/streams/:streamID/statsStream statistics

Key Concepts

  • Streams -- create live, VOD, or event streams. Each stream has a unique ID, multiple variants, and a master playlist.
  • Variants -- each stream can have multiple quality variants (e.g. 360p, 720p, 1080p) with different bitrates and resolutions.
  • Segments -- media is divided into time-based segments (default 6 seconds). Segments are stored via the storage extension.
  • Transcoding -- FFmpeg-based transcoding converts ingested media into multiple quality variants.
  • DVR window -- configurable sliding window of segments in live playlists for time-shifted viewing.
  • Distributed mode -- scale HLS across nodes with consensus-based leader election and stream ownership.

Detailed Pages

How is this guide?

On this page