hls.newplaylist 返回空指针是因为它只是工厂函数,不创建具体实例,需明确调用 hls.newmediaplaylist 或 hls.newmasterplaylist 才能获得可用播放列表。

为什么 hls.NewPlaylist 返回空指针?
因为没初始化播放列表类型,hls.NewPlaylist 本身不创建具体实例,它只是工厂函数,返回的是 nil —— 你得明确告诉它要生成 hls.MediaPlaylist 还是 hls.MasterPlaylist。
- 常见错误:直接
pl := hls.NewPlaylist(); pl.Append(...),立刻 panic - 正确做法:用
hls.NewMediaPlaylist(2, 10)(窗口大小 2,总容量 10)或hls.NewMasterPlaylist() - 注意参数含义:
hls.NewMediaPlaylist(targetDuration, capacity)中targetDuration单位是秒,必须是整数,小数会被截断,导致#EXT-X-TARGETDURATION不合法 - Web 播放器(如 hls.js)对
#EXT-X-TARGETDURATION非常敏感:若实际 ts 片段时长超过该值,部分版本会卡住或静音
如何让 Go 生成的 m3u8 被 hls.js 正确加载?
关键不在格式“对不对”,而在响应头、路径和 CORS 是否匹配浏览器实际请求链路。
- 必须设置
Content-Type: application/vnd.apple.mpegurl,不能用text/plain或application/x-mpegURL(后者 hls.js 旧版可能拒收) - 所有
.ts和.m3u8路径必须可被浏览器直接 GET 到;若用相对路径(如segment-1.ts),确保服务器路由能映射到真实文件或 handler - 如果流地址跨域(比如前端跑在
localhost:3000,后端在:8080),必须在 Go HTTP handler 中加Access-Control-Allow-Origin: *(或具体域名),否则 hls.js 拿不到响应体 - 避免在 m3u8 中写本地文件路径(如
/tmp/seg.ts)—— 浏览器根本访问不了,只写 URL 可达路径
io.Copy 写 ts 文件后,hls.js 报 “failed to load segment” 是为什么?
大概率是 ts 文件不完整或未 flush,浏览器拿到的是截断数据,解码失败。
本文档主要讲述的是android rtsp流媒体播放介绍;实时流协议(RTSP)是应用级协议,控制实时数据的发送。RTSP提供了一个可扩展框架,使实时数据,如音频与视频,的受控、点播成为可能。数据源包括现场数据与存储在剪辑中数据。该协议目的在于控制多个数据发送连接,为选择发送通道,如UDP、组播UDP与TCP,提供途径,并为选择基于RTP上发送机制提供方法。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
- 别用
os.Create+io.Copy就完事:默认文件句柄无缓冲,但写入中途若服务重启或 panic,最后几 KB 可能滞留在内核页缓存里没落盘 - 务必在
io.Copy后调用f.Close()——Close()会触发底层fsync(Linux/macOS)或等价刷盘操作 - 更稳妥的做法:先写到临时文件(如
seg-1.ts.tmp),Close()成功后再os.Rename();hls.js 只认最终存在的文件名,避免播放器读到正在写的半成品 - 验证方法:用
ffprobe seg-1.ts看是否报invalid data found when processing input,有则说明文件损坏
并发写多个 ts 片段时,hls.MediaPlaylist.Append 为啥丢片段?
因为 hls.MediaPlaylist 不是线程安全的,Append 会修改内部 slice 和计数器,竞态下会覆盖或跳过条目。
立即学习“go语言免费学习笔记(深入)”;
- 不要在 goroutine 里直接调用
playlist.Append();所有 playlist 修改必须串行 - 推荐模式:用 channel 收集新片段信息(如文件名、时长),由单个“playlist 更新 goroutine”消费并调用
Append,再广播更新后的 m3u8 内容 - 别试图用
sync.Mutex包一层就完事 ——Append内部还可能 realloc slice,锁粒度太粗反而掩盖问题,且易引发死锁(比如锁期间调用 http.Write) - 注意:每次
Append后需重新生成 m3u8 字符串(playlist.String()),不能复用旧字符串,因为内部状态已变
真正难的不是生成 m3u8,而是保证 ts 文件原子写入、playlist 状态与磁盘文件严格一致、以及所有路径和头信息刚好落在浏览器加载策略的“舒适区”里。漏掉其中一环,前端就只会显示 loading 转圈。









