Swiftpack.co - frolovilya/SwiftUIViewRecorder as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by frolovilya.
frolovilya/SwiftUIViewRecorder 0.1.0
Efficiently record any SwiftUI View as image or video
⭐️ 14
🕓 38 weeks ago
iOS
.package(url: "https://github.com/frolovilya/SwiftUIViewRecorder.git", from: "0.1.0")

SwiftUIViewRecorder

Package to efficiently record any SwiftUI View as image or video.

Requirements

  • iOS 13.0
  • Swift 5.2

Installation

Use Xcode's built-in Swift Package Manager:

Usage

Record View animation as a .mov QuickTime video

func recordVideo(duration: Double? = nil,
                 framesPerSecond: Double = 24,
                 useSnapshots: Bool = false) throws -> ViewRecordingSession<URL>

Note that each SwiftUI View is a struct, thus it's copied on every assignment. Video capturing happens off-screen on a view's copy and intended for animation to video conversion rather than live screen recording.

Recording performance is much better when setting useSnapshots to true. In this case view frame capturing and image rendering phases are separated, but the feature is only available on a simulator due to security limitations. Use snapshotting when you need to record high-FPS animation on a simulator to render it as a video.

You could use provided ViewRecordingSessionViewModel or write your own recording session view model to handle recording progress.

import SwiftUI
import SwiftUIViewRecorder

struct MyViewWithAnimation: View {
    
    // observe changes using built-in recording view model
    @ObservedObject var recordingViewModel: ViewRecordingSessionViewModel<URL>
    
    private var viewToRecord: some View {
        // some view with animation which we'd like to record as a video
    }
    
    var body: some View {
        ZStack {
            if (recordingViewModel.asset != nil) {
                Text("Video URL \(recordingViewModel.asset!)")
            } else {
                Text("Recording video...")
            }
        }
        .onAppear {
            recordingViewModel.handleRecording(session: try! viewToRecord.recordVideo())
        }
    }
    
}

Snapshot View as UIImage

func asImage() -> Future<UIImage, Never>

Simply call asImage() on any View to capture it's current state as an image. Since image is returned as a Future value, view model must be used to handle the result. You could use provided ViewImageCapturingViewModel or write your own.

import SwiftUI
import SwiftUIViewRecorder

struct ContentView: View {

    // observe image generation using built-in recording view model
    @ObservedObject var imageCapturingViewModel: ViewImageCapturingViewModel

    var viewToImage: some View {
        Circle()
            .fill(Color.yellow)
            .frame(width: 50, height: 50)
            .asImage()
    }
    
    var body: some View {
        ZStack {
            if (imageCapturingViewModel.image != nil) {
                Image(uiImage: imageCapturingViewModel.image!)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 200, height: 200)
            }
        }
        .onAppear {
            imageCapturingViewModel.captureImage(view: viewToImage)
        }
    }

}

Record view with a custom frames renderer

It's possible to impement and use your own FramesRenderer to convert array of UIImage frames to some asset.

First, implement FramesRenderer protocol:

class CustomRenderer: FramesRenderer {
    func render(frames: [UIImage], framesPerSecond: Double) -> Future<CustomAsset?, Error> {
        // process frames to a CustomAsset
    }
}

Second, init ViewRecordingSession with your custom renderer:

extension SwiftUI.View {
    public func toCustomAsset(duration: Double? = nil,
                              framesPerSecond: Double = 24) throws -> ViewRecordingSession<CustomAsset> {
        try ViewRecordingSession(view: self,
                                 framesRenderer: CustomRenderer(),
                                 duration: duration,
                                 framesPerSecond: framesPerSecond)
    }
}

GitHub

link
Stars: 14
Last commit: 2 weeks ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

0.1.0
38 weeks ago

Initial release.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics