hls

package
v0.8.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package hls 提供一个直播/点播 HLS origin:管理滚动分片窗口、生成 m3u8 播放列表, 并作为 http.Handler 挂在任意 mux(如 pkg/service/webserver)上分发。

边界(和框架"薄机制"一致):本包**不做编解码/转码/切片**。分片(.ts / .m4s)由上游 产出后 Append 进来——上游可以是 ffmpeg,或 pkg/media/rtmp 采集后的 remux。纯 Go、 零 cgo,只负责"存分片窗口 + 出播放列表 + HTTP 分发"这三件苦活。

用法:

s := hls.NewStream(hls.WithWindow(6), hls.WithTargetDuration(2*time.Second))
mux.Handle("/live/", http.StripPrefix("/live", s)) // s 实现 http.Handler
// 上游每产出一个分片:
s.Append(segBytes, 1980*time.Millisecond)
// 直播结束转点播:
s.Finish()

播放端拉 /live/index.m3u8 → 得到 media playlist,再按其中的 seg{N}.ts 拉分片。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DiskStore

type DiskStore struct {
	// contains filtered or unexported fields
}

DiskStore 把分片写到目录下的文件(seg{seq}.dat),重启后仍在(可做简单持久化/大窗口)。 淘汰即删文件。文件名与播放列表 URL 无关(HTTP 侧按 seq 经 Store 取,不直接暴露路径)。

func NewDiskStore

func NewDiskStore(dir string) (*DiskStore, error)

NewDiskStore 创建磁盘 Store,分片落在 dir(不存在则创建)。

func (*DiskStore) Get

func (d *DiskStore) Get(seq uint64) ([]byte, bool, error)

func (*DiskStore) Put

func (d *DiskStore) Put(seq uint64, data []byte) error

func (*DiskStore) Remove

func (d *DiskStore) Remove(seq uint64) error

type Master

type Master struct {
	// contains filtered or unexported fields
}

Master 把多路码率变体组合成一个 ABR 主清单,并按变体名路由到各自 Handler。

func NewMaster

func NewMaster(variants ...Variant) *Master

NewMaster 创建主清单。各 Variant 至少要有 Name、Bandwidth、Handler。

func (*Master) Playlist

func (m *Master) Playlist() []byte

Playlist 生成 master playlist(m3u8)。

func (*Master) ServeHTTP

func (m *Master) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP 实现 http.Handler:根路径的 *.m3u8 返回 master playlist;/{variant}/… 去掉 变体名前缀后交给该变体的 Handler。

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore 把分片存在内存 map 里,进程退出即丢。适合直播滚动窗口(总量有界)。

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore 创建内存 Store。

func (*MemoryStore) Get

func (m *MemoryStore) Get(seq uint64) ([]byte, bool, error)

func (*MemoryStore) Put

func (m *MemoryStore) Put(seq uint64, data []byte) error

func (*MemoryStore) Remove

func (m *MemoryStore) Remove(seq uint64) error

type Option

type Option func(*config)

Option 配置 Stream。

func WithPartTarget

func WithPartTarget(d time.Duration) Option

WithPartTarget 开启 LL-HLS(低延迟)并设置部分分片(part)目标时长(如 333ms)。 开启后用 AppendPart/CompleteSegment 驱动(而非 Append),播放列表带 EXT-X-PART 等指令 并支持阻塞式刷新。

func WithSegmentExt

func WithSegmentExt(ext string) Option

WithSegmentExt 设置分片扩展名(默认 ".ts";fMP4 用 ".m4s",此时通常需配 SetInitSegment)。

func WithStore

func WithStore(s Store) Option

WithStore 设置分片存储后端(默认内存)。可用 NewDiskStore 落磁盘,或自实现对象存储。

func WithTargetDuration

func WithTargetDuration(d time.Duration) Option

WithTargetDuration 设置 #EXT-X-TARGETDURATION(默认从分片时长推断,取上界并向上取整)。

func WithWindow

