WWDC Quick Look 💓 By SwiftGGTeam
Discover rolling clips with ReplayKit

Discover rolling clips with ReplayKit

观看原视频

Highlight

ReplayKit 在 iOS 15 和 macOS Monterey 上新增了 Clips Recording 能力:应用启动后自动维护一个 15 秒的滚动音视频缓冲区,玩家在精彩时刻触发导出即可保存过去最多 15 秒的画面,无需提前开始录制。

核心内容

玩家打出五杀、解锁隐藏关卡、刷新速通记录——这些瞬间往往来得突然。按以往的做法,玩家必须全程录制游戏画面,事后再从长视频里剪辑。这占用大量存储空间,剪辑过程也繁琐。

ReplayKit 的 Clips Recording 改变了这个流程。

应用启动后调用 startClipBuffering,ReplayKit 开始在内存中维护一个滚动缓冲区,持续保存最近 15 秒的屏幕画面和应用音频。缓冲区满后,旧数据自动被新数据覆盖。当精彩时刻发生时,应用调用 exportClip 即可将过去最多 15 秒的内容导出为独立视频文件。

开发者可以设计多种触发方式:在界面上添加导出按钮让玩家手动控制,或者由游戏逻辑自动触发——比如击败 Boss、达成连击、刷新记录时自动保存片段。

导出的片段保存在应用指定的 URL,开发者可以自由构建后续体验:展示本局高光集锦、添加自定义水印和滤镜、或者直接保存到相册。

游戏手柄框架(Game Controller)也内置了对 Clips Recording 的支持。玩家按下手柄上的录制键即可导出片段,这些片段会直接保存到相册或桌面。

详细内容

启动和停止滚动缓冲区

05:19)Clips Recording 的核心是三个 API:startClipBufferingstopClipBufferingexportClip

启动缓冲区的代码:

func startClipBuffering() {
    RPScreenRecorder.shared().startClipBuffering { error in
        if error != nil {
            print("Error attempting to start Clip Buffering")
            self.setClipState(active: false)
        } else {
            self.setClipState(active: true)
            self.setupCameraView()
        }
    }
}

关键点:

  • RPScreenRecorder.shared() 获取单例实例,这是 ReplayKit 所有功能的入口
  • startClipBuffering 启动滚动缓冲,无需指定时长,系统固定维护 15 秒
  • 回调中处理错误并更新 UI 状态,让用户知道录制已激活
  • setupCameraView() 可以设置前置摄像头画面叠加,用于录制玩家反应

停止缓冲区的代码:

func stopClipBuffering() {
    RPScreenRecorder.shared().stopClipBuffering { error in
        if error != nil {
            print("Error attempting to stop clip buffering")
        }
        self.setClipState(active: false)
        self.tearDownCameraView()
    }
}

关键点:

  • stopClipBuffering 释放滚动缓冲区资源
  • 停止后可以切换到 ReplayKit 的其他功能,比如直播(in-app broadcast)
  • 记得清理摄像头预览视图

导出视频片段

06:13)导出片段可以由用户手动触发:

@IBAction func exportClipButtonTapped(_ sender: Any) {
    if self.isActive && self.getClipButton.isEnabled {
        exportClip()
    }
}

实际导出逻辑:

func exportClip() {
    let clipURL = getAppTempDirectory()
    let interval = TimeInterval(5)

    print("Generating clip at URL: \(clipURL)")
    RPScreenRecorder.shared().exportClip(to: clipURL, duration: interval) { error in
        if error != nil {
            print("Error attempting to export clip")
        } else {
            self.saveToPhotos(tempURL: clipURL)
        }
    }
}

关键点:

  • exportClip(to:duration:) 的两个参数:目标文件 URL 和片段时长(最大 15 秒)
  • 示例中导出 5 秒片段,实际可以根据场景调整
  • 导出成功后片段保存在指定 URL,开发者可以保存到相册、上传到服务器、或进行后期处理
  • 导出过程由 ReplayKit 处理编码和封装,开发者无需关心视频格式细节

与游戏手柄集成

07:26)Game Controller 框架内置了 Clips Recording 支持。玩家按下手柄录制键时,系统会自动导出片段并保存到相册或桌面。

如果开发者想构建自己的片段体验(比如在游戏内展示高光集锦),需要同时集成 ReplayKit Clips API 和游戏手柄框架。建议:

  • 使用 KVO 监听 RPScreenRecorderavailablerecording 属性
  • 遵循 RPScreenRecorderDelegate 协议,及时响应录制状态变化

核心启发

  • 自动高光捕捉:在赛车游戏到达终点线、格斗游戏打出连击、解谜游戏发现隐藏彩蛋时,用游戏事件自动触发 exportClip,给玩家生成”刚刚发生了什么”的即时回放。入口 API:RPScreenRecorder.shared().exportClip(to:duration:)

  • 本局集锦生成:在关卡结束时收集本局所有自动导出的片段,用 AVFoundation 拼接成集锦视频,配上背景音乐和结算数据(击杀数、用时等)作为分享素材。片段文件已保存在本地 URL,直接读取即可。

  • 玩家反应录制:启动缓冲区时同步开启前置摄像头(setupCameraView),导出的片段会同时包含屏幕画面和画中画的玩家表情。适合恐怖游戏 jump scare 瞬间、或者 AR 游戏里的真实互动反应。

  • 直播精彩瞬间存档:在直播过程中,当弹幕热度达到峰值或主播手动标记时,自动导出片段保存到本地。这些片段后续可以剪辑成短视频发布到其他平台,实现”直播+短视频”的内容复用。

关联 Session

评论

GitHub Issues · utterances