【3/7】记录RKE开发过程

先放上成品:esterTion/ReplayKitEverywhere BigBoss


这次搞的插件开始的时候算是很久之前了

最早的时候,在github里面找了一个实现了开始/停止的类,编译注入,然后用cycript调用。结果测试了一下质量过糟,就暂时放置了

然后就是放假后了,那一阵还在学校,因为实在是需要一个随时随地的录屏功能,所以把开始停止合并成一个函数,然后activator写了一个cycript注入调用的脚本,就这样凑活使用了

回家之后配好了theos环境,然后正式开始从一个附加类升级为hook型插件。写好了activator整合之后,就提交发布了1.0。但是因为跨进程通信抄了BigShot的objcipc,只兼容ios9。

在发布之前,我本来是研究过能不能用其他方法,但次次崩溃,后来发现原因是quicktime挂载的开发者工具disk导致的问题。次日重启手机后notify.h库正常工作了,于是将objcipc改为了notify,兼容了ios10

在找人测试的时候又一次意识到,需要一个开始录制的提示,不然过于不友好。苦恼地翻了半天flipswitch源码也不知道他用的什么方法,然后在devwiki上翻阅springboard相关类的时候看到SBBulletinBannerController,找功能全靠运气(上次找mltd的aes也是运气看到那串string,包括最早b站flash的secret也是dump内存硬翻到,真是没谁了)

1.1版本花了大概三天才更新,其中主要是等别人帮忙测试,基本上是一天联系上一次。本想让pass用他的6p测试,但他机子不知道什么毛病不能开启。

1.1提交次日,我开始着手研究能不能修改码率。查看进程的时候发现开始录制后会蹦出一个replayd,文件拖到电脑上扔进ida,一百多k的小服务代码量也不是很大,而且相比il2cpp的游戏来讲,这个daemon可全是objc啊!分析起来不要太爽。

一通观察外加文档搜索,replayd用的AVFoundation的AVAssetWriterInput进行流编码,而配置都是传给initWithMediaType:outputSettings:方法。这个相当简单了,单开一个dylib注入replayd,hook调这个方法。首先在里面观察他的参数。期间出于有趣把filter改成了com.apple.avfoundation观察所有编码程序的参数,虽然最后只观察了微信。微信小视频编码设置的是1.2m视频+64k音频。

简单尝试了一下修改参数可行,就暂时没有管这里了,有一个更关键的地方需要解决。

之前也提到过,rk音频出奇的烂,不仅仅是码率,而且有一点是他会把左声道塞到输出立体声里,然后造成一些音乐变得极其难听。在ida里找了半天,最终发现replayd从AudioToolbox提取app的声音。而对比输入参数,我发现苹果程序员不知道出于什么理由,设置提取音频的声道数为1……

AudioToolbox的AudioQueueNewInput函数是c函数而不是objc方法,不过ms注入也提供了c函数的hookf。于是一套简单的参数修改,就成功的修复了录制成品的声道问题。

声道问题得到修复可以说我是心情大好,这个问题我自从试用过rk之后一直纠缠心头,也是我不愿意用rk录视频的原因。谁会愿意用一个只能录制左声道的东西。

然后就是一个比较简单的了,加入一个PreferenceLoader入口。改变码率我计划制作的是一个选单选择输出质量,所以就需要一个新的设置页了。原本我是不计划再写一个单独的bundle的,只用纯plist,目前的功能倒是也实现了,但是rk的录制文件会存在临时文件夹里一直留着,不会主动删除,直到下一次同一程序覆盖(按照包id命名文件)。这方面我计划写一个大小统计+删除功能,所以还是逃不过bundle,这些之后再说。

我原计划的最高档码率是20m,测试的时候我注意到20m会导致设备变卡,当然可能只是因为se硬件开始过时了,但毕竟还是要自用的,于是最高档设置为了15m,相比系统默认的2m(宽高1600以上3m)已经高很多了。我自己在玩了几次15m录制之后选择了4m,对于4寸屏幕而言这个cbr码率也算是差不多了,毕竟是要录来投稿的,破b也会二压。

(制作完之后我意识到这些码率大概都不够ipad使用,那个屏幕可能得需要30m能算是顶配码率?但我手上也没有支持的pad,家里6年前的pad3还停在卡的不行的802上)

到目前为止基本上的开发笔记就这么些,而我现在备忘录上已经又有了一堆todo,包括全局麦克风开关(我从不录麦)、改进notify listener声明之类,以及设置bundle制作。所以,未完待续?


02/13追记

上面那些是到1.2版本的,1.3做完也是有一阵了才来接着写

首先是写了一个全局麦克风开关,像我这种只录屏从不录麦的,直接是全程关闭的

设置bundle稍微搜了一下就看到可以创建子项目,theos这方面足够智能,会自动打包子项目。至于主设置内容依然是plist导入,所以倒也不复杂

有了bundle之后就可以搞一个临时文件大小统计了,原本期望是外面显示总大小,进入一个列表可以单独删除。但是devwiki上的样例并不能使用,搜了几下也没有类似内容,就把这个想法阉割了,转为加了一个全部删除的按钮。在最后完成的时候,又加上了一个ifile打开链接,格式也简单,ifile:/User/Library/ReplayKit

主要想加的加完了,稳定性上就在几个主要的地方加了try catch,插件成功变stable(迫真)

iOS11目前还不清楚怎么搞,有点想法要不要给系统录屏搞一个质量控制。我手头反正也是没有设备,再说吧


03/07 v1.4追记

1.4首先是加了跳过权限提示。从shared_cache里导出了框架后跟着开始录制的函数一路寻找,权限的提示依然是在replayd里发出的。看了函数后发现这个权限提示的选项是一个同步阻塞的通知(CFNotification),这也解答了我为什么alert不会导致bang dream退房间而开始录制会。

是否提示的判断是对比一个记录,而直接根据设置把这个函数选择调用原始或返回true就可以满足需求了。

做完提示跳过后顺手做了动态监听名,自己看起来爽到就是划算(

然后是做了一个自动保存,而为了不被系统相册权限限制,找了下框架调用的保存函数。不过说实在的,共享缓存里的框架在ida里真的难看,到头来也没找到怎么保存的,只是半猜加半搜索看到了PhotoLibraryServices下的PLAssetsSaver类下的saveVideoAtPath。这个方法的回调block参数在ida里看到有一个或三个参数,我用cycript试了一阵,试出来一个参数的block是NSURL,没懂三个参数是怎么个版本,反正就这样随便用了。

因为框架实在是太难看了,有一个10.3.3回报使用一小时后持续failed to start直到重启我也没搞懂具体是什么原因。我所找到的-5803(FailedToStartError)错误只有两处,一个是开始录制的时候available为false,另一个是replayd里取 isApplicationInForegroundWithBundleIdentifier:bundleId 的时候返回了false

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax