手把手教你用 Golang 玩转 m3u8,视频切片+直播全搞定
作者:佚名 时间:2025-11-19 12:36

m3u8 是什么?它的名字有何来历?
当你在视频网站点开一个视频,或者刷直播时,背后都有可能是 .m3u8 文件在默默发力。它并不是视频文件本身,而是一个索引清单,告诉播放器:“嘿,这里有一堆分片视频,照着顺序一个个播就行了。”
m3u8 是 Apple 推出的 HLS(HTTP Live Streaming)协议的一部分,本质上是一个基于 UTF-8 编码的扩展 M3U 播放列表。别看这名字有点“生僻”,其实挺有逻辑:M3U 是最早的播放列表格式,而后缀中的 8 就代表它采用的是 UTF-8 编码——M3U + UTF-8 = m3u8,命名就这么简单粗暴。
这种格式为什么会火?因为它几乎天然适配各种网络环境。哪怕用户在地铁上信号忽强忽弱,播放器也能智能地选择合适的分片质量,实现“不卡顿”的观看体验。对于开发者来说,它的纯文本结构、分片机制、HTTP传输方式,也让实现和部署变得非常轻便。
m3u8 文件结构长啥样?
m3u8 文件其实就是一个“点播/直播清单”,每一段 .ts 视频片段(Transport Stream)都会在里面有自己的位置。
打开一个 m3u8 文件,你大概率会看到这些内容:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY
#EXTINF:2.000000,
output0.ts
#EXTINF:2.000000,
output1.ts
#EXTINF:2.000000,
output2.ts
#EXTINF:2.000000,
output3.ts
#EXT-X-ENDLIST
每一项标签都有含义:
播放器会根据这个清单逐个加载对应的 ts 文件,拼接还原成完整视频流。如果是直播流,还会实时更新这个文件,保证“后进来的观众”也能正常观看。
用 Golang + FFMPEG,实现视频切片转 m3u8
想用 Golang 实现本地视频转成 m3u8 格式,核心其实是调用 ffmpeg 的切片命令,并用 Golang 封装自动化流程。
基础命令如下:
ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename "segment%d.ts" \
output.m3u8
Golang 封装示例:
package main
import (
"fmt"
"os/exec"
)
func ConvertToM3U8(inputPath, outputDir string) error {
cmd := exec.Command("ffmpeg",
"-i", inputPath,
"-c:v", "libx264",
"-c:a", "aac",
"-f", "hls",
"-hls_time", "10",
"-hls_list_size", "0",
"-hls_segment_filename", outputDir+"/segment%d.ts",
outputDir+"/output.m3u8",
)
return cmd.Run()
}
func main() {
input := "input.mp4" // 输入文件路径
outputDir := "." // 输出目录
if err := ConvertToM3U8(input, outputDir); err != nil {
fmt.Printf("转换失败: %v\n", err)
} else {
fmt.Println("转换成功")
}
}
这样,就能通过 Golang 让本地 mp4 一键转码成 m3u8+ts 文件,部署到 CDN 或本地服务器都很方便。
屏幕也能推流?Golang 带你玩直播
除了本地转码,另一个有趣玩法是:将屏幕内容实时录制并推送为 m3u8 格式的直播流!
你没听错,m3u8 不光能点播,它其实也能“伪实时直播”。核心仍然是 ffmpeg 的命令组合。
FFmpeg 实时推流命令(Windows):
ffmpeg -f gdigrab -framerate 30 -i desktop \
-c:v libx264 -preset fast -tune zerolatency -pix_fmt yuv420p \
-crf 23 -r 30 \
-f hls -hls_time 3 -hls_list_size 5 \
-hls_flags delete_segments+append_list \
-hls_segment_filename "segment%d.ts" \
output.m3u8
用 Golang 调用:
package main
import (
"log"
"net/http"
"os/exec"
)
func StartScreenStream() error {
cmd := exec.Command("ffmpeg",
"-f", "gdigrab",
"-framerate", "30",
"-i", "desktop",
"-c:v", "libx264",
"-preset", "fast",
"-tune", "zerolatency",
"-pix_fmt", "yuv420p",
"-crf", "23",
"-r", "30",
"-f", "hls",
"-hls_time", "3",
"-hls_list_size", "5",
"-hls_flags", "delete_segments+append_list",
"-hls_segment_filename", "segment%d.ts",
"output.m3u8",
)
return cmd.Run()
}
func main() {
go StartScreenStream()
// 播放地址 http://127.0.0.1:8000/output.m3u8
http.Handle("/", http.FileServer(http.Dir(".")))
log.Println("Server started at :8000")
http.ListenAndServe(":8000", nil)
}
这样启动之后,只需要让播放器加载 output.m3u8,就能实现“准实时”的直播体验。
m3u8 直播,凭什么能替代 FLV?
传统直播大多使用 FLV+RTMP 方案,但这套组合存在很多局限:
而 m3u8(即 HLS)恰好解决了这些痛点:
虽然它比 FLV 有 3~6 秒的延迟,但这点换来稳定和兼容,很多场景(如教育、电商直播)完全可以接受。
总结一句话
不论你是想开发一个小型视频网站,还是做轻量直播系统,m3u8 都是个值得研究的好伙伴。而 Golang + FFmpeg 的组合,则能帮你把复杂的音视频操作变得异常简单。