func WithWindow(n int) Option

WithWindow 设置直播播放列表保留的分片数(滚动窗口,默认 6)。点播不受此限。

type Store

type Store interface {
	Put(seq uint64, data []byte) error    // 写入一个分片
	Get(seq uint64) ([]byte, bool, error) // 读取;不存在返回 (nil,false,nil)
	Remove(seq uint64) error              // 淘汰(不存在也不报错)
}

Store 是分片字节的可插拔存储后端。Stream 只在内存里维护播放列表元数据(序号+时长), 分片内容的存/取/淘汰交给 Store——从而支持内存、磁盘、对象存储等不同落地。

实现须并发安全(Append 来自采集 goroutine,Get 来自多个 HTTP 请求)。

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream 是一路 HLS 流。零值不可用,用 NewStream 构造。并发安全。

func NewStream

func NewStream(opts ...Option) *Stream

NewStream 创建一路 HLS 流。

func (*Stream) Append

func (s *Stream) Append(data []byte, dur time.Duration) (uint64, error)

Append 追加一个分片,返回其序号。分片字节写入 Store;直播模式下超出窗口会淘汰最旧 分片(从 Store 删除并推进 media-sequence)。Finish 之后调用无效果,返回 (0, nil)。 Store 写入失败时返回错误(此时不改动播放列表)。

func (*Stream) AppendPart

func (s *Stream) AppendPart(data []byte, dur time.Duration, independent bool)

AppendPart 追加一个部分分片到"当前正在构建的分片"(LL-HLS)。independent 表示该 part 是否可独立解码(通常本分片首个 part 为 true)。仅在 WithPartTarget 开启时有意义。

func (*Stream) CompleteSegment

func (s *Stream) CompleteSegment() error

CompleteSegment 把当前构建中的各 part 合并成一个完整分片(序号 nextSeq)收官,进入滚动 窗口;随后开始累积下一个分片。LL-HLS 专用(与 Append 互斥使用)。

func (*Stream) Finish

func (s *Stream) Finish()

Finish 标记流结束:播放列表加 #EXT-X-ENDLIST 变为点播,且不再淘汰当前窗口内分片。

func (*Stream) MediaPlaylist

func (s *Stream) MediaPlaylist() []byte

MediaPlaylist 生成当前的 media playlist(m3u8)。

func (*Stream) SegmentData

func (s *Stream) SegmentData(seq uint64) ([]byte, bool)

SegmentData 按序号取分片数据(仍在窗口内才有)。

func (*Stream) ServeHTTP

func (s *Stream) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP 实现 http.Handler:分发播放列表、init 分片与各媒体分片。 路由(去掉挂载前缀后):

  • *.m3u8 → media playlist
  • init.mp4 → fMP4 初始化分片(若已 SetInitSegment)
  • seg{N}.ext → 序号 N 的分片

func (*Stream) SetInitSegment

func (s *Stream) SetInitSegment(data []byte)

SetInitSegment 设置 fMP4 的初始化分片(EXT-X-MAP,URI 为 init.mp4)。TS 分片无需调用。

type Variant

type Variant struct {
	Name       string       // URL 路径段,如 "720p"(master 里引用为 720p/index.m3u8)
	Bandwidth  int          // 峰值码率 bits/s(BANDWIDTH,必填)
	Resolution string       // 如 "1280x720"(RESOLUTION,可空)
	Codecs     string       // 如 "avc1.64001f,mp4a.40.2"(CODECS,可空)
	Playlist   string       // 变体 media playlist 的文件名(默认 "index.m3u8")
	Handler    http.Handler // 分发该变体 media playlist + 分片
}

Variant 是 ABR(自适应码率)里的一路码率变体。Handler 负责分发这一路的 media playlist 与分片——既可是本包的 *Stream(进程内 remux/copy),也可是 http.FileServer (指向 ffmpeg 转码写出的目录),因此 Master 能同时适配"进程内"与"ffmpeg 外部转码"两种产源。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL