那段视频到底藏在哪?
前两天刷手机又刷到《365天:今时之欲》的游轮片段,弹幕里一堆人问“背景音乐叫啥”“这段拍摄地在哪”,我寻思着,与其在评论区当复读机,不如自己写个小工具把那段视频扒下来分析分析,说干就干,打开电脑,Golang的logo在那儿冲我眨眼——得,就用它了。
为什么非要用Golang?Python它不香吗?
说实话,我平时写Python更多,但这次选Golang有三个实打实的原因:

- 编译成单个可执行文件——扔到服务器上就跑,不用管依赖环境
- 并发是亲儿子——抓取多个分片视频时,goroutine甩开Python的线程几条街
- 标准库够硬——
net/http、io这些包处理流媒体下载,比Python的requests+urllib组合拳省心
你要是问我Python行不行?当然行,但咱今天聊的是Golang,对吧?
第一步:找到视频的真实地址(这步最坑)
游轮那段视频在流媒体平台上,直接<video>标签里的src是个blob:协议,压根没法直接下载,得用浏览器开发者工具翻Network面板,找.m3u8文件。
这里我踩了个坑——跨域请求的Referer和User-Agent必须伪装成浏览器,不然服务器直接甩个403,代码长这样:
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
req.Header.Set("Referer", "https://www.example.com/")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
return nil
},
}
第二步:解析m3u8文件——Golang的strings.Split够用了
.m3u8文件本质就是个文本清单,记录了视频分片的URL,用bufio.Scanner逐行读,遇到不以开头的行就是分片地址:
scanner := bufio.NewScanner(resp.Body)
var segments []string
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line != "" && !strings.HasPrefix(line, "#") {
segments = append(segments, line)
}
}
有的m3u8里分片地址是相对路径,得用url.Parse拼上base URL,不然下载一堆404,这步我一开始没注意,白白浪费了5分钟调试。
第三步:并发下载分片——goroutine+WaitGroup
游轮那段视频有300多个分片,每个几百KB,串行下载得等半天,用并发瞬间就能拉完:
var wg sync.WaitGroup
segChan := make(chan string, 10) // 缓冲通道控制并发数
for i := 0; i < 8; i++ { // 8个worker
wg.Add(1)
go func() {
defer wg.Done()
for segURL := range segChan {
// 下载逻辑,存为seg_001.ts类似的文件
}
}()
}
for _, seg := range segments {
segChan <- seg
}
close(segChan)
wg.Wait()
注意:并发数别开太大,有的服务器有限流,开20个worker反而容易触发反爬,8个挺稳的。
第四步:合并分片——ffmpeg来收尾
下载下来的.ts分片得合并成完整的mp4,最省事的方式是调系统命令:
cmd := exec.Command("ffmpeg", "-f", "concat", "-safe", "0", "-i", "filelist.txt", "-c", "copy", "output.mp4")
cmd.Run()
前提是得提前生成一个filelist.txt,格式是file 'seg_001.ts',用Golang写这文件比手打快多了:
var files strings.Builder
for i := 0; i < len(segments); i++ {
fmt.Fprintf(&files, "file 'seg_%03d.ts'\n", i)
}
os.WriteFile("filelist.txt", []byte(files.String()), 0644)
踩坑记录:这五个坑我帮你先踩了
| 坑 | 现象 | 解决办法 |
|---|---|---|
| 分片文件名补零 | 100号分片排到2号前边 | fmt.Sprintf("%03d", i)强制三位数 |
| 内存溢出 | 大文件一次性ReadAll卡死 | 用io.Copy边读边写 |
| 加密m3u8 | 分片是加密的,合并后花屏 | 解析#EXT-X-KEY,用openssl解密 |
| 重试机制 | 网络抖动导致分片下载失败 | 加个简单的错误重试循环 |
| 磁盘空间不足 | 忘了清理临时ts文件 | 合并完用os.Remove清理 |
优化:如果你还想玩点花的
拿到视频后,我突然想知道游轮那段插曲到底用了哪个镜头角度,顺手用github.com/u2takey/ffmpeg-go这个库做了关键帧提取,每隔10秒抓一帧,直接拼成九宫格,效果还挺惊艳。
代码就不全贴了,核心就是:
err := ffmpeg.Input("output.mp4").
Output("frame_%02d.png", ffmpeg.KwArgs{"vf": "fps=1/10"}).
OverWriteOutput().
ErrorToStdOut().
Run()
最后的多嘴一句
折腾完这段视频,我突然觉得Golang特别适合这种“小工具型”任务——写起来不像Java那么啰嗦,跑起来又比Python靠谱,你要是也想扒点东西,建议先从这下边几个地方入手:
go-rod:用代码控制浏览器,自动抓取m3u8链接go-m3u8:专门的解析库,不用自己手写逻辑aria2(RPC调用):下载速度比自带http包快好几倍
好了,我得去给视频配字幕了,下次见,如果还有什么想看的视频不知道怎么搞,留言告诉我,咱们接着折腾。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://hljbesthome.com/tiyu/2487.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Golang扒下365dni游轮那一段插曲视频,一个普通程序员的折腾手记》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:那段视频到底藏在哪?前两天刷手机又刷到《365天:今时之欲》的游轮片段,弹幕里一堆人问“背景音乐叫啥”“这段拍摄地在哪”,我寻思着,...