ScreenCaptureKit 里面的 SCStreamOutput 没有被顺利触发,是那个步骤错了,求解惑

92 天前
 happydoze

代码如下:

import SwiftUI
import ScreenCaptureKit




struct ContentView: View {
    @State private var showingScreenshotAlert = false
    @State private var screenshotRect = CGRect(x: 100, y: 100, width: 400, height: 300) // 示例区域
    @State private var cc = "截图 1"

    var body: some View {
        VStack {
            Text("点击下方按钮进行截图")
                .padding()

            Button(action: takeScreenshot) {
                Text(cc)
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
        }
        .alert(isPresented: $showingScreenshotAlert) {
            Alert(title: Text("截图完成"), message: Text("截图已保存至桌面"), dismissButton: .default(Text("确定")))
        }
    }

    class MyStreamOutput: NSObject, SCStreamOutput {
        var onCaptureCompletion: (() -> Void)?  // 闭包,用于通知截图完成
        func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) {
            // 每当捕获到新的样本帧时打印消息
            print("Captured a new frame of type")
            onCaptureCompletion?()// 调用闭包通知截图完成
        }
    }
    
    func takeScreenshot() {
        cc = "在截图 1..."
        showingScreenshotAlert = true

        SCShareableContent.getWithCompletionHandler { (content, error) in
            if let error = error {
                print("Error: \(error)")
            } else if let content = content {
                print("Displays: \(content.displays)")
                print("Displays: \(content.displays[0])")
                print("Displays: \(content.displays[0].width)")
                print("Displays: \(content.displays[0].height)")
                print("Windows:\(content.windows[23])")
                print("Windows ID:\(content.windows[23].windowID)")
                print("Windows Count:\(content.windows.count)")

                // MARK: - 创建
                // 创建一个过滤器以捕获整个屏幕
                let filter1 = SCContentFilter(display: content.displays[0], excludingWindows: [])
                let config1 = SCStreamConfiguration()
                let stream1 = SCStream(filter: filter1, configuration: config1, delegate: nil)
                
                
                // 实例化我们的输出处理类
                let streamOutput = MyStreamOutput()
                // 定义截图完成时的动作
                streamOutput.onCaptureCompletion = {
                    DispatchQueue.main.async {
                        cc = "截图完成了"
                        print("-----------")
                    }
                }
                // 添加输出
                do {
                    try stream1.addStreamOutput(streamOutput, type: .screen, sampleHandlerQueue: DispatchQueue.main)
                    print("流输出已成功添加")
                } catch {
                    print("添加流输出时出错: \(error)")
                }
                stream1.startCapture { error in
                    if let error = error {
                        print("Failed to start capture: \(error)")
                    } else {
                        print("Capture started successfully!")
                    }
                }
            }
        }
        
    }
    
}

976 次点击
所在节点    Swift
1 条回复
happydoze
90 天前
那自己回答吧,不知道为什么,只有异步才成功。不知道是不是线程的问题。有知道答案的人分析一下么
贴一下成功的代码

```swift

func signIn4() {
Task {
do {
let content = try await getShareableContent()
guard let display = content.displays.first else { return }
print(display)
let filter = SCContentFilter(display: display, excludingWindows: [])
let config = SCStreamConfiguration()
config.minimumFrameInterval = CMTime(value: 1, timescale: 10)
let stream = SCStream(filter: filter, configuration: config, delegate: nil)
let output = Output()
try stream.addStreamOutput(output, type: .screen, sampleHandlerQueue: nil)
try await stream.startCapture()
try await Task.sleep(nanoseconds: 200_000_000)
try await stream.stopCapture()
} catch {
print("Failed to retrieve capturable content or start stream: \(error.localizedDescription)")
}
}
}

func getShareableContent() async throws -> SCShareableContent {
return try await withCheckedThrowingContinuation { continuation in
SCShareableContent.getWithCompletionHandler { content, error in
if let error = error {
continuation.resume(throwing: error)
} else if let content = content {
continuation.resume(returning: content)
}
}
}
}

```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1074320

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX