录播的原理及其方法论
  • 直接录屏

如果不讨论其他形式的直播,对于普通的音视频媒介的直播,录屏就是最直接的也是最后的录制手段。

本质上,直播的音视频就是一串以时间排列的信息序列。类似模拟漏洞(Analog hole),无论直播的平台是什么架构,都需要转换成音视频显示在电脑或手机上,于是就都可以通过录屏来对音视频序列进行记录。录屏的优势也在于其通用性,只要一个OBS就可以应对所有的直播站点。

录屏的缺点也很明显,对电脑的性能要求高、画质差、有水印、容易受到干扰等。所以除非没有其他的录播手段,并不建议使用录屏的方式录制直播。不过相应的,如果要录制直播间特效等素材,录屏基本上是唯一的选择。

录屏理论上可以通过Selenium + obs-websocket实现自动化录制。

  • 浏览器抓包

抓包作为一种过渡的手段,非常适合初见一个直播平台的时候使用。抓包可以在缺少时间研究陌生的直播站点时,尽可能完整地保存直播的音视频的信息,也可以为后续利用专门软件提供数据支持。

直播的音视频是通过网络进行推流的,所以只要保存下浏览器接收到的所有数据,那么直播的音视频的信息也就都保存下来了。这样就可以在之后时间充裕的时候,从记录下的网络数据中提取音视频的数据流。

抓包的优势在于可以直接抓取音视频的码流,避免二次编码带来的损失,同时可以让人在直播结束后再从容地对直播站点和直播数据进行分析处理。所有需要知道的都保存下来了,那么也就不用在直播的时候手忙脚乱了。

抓包的缺点也很明显,以Fiddler抓包为例,一是需要专业知识来分析和处理抓取的数据包,二是抓包获取的数据可能是加密的,这就需要再专门分析如何解密,增大工作量。另外Fiddler无法抓取WebRTC的UDP数据包,并且对于B站这种使用HTTP-FLV长连接协议的站点,Fiddler难以完整的抓取和存储几个GB大小的请求。    

  • 从sourceBuffer抓取视频数据流(设想)

直播站点获取并解析完音视频数据后,还需要将这些数据放入页面上的播放器,让播放器渲染声音和图像,这些播放器一般都是基于浏览器自带的HTMLMediaElement实现的,所以只要在数据被送入播放器的过程将其复制下来,理论上就可以实现对直播的录制。

  • 使用专门的录播软件进行录制

当有录播软件能用的时候,就优先使用录播软件。

大部分的直播站点都可以使用现成的软件进行录制。这些软件会模拟浏览器发出的请求,直接获取直播推流的地址,然后下载音视频的数据流写入到硬盘上。这一过程基本和下载文件的负荷差不多,所以即便是最低配的云主机或者是十多年前的电脑,都可以轻松地用录播软件来录制直播。

用软件录制,优点是占用少并且稳定可靠,方便实现自动录制,缺点是只支持软件支持的站点。

对于主要的直播网站,可能会有多个软件支持。我个人的建议是,对B站这样有专门针对单个站点的软件时(不包括很久没更新的),就使用B站录播姬这样的专门的软件,而非yt-dlp/streamlink这样的通用软件。当没有专门的软件,而yt-dlp和streamlink均支持时,使用streamlink而非yt-dlp。


各直播站点的录播实践和经验
  • B站/Bilibili直播/哔哩哔哩直播

B站的直播有很多录播软件,但我个人只推荐使用B站录播姬进行主力录制。如果录制用的网络环境较差,录制经常断开导致大量碎片文件的情况下,也可以尝试blrec的HLS(fMp4)模式(不稳定的网络下FLV也只能录到二压画质)。

从23年10月25日开始,无cookies的情况下,无法获取原画画质(除非获取时直播间仅原画画质)。对于网络不稳定的FLV录制环境和所有的HLS录制环境,添加cookies几乎成为一个必选项。

为了正常录制弹幕,需添加cookies并确保cookies有效。旧版本需关闭“弹幕传主播uid”选项(新版本中已移除)。需打开“弹幕传主播uid”选项,并在开启选项后重启录播姬

但就目前而言,录播姬仍未正式支持HLS,而B站有部分直播间已经测试过仅提供HLS推流(同时也导致海外IP无法观看/仅国内可以观看),所以对于重要的直播间,可以用blrec等作为备份选项,同时进行录制(但HLS基本必然录制的是画质更差的二压画质)。

如果只是自己录着玩玩,那么用家庭带宽,随便选一个电脑、甚至是NAS运行录播姬程序就可以了。设置里“录制模式”选择“标准模式”,然后房间列表添加自己想录制的房间号,保持这台电脑一直联网开机就可以了。剩下的就是可以根据个人偏好,打开“弹幕录制”的“保存弹幕”、“保存弹幕原始数据”,以及保存封面等。

对于仅HLS(fMp4)流的直播间(即海外无法观看的直播间),录播姬的录制图标会出现反复闪烁,并可以在日志中看到“no supported stream url, qn: 10000”(国内)或“System Exception: playurl is null”(海外),即表明当前直播间无法用2.xx版本的录播姬录制。(直播间视频统计中显示Hls7Player只说明存在HLS流,海外无法观看才为无FLV流/仅HLS流)

对于仅HLS的直播间,国内只需要改用支持HLS录制的软件(如blrec)即可。海外则还需要添加反代API,因为海外IP无法获取HLS的直播流链接。

添加cookies的方法可以参考另一篇专栏,这里也保留之前的简单叙述。

注意除非是录制大航海直播/舰限直播,应只使用小号的cookies。录制舰限直播可以另外开一个录播姬(多开)专门只添加在舰/舰限主播的直播间。

要给录播姬添加cookies,以B站录播姬为例,首先需要打开软件的高级设置。桌面版是用鼠标右击(不是左键)双击两次设置按钮,即可显示高级设置。在高级设置中可以找到cookies一项。

接下来是获取cookie string。可以参考如下的带图片的教程:

在一个已经登录的浏览器打开一个B站页面,按F12。在弹出的开发者工具(DevTools)窗口最上方切换到网络(Network)标签,然后刷新网页。接下来列表中会出现很多内容。

在上面的过滤器(Filter)中输入api,然后选中一个对应域名(Domain)列是api.bilibili.com或live.api.bilibili.com的任意一项,在弹出的页面中向下滚动,找到Request Headers的粗体字。在Request Headers里找到cookie: xxx=xxx; xxx=xxx这样的一行,然后把xxx=xxx; xxx=xxx复制出来,粘贴进录播姬的cookies配置中,然后点一下别处,让cookies配置中的光标消失。

粘贴了正确的cookies后,点一下边上的Test按钮。如果弹出了你的B站昵称,那么cookies就配置成功了。在配置cookies后最好定期检查和更换,以确保cookies不会过期。

那么面向小白的教程到此为止,接下来讨论点复杂的。

首先B站的直播相对于其他平台来说是一个经常会有变动的平台,所以这里的经验随时都可能过时。其次以下的内容展开的角度是投入较多的资源(服务器、时间)来录制1-2个直播间,以保证录制的完整,而不是节约资源来录制尽可能多的直播间,来追求录制的范围。

对于“录播模式”,我建议设置为“原始数据模式”。原因有两个,一是原始数据模式更不容易出错。录播只有一次机会,所以应当尽量降低一切风险因素。同时B站已经使用自定义的FLV标准来实现H265推流,目前版本的录播姬的标准模式不能录制H265推流,使用标准模式会导致无法录制。第二个原因使用原始数据模式可以在录制结束后再决定如何进行修复,例如是否自动在跳变处分段,也可以避免强行修复现有修复规则无法修复的新错误。

对不同服务器录制的录播文件,我会对各帧(flv tag)的原始数据的哈希值进行比对,来选择没有缺失的一个进行保存。另外弹幕的录制有时会出现缺失,其原因一般是和录播的节点和弹幕服务器的链接短暂的断开了,导致断开期间的弹幕会丢失

服务器的选择方面,基本上可以分为国内服务器(使用B站视频云的CDN,cn-xxxx-xx-00-00格式域名,或称省级服务器)和国外服务器(使用Akamai的CDN更正:d1--ov-gotcha一般为05网宿/07百度的CDN)两类。在21-22年左右,基本上使用国内服务器录到的都是完整连贯的录播,而国外的会不时出现数秒的缺失或断开。但从23年年初左右开始,国内的服务器录制会经常出现断开和缺失,而国外服务器则一般完整。另外加拿大的网很烂,弹幕服务器经常会断,建议尽量用美国的。关于CDN的信息和选择可参照录播姬的在线文档的《生放送 CDN 信息》、录播姬闲聊群的群文档的《【录播】反代API》(均可直接浏览)。

B站从22年3月开始对直播推流开启了二压,只要推流码率达到5Mbps左右,并且是有一定的观看人数的主播,那么大概开播一分钟内,获取到的“原画”就会变成二压的伪原画,特征[2023年9月更新]是视频码率一般变低(少数情况码率反而变高),且分辨率帧率固定为1080p60fps(对低于1080p60fps的推流会进行缩放、添加重复视频帧提升参数)。[2023年11月更新]音频码率不再有特征。

二压的分辨率/帧率可能比推流更高,例如720p30fps的推流可能二压后变为1080p60fps。这时可以通过比较第k、k+1帧的内容是否一致辨别虚高帧率是否为二压副作用导致。

浏览器可以用如下油猴脚本检查当前推流是否为二压:

HLS录制需要反复请求m3u8链接来获取最新分片,而m3u8链接有效期也为1小时,必须反复获取。所以在触发二压条件的直播间,新获取的m3u8只有二压画质,导致HLS几乎必然只能录制二压原画。相比之下,HTTP-FLV使用一个长连接来获取直播推流。只要连接没有因为网络波动断开,在直播开始时获取的真原画(推流画质)的链接就可以一直使用。

为了尽可能地录制原画,在录制时应当优先选择HTTP-FLV模式进行录制,并且选择稳定的网络(23年的现状下,建议选用国外的服务器)。目前B站录播姬对FLV的录制提供了最好的支持,这也是我仅推荐B站录播姬的原因。虽然理论上B站录播姬会自动在开播时启动录制、获取真原画链接,但因为推流延迟、网络波动等原因,录播姬有时会反复获取链接,导致录制使用的是后获取的二压链接。为了尽可能地确保录制到推流原画,在使用录播姬时,需要添加用户脚本(需要开启高级设置),来优先使用推流画质的真原画链接,避免误用二压画质的链接

(23年11月更新)旧的复用原画链接的脚本目前因脚本系统无法使用cookies,无论是否在录播姬中设置了cookies,都会在没有原画链接时变成高清画质。我这里提供一个修改版的用户脚本,在没有原画链接时恢复由录播姬请求二压原画,可供参考使用。

总结一下,为了录制原画,需要:1. 使用FLV模式录制(推荐使用B站录播姬),2. 在稳定的网络进行录制(23年上半年是优先国外的机房),3. 添加用户脚本降低录播姬使用二压链接概率

B站直播间基本上不需要登录即可观看和录制。但是B站存在类似清流源、舰限、收费演唱会等项目,而这些项目需要直播间密码或登录才能观看。无论是清流源(输入密码后新请求的cookies中会附带6位密码)还是用户登录,都是通过cookies来实现校验的。目前主要的录播软件均支持添加cookies。理论上从输入密码或登录后的浏览器复制cookies,输入到录播软件中,即可录制各种带访问限制的直播流。


  • YouTube/油管/Y台

YouTube作为HLS推流的典型,可以直接使用streamlink进行录播,也可以用youtube-dl的后继者yt-dlp进行录播和下载。

YouTube相较于B站的一个特点是,在直播结束后,直播的链接会直接转变为录播/直播回放,可以立刻观看和下载录播。但是需要注意的是,直播结束后会有一个数小时的转码的时期,最大的特征是在此期间,录播的右侧没有聊天回放。在转码期使用yt-dlp可以下载到和直播时同等的画质的音视频流,并且不会下载到VP9/opus的二次二压的码流,但是yt-dlp只能最多下载从结尾往前2小时的内容。

所以如果在直播结束后用yt-dlp下载录播,并且这一场直播超过2小时,请务必等待右侧的聊天回放栏出现、让二压完成后再进行下载。虽然画质会变差,但是这样下载的才是完整录播。如果直播本身不超过2小时则没这个问题。

yt-dlp下载录播可以参考如下的参数

如果使用socks等代理可以根据服务器的地址和端口再加上代理参数

YouTube频道直播的录制可以参考lovezzzxxx/liverecord的脚本,通过简单的bash脚本来检测开播/直播预约,并获取直播场的链接。需要注意的是,Google对爬虫有很严格的限制,尤其是对YouTube的API的请求。所以进行录制时,要避免同一个IP地址对大量直播间同时进行监测和录制。其次尽量请求HTML页面而非API接口,后者比前者更容易触发访问限制。

YouTube可以使用streamlink进行录制,但streamlink不能保存实时聊天(弹幕)。yt-dlp可以录制聊天,但yt-dlp录制聊天后就无法同时录制直播(yt-dlp在获取完所有聊天后才获取视频,而这时直播已经结束了)。所以可以分别开启一个streamlink和yt-dlp,streamlink用于录制直播视频,而yt-dlp则专门用于录制聊天。yt-dlp录制聊天的命令如下:

  • YouTube的会员限定(会限)的直播/录播

会限的直播录制和录播下载基本和普通的场次是一样的,区别是会限需要额外的登录信息,具体到YouTube就是登陆后的浏览器cookies。

向yt-dlp添加cookies的方法相对简单,可以直接让yt-dlp自己尝试从读C盘,从本地浏览器获取,或者提供cookies文件。

以下载录播为例,提供--cookies-from-browser后,即可让yt-dlp使用本地浏览器的cookies。用Firefox登录YouTube后,打开Windows的文件资源管理器,单击地址栏,输入“%APPDATA%\Mozilla\Firefox\Profiles”再回车,即可跳转到存放了Firefox的历史记录、cookies等的文件夹。找到xxxx.default-release,把这个名称复制下来,这个就是要指定yt-dlp使用的对象。然后就可以用yt-dlp下载会限录播了。

但单独的cookies文件更适合远程服务器使用。首先浏览器安装EditThisCookie插件,然后登录YouTube。打开录播页面确认登录的账号可以观看后,打开EditThisCookie,点击最上面朝右箭头的图标(导出cookies),将Netscape格式的cookies导出至剪贴板。打开记事本,粘贴内容,然后保存为youtube-cookies.txt文件(如果保存为其他的文件名,命令中的对应文件名则进行相应调整)。

导出完cookies后,添加--cookies youtube-cookies.txt,即可用yt-dlp下载会限录播。

streamlink的cookies是使用key=value的格式进行配置,所以需要手动再进行一次转换,样例可以参考lovezzzxxx/liverecord的README。这里提供一个我写的Python脚本实现以供参考

将导出的cookies保存为youtube-config.txt之后,理论上添加--config youtube-config.txt之后,就可以用streamlink录制直播了,但我没有实际遇到录制会限直播的情况,所以具体建议参照lovezzzxxx/liverecord中对streamlink的cookies的处理。


  • Twitch/老鼠台

Twitch是基于HLS的直播平台,可以直接使用streamlink进行录制,方式和YouTube类似。

lovezzzxxx/liverecord中采取反复启动streamlink的方式检测Twitch开播,对CPU负荷较高。streamlink支持自动重试获取直播流,而不用反复重新启动,代价是一直开着streamlink会比较消耗内存。如果需要大量录制Twitch则需要权衡内存/CPU开销,或者根据streamlink中的plugins源代码设计bash脚本。streamlink自动重试的脚本如下:

--retry-streams参数指定了重试的间隔秒数,而--retry-max则设定了重试次数。不建议把--retry-max设置的过大,以免脚本有bug的情况下,streamlink一直运行不自动结束。注意Twitch允许主播直接转播别人的直播,加入--twitch-disable-hosting参数可以避免因转播而录制到其他频道的直播。--progress=no会关闭进度显示,节约资源。

Twitch的聊天是基于IRC实现的,可以通过第三方的Twitch聊天客户端来记录聊天历史。Chatty是一个基于Java的第三方Twitch IRC客户端,可以将聊天记录保存在log文件中,同时也会记录开播的时间、标题、同接和礼物等。可以在相应的直播间录制完成后从Chatty的log文件提取直播期间的聊天记录等信息。


  • TwitCasting/TC

TwitCasting是一个日本的直播站点,可以直接用streamlink录制。录制的命令可以参考上文Twitch的录制命令。注意TwitCasting使用websocket来进行推流,loglevel不宜设置过高,否则会包含大量的websocket相关调试信息。

TwitCasting的特点是支持带密码(口令)的直播,要进入直播间必须要输入正确的密码。因而TwitCasting也经常被用于Fanbox的会员限定直播。streamlink也提供了对带密码的直播的支持,添加--twitcasting-password PASSWORD即可让streamlink自动尝试该密码。考虑到会员限定直播的密码会变,要录制会员限定直播需要记得提前改好脚本/密码文件。

  • 推特空间/Twitter Space

Twitter Space是基于HLS的语音直播平台。特点是Twitter有一套比较复杂的API,所以难以通过简单的脚本来获取录制链接。针对space,有一个名为twspace-dl的开源软件可以录制space的直播和下载录播:

space会对所有的直播进行存档,以供Twitter进行审计,所以在Twitter开放space的录播功能前,就已经有人成功地下载过录播了。事实上目前的space直播无论是否开启了录播,都可以在直播结束后大致几个月的时间内下载录播,但前提是保存了master url或者dynamic url,也就是能获取直播相关数据的url。

twspace-dl自带的监控和录制脚本允许添加--write-url参数来保存master url。而dynamic url则可以通过浏览器抓包获取。也就是说,即便是中场进入一个space,只要在进入时用Fiddler抓包保存到了dynamic url,无论这场直播是否选择开放录播,都可以在直播结束后使用dynamic url下载到完整的录播。但在最近的AI热潮中,Twitter对开发者API进行了巨大的阉割,而twspace-dl所依赖的浏览器API也有随时被修改的风险。所以为了避免未来的API变动导致自动录制失效,建议尽可能多地使用浏览器打开想要录制的space进行抓包作为备份,来避免突然的变动导致的自动录播失效。

twspace-dl自动录制可以参考以下脚本(注意对开放录播的space,twspace-dl会反复下载):

  • FC2 Live

FC2是一个基于HLS的站点,可以直接使用yt-dlp下载录播和对直播进行录制,也可以用streamlink进行录制。需要注意的是,FC2如果没有登录的时候,浏览器语言(locale)如果是中文会跳转到中文特供域名。

FC2自带防多开机制。没有登录的情况下,一个直播间,同一个IP地址只能同时打开一个。新打开相同的页面会自动导致旧页面的直播间断连。所以没有登录的情况下,同一台电脑(IP)不能同时进行录播和浏览器观看。登录后的直播间防多开机制应该是根据账号而非IP计数。

注意用yt-dlp下载过往录播的时候,需要手动修改URL格式,来确保yt-dlp正常匹配识别

另外FC2直播刚开始推流的时候,是先有低画质,再出高画质,这一点刚好和B站是反过来的。所以在开始录制的时间点上需要进行一些取舍:是追求完整,还是追求高画质

参考的bash录制脚本:

  • 8181Live

8181Live是一个基于HLS的新站点,比较简单,可以用streamlink进行录制。需要注意的是这个站点必须登录才能进入直播间页面(并获取推流链接),所以必须通过--config提供cookies才能进行录制。参考bash录制脚本:

  • ZAIKO

ZAIKO是一个收费的直播平台,特点是直播需要买票,但是会在直播结束后的几天的窗口期内提供录播。一些日V的收费演唱会就是在ZAIKO平台上进行的。

因为ZAIKO基本都有录播,所以只需要直播结束后下载录播即可,也可以尝试用yt-dlp直接在直播时进行录制。ZAIKO的录播是AES-128加密的m3u8,所以如果采用抓包,还需要额外对抓取的ts分片进行AES解密。事实上密钥的链接就在m3u8文件内(EXT-X-KEY),属于标准的m3u8行为,所以直接用ffmpeg或yt-dlp下载即可。具体yt-dlp命令可以参照上面YouTube会限的部分。

  • Fantia

Fantia是一个类似Fanbox和Patreon的网站,但主要的方向是内容贩售,以对创作者利益的保护来吸引创作者入驻,为创作者进行内容贩售提供一个完整而相对严苛的付费机制。

Fanbox这种只提供简单的博客的站点,限定直播一般会通过在Fanbox内贴出密码,再在TwitCasting用密码直播来实现限制。而Fantia则自带一套直播系统,并且需要用户购买直播门票,再用Fantia的账户进行观看。

Fantia的直播系统用的是声网(Agora)的WebRTC方案。WebRTC使用UDP而非HTTP进行通讯,无法用Fiddler等软件进行抓取。同时WebRTC是点对点的连接,所以Fantia的直播也无法一个账号多开。对于Fantia这样的WebRTC的直播站点最容易的方案似乎还是进行录屏。