V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
happydoze
V2EX  ›  Swift

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

  •  1
     
  •   happydoze · 93 天前 · 978 次点击
    这是一个创建于 93 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下:

    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!")
                        }
                    }
                }
            }
            
        }
        
    }
    
    
    1 条回复
    happydoze
        1
    happydoze  
    OP
       91 天前
    那自己回答吧,不知道为什么,只有异步才成功。不知道是不是线程的问题。有知道答案的人分析一下么
    贴一下成功的代码

    ```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)
    }
    }
    }
    }

    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2740 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:21 · PVG 17:21 · LAX 01:21 · JFK 04:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.