https://github.com/hoshinohikari/ShowroomRecorder
年更人来了(
最近因为某些原因,所以录制showroom这个傻逼平台比较多,所以研究了一下这个平台的检测开播和录制的功能,之前网上有一些参考的工具,大部分都是用python写的,python做的开播检测和地址抓取部分,而流下载的部分则是由ffmpeg来执行的。
当然这个设计本身是没有什么问题的,python确实适合做这种事情。但是ffmpeg始终还是一个视频编解码软件而并非专业的下载器,在使用ffmpeg的时候经常会遇到各种问题,例如,m3u8获取超时了怎么办,中间缺块了怎么办,等等等等
于是我将开播检测和流获取的部分移植到了C#,并且添加了多下载器支持的功能,先后支持了 ffmpeg、minyami、minyami-iori、streamlink
因为用minyami和minyami-iori比较多,所以大概理解这两个软件的设计思路,本身它们是作为一个多平台支持的下载器,所以有一些东西做的比较普适,肯定不能为了某个平台去做特别的优化,再加上本身的开发人员有限,不太能做到面面俱到;而streamlink作为一个成熟的软件提供了众多的选项可以设置,在这一点上是非常好的,但是它在某些情况下也不太适配showroom这个垃圾平台,我给他提过issue但是作者团队的回复说,streamlink是一个直播实时观看的软件而并非一个下载的软件,所以拒绝解决我提出的问题,这个我们下面再谈。
所以想了半天,还是自己去写这个特殊化的下载器算了。
特别感谢我的代码指导大师,Claude 3.7 Sonnet,起码提高了我三倍的效率(x)
开播检测逻辑
用户信息
这个很简单,用户的用户名就是直播间的地址最后面那一串,将其放入 www.showroom.com/api/room/status 就可以获取到用户的ID,然后将用户的ID输入到 www.showroom.com/api/live/live_info 就可以得到用户开播与否的信息,这个就可以实现开播监控了。
流获取
用户每次开播的流地址都是随机的,但是用户的ID是固定的,所以一般用 ID去获取流信息,接口为 www.showroom.com/api/live/streaming_url ,从这个接口就可以获取到这次开播使用的流地址。
流录制
这部分其实才是最关键的...上面的部分都属于非常简单的请求获取,但是流录制才是最坑的地方,也能看出来这个破网站的后端到底写的多差(x
showroom采用的是标准的hls协议,本身获取这个流并且下载是没有难度的,但是不知道是不是后端的负载写的有问题,我在录制过程中遇到过一下这些问题:
- 长时间无法获取m3u8
showroom的m3u8中,每次获取会保留最近的3个segment,通常情况下一个segment是2s,一般以2s为间隔请求一次m3u8,但是有时候不知道是客户端还是服务端的问题,总之是发生了网络震荡,那么请求m3u8的时间就会变长,可能变为十几秒才返回结果,那么这时就发生了丢块的现象,因为一个m3u8保存的时间并没有那么多。在minyami中,并没有设置超时这一选项,而streamlink处理的过程中,如果将流的超时设置的比较短,那么超时时程序将自动退出,我发过issue询问这个问题,问是否可以增加一个超时后自动重连的机制,可惜被开发团队拒绝了。
这个问题倒是不难解决,主要就是m3u8的timeout机制以及超时重连机制,加上去就行了。
- segment分片的跳变
这个分两种情况,一是和问题1同时出现,首先m3u8长时间无法获取,导致触发timeout后重连,这个时候花费了过多时间导致segment已经过去了;二是在showroom这边遇到的特殊情况,在请求m3u8时,有时候会出现请求下来的m3u8一直是同一个内容,反复重复,好像流停止了一样,然后一段时间后突然又能请求到后续的segment了,但是这时候已经过去了较多;minyami和streamlink在这方面的处理是一致的,它们因为考虑到其它的网站兼容性,并没有完全信任media sequence,所以遇到这种跳变的情况下会直接二进制合并到之前的文件结尾,这样就会导致合并出来的文件中间的timestamp错乱,表现为,当你用播放器播放时,到了出错的位置,你会发现无法拖动进度条。这个时候用一些remux之类的方法有时候可以解决这些问题。
这个问题没有什么好的解决方法,唯一的方法就是在断点处分片,当视频出现segment的断点时,将其前后直接分割为多个文件,这样的话就能避免强行二进制合并导致的timestamp错乱问题,之后就可以自己手动合并多个断开的视频文件。
因为整个用C#重写了一次,目前的.net core对于跨平台也算友好,内存的控制尚可,多线程的性能也过得去;毕竟在这种网络环境下,语言的延迟性还是没那么重要的。
Be First to Comment