兄弟们,我最近刷手机老刷到“vs嘴哥”这几个字,一开始我还以为是啥新出的街球对战综艺,点进去一看,好家伙,是直播录像,嘴哥那嗓门,隔着屏幕都能把我家猫吓一跳,但问题是,我有时候就是想看点特定的片段,比如他那句“这球不进我倒立洗头”到底在第几分钟,手动拖进度条?那不是咱程序员该干的事儿。
所以我寻思着,能不能用Go语言直接把这直播视频给“安排”了,别误会,不是说搞什么黑产盗录,咱就是说,能不能把官方公开的回放链接扒下来,然后本地做点分析,你别说,我折腾了一晚上,还真跑通了点东西,但坑也是真不少。

第一步:先搞清楚“vs嘴哥”的视频藏在哪
这年头,直播平台都不傻,视频流基本都走HLS协议,就是一长串的.ts小文件,配一个.m3u8的索引文件,你想拿到完整视频,得先找到那个m3u8文件的真实URL。
我一开始想用Go写个爬虫,直接去解析网页源码,结果发现现在前端都是React、Vue,全是动态渲染的,源码里毛都看不到,用chromedp跑无头浏览器?太笨重了,而且人家有风控,一检测到自动化就给你弹验证码。
后来我是这么干的:打开浏览器开发者工具(F12),切到网络面板,过滤m3u8关键字,然后手动点一下播放,等那个请求出来,直接右键复制为cURL,再把cURL命令转成Go代码,用github.com/avelino/awesome-go里那个http库封装一下请求头,这一步的关键是Referer和User-Agent必须伪装到位,不然服务端直接给你个403。
// 伪代码示意,别直接抄,会报错的
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://fake.cdn.com/live/zhuiwei.m3u8", nil)
req.Header.Set("Referer", "https://www.douyu.com/")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
resp, err := client.Do(req)
拿到m3u8后,里面一般会指向不同清晰度的子文件,比如720p.m3u8、1080p.m3u8,我挑了1080p的,因为嘴哥那表情包,糊了就没内味儿了。
第二步:用Go并发下载,但别把服务器搞崩了
m3u8里是一堆.ts分片,每个大概几秒钟,串行下载那得等到猴年马月,Go的goroutine这时候就好使了,我开了20个协程,用sync.WaitGroup来控制。
var wg sync.WaitGroup
for i, segment := range segments {
wg.Add(1)
go func(idx int, url string) {
defer wg.Done()
// 下载并保存为 part_xxx.ts
}(i, segment.URI)
}
wg.Wait()
但这里有个大坑:如果下载太快,平台会直接封IP,我因为贪快,一口气下了500个分片,结果IP被限流了十分钟,啥都访问不了,后来我加了个time.Sleep(50 * time.Millisecond),再配合一个简单的令牌桶限速,才算稳住。
| 并发数 | 下载500个分片耗时 | 是否触发风控 |
|---|---|---|
| 5 | 8分钟 | 否 |
| 20 | 3分钟 | 是 |
| 10 | 5分钟 | 否 |
所以兄弟们, 别贪, 10个并发够了,你也不想凌晨三点被平台的安全邮件问候吧?
第三步:合并分片,但更绝的是“抽帧”分析
下载完1000多个.ts文件后,得合并成一个mp4,直接用cat命令拼?Windows上不行的,用ffmpeg吧,但Go的os/exec调用一下就行,这步极其简单,复杂的是我想做嘴哥语音识别,看看他那句“兄弟们,这波不亏”到底说了几次。
如果你只想看视频,那合并完就完事儿了,但如果你想定位某句话,比如那句经典台词,就得用ffmpeg把音频抽出来,转成wav,再用讯飞或者百度的语音识别API,但这得花钱,而且嘴哥那口音,识别率感人。
我了个更聪明的土办法:直接抽关键帧,嘴哥激动的时候,画面会有字幕条弹出来,我用Go写了个脚本,每隔1秒抽一帧(用goav库),然后做一下图像差异对比,如果当前帧和上一帧的像素差超过阈值(比如人脸区域变化大),就保存下来,这样一搞,虽然没有语音识别那么智能,但能把嘴哥说话时手舞足蹈的瞬间抓出来。
// 伪代码:计算两帧的PSNR值,低于25就认为是有大变化
psnr := calculatePSNR(prevFrame, currFrame)
if psnr < 25.0 {
saveFrame(currFrame, fmt.Sprintf("key_%d.jpg", i))
}
结果还挺有意思,我抓到了376个关键瞬间,其中有一张,嘴哥眼睛瞪得跟铜铃似的,配的字幕是“这球要是不进,我把篮球吃了”,真实得一批。
vs嘴哥”最火的那个怼脸镜头
很多人问,最新一期“vs嘴哥”里,他是不是真把矿泉水瓶捏爆了?我下载完看了下那个分片时间戳,是第38分52秒,你别看网上传的都是动图,那都是剪辑过的,水是溅到他自己脸上了,旁边那个裁判直接笑场,视频分析完,我发现那个瓶子捏爆前的半秒,嘴哥的喉结有明显的下压动作,这哥们是真使劲了,不是演的。
这让我想到,如果做直播带货的商品分析,比如看嘴哥卖货时哪件商品出镜时间最长,用这套Go工具链也能做,就是得框选商品区域,跑个简单的物体识别模型,YOLO那种,我试过用gocv跑个轻量版,CPU占用率很高,但能跑出大概位置,不过我现在懒得折腾了,因为周末我想去看场线下球赛,不想再对这屏幕了。
我这方案算不上什么高科技,就是Go的并发加ffmpeg的批处理,加起来不到300行代码,你要是想扒其他主播的直播回放也一个道理,改一下m3u8地址就行,不过还是得提醒一句,下载下来自己看行,别二次传播,嘴哥那团队法务不是吃素的,听说最近在告一个搬运工,索赔了几万块,我反正看完就删,只留了几张表情包,那捏爆瓶子的截图,我现在当手机壁纸了,挺解压的。
本文来自作者[kyadmin]投稿,不代表中国·AC米兰(Milan)体育官方网站-Official Website立场,如若转载,请注明出处:http://f6336.com/ny/1403.html
评论列表(4条)
我是中国·AC米兰(Milan)体育官方网站-Official Website的签约作者“kyadmin”!
希望本篇文章《用Go语言扒下vs嘴哥最新直播视频?这事儿我真试了,结果有点意思》能对你有所帮助!
本站[中国·AC米兰(Milan)体育官方网站-Official Website]内容主要涵盖:AC米兰,ac米兰官网,AC米兰官网
本文概览:兄弟们,我最近刷手机老刷到“vs嘴哥”这几个字,一开始我还以为是啥新出的街球对战综艺,点进去一看,好家伙,是直播录像,嘴哥那嗓门,隔着屏...