Go语言视频切片需用io.SectionReader分段读取避免offset竞争,预分配buffer批量写入,控制SSD/HDD并发数(8–16/4–8),并确保key frame对齐以保障可播放性。

Go 语言里用协程处理视频切片,核心不是“能不能并发”,而是“怎么避免 IO 阻塞 + 怎么控制并发粒度 + 怎么保证切片边界不越界”。直接 go io.Copy 多个 goroutine 写同一文件或读同一 *os.File,大概率出错或性能反降。
video 文件必须用 io.SectionReader 分段读取
视频文件通常很大,不能 whole-file load 到内存;也不能让多个 goroutine 同时 Read() 同一个 *os.File,因为底层 file offset 是共享的,会互相干扰。
-
os.Open()后得到的*os.File是一个可寻址句柄,但它的读位置(offset)是全局状态,goroutine 并发调用Read()会竞争 offset,结果不可预测 - 正确做法:用
os.Stat()获取文件总大小,再按 byte range 构造多个io.SectionReader实例,每个 goroutine 持有独立的 reader,互不干扰 - 示例:切第 2 段(从 100MB 开始、长度 50MB)→
sr := &io.SectionReader{r: f, off: 100 * 1024 * 1024, n: 50 * 1024 * 1024}
写入切片文件时别用 os.Create + io.Copy 直接套娃
io.Copy 默认是阻塞同步写,如果开 10 个 goroutine 同时 io.Copy(sr, dst),且 dst 是普通磁盘文件,实际仍是串行刷盘——OS 层面的 write 调用会被调度器排队,还可能触发大量小块 write 系统调用,反而比单 goroutine 慢。
- 真正提速点在「读」阶段:用
SectionReader并发读不同区间,把数据提前拉进内存 - 写阶段建议预分配 buffer(比如
make([]byte, 1),再用 <code>dst.Write(buf)批量写,避免io.Copy内部反复 malloc - 若目标是生成多个独立文件(如
part_001.mp4,part_002.mp4),每个 goroutine 自己os.Create自己的文件,完全隔离
并发数不是越多越好,runtime.GOMAXPROCS 和磁盘类型决定上限
SSD 上并发 8~16 个 reader 基本打满带宽;HDD 上超过 4 个就容易 seek 抖动,吞吐不升反降。盲目设 runtime.GOMAXPROCS(100) 没用,IO-bound 场景下 goroutine 数 ≠ 并发读能力。
立即学习“go语言免费学习笔记(深入)”;
- 实测建议:先用
dd if=/dev/zero of=test.bin bs=1M count=1000测磁盘顺序写速度,再按该速度 / 单切片大小 ≈ 合理并发数 - 务必加限流 channel(如
sem := make(chan struct{}, 4)),每个 goroutine 启动前sem ,结束时 <code>,防止瞬时打开太多文件句柄 - 忽略
os.Getwd()或相对路径问题:视频路径传入 goroutine 前必须转成绝对路径,否则不同 goroutine 可能因os.Chdir(或其他库调用)导致 open 失败
最易被忽略的是切片边界对齐——MP4 文件有 moov atom,直接按字节截断会导致部分切片无法播放;实际生产中得解析容器结构,至少确保每个切片以 key frame 对齐,这不是纯 IO 问题,而是音视频领域知识硬门槛。


















