订阅 RxSwift Observable<VideoCaptureOutput> 不触发 onNext()

Subscription to RxSwift Observable<VideoCaptureOutput> not triggering onNext()

我想使用 RxSwift 处理从 iPhone 相机捕获的视频帧。我正在使用一个社区维护的项目,https://github.com/RxSwiftCommunity/RxAVFoundation,它连接了 AVFoundation(用于捕获相机输出)和 RxSwift。

我正在尝试在新视频帧写入输出缓冲区时只打印一个虚拟日志语句。以下是我的ViewController。我配置 AVCaptureSession,设置 Rx 链,然后启动会话。但是,永远不会触发 .next 情况下的打印语句。我联系了项目所有者。下面的代码是否正确?这是来自社区维护项目的 AVCaptureSession class 的 Reactive 扩展:https://github.com/RxSwiftCommunity/RxAVFoundation/blob/master/RxAVFoundation/AVCaptureSession%2BRx.swift

//  ViewController.swift
import UIKit
import AVFoundation
import RxSwift

class ViewController: UIViewController {

    // capture session
    private let session = AVCaptureSession()
    private var videoDevice: AVCaptureDevice!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
    
        session
            .rx
            .configure(captureDevice: videoDevice)
    
        let disposeBag = DisposeBag()
        
        let videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) : NSNumber(value: kCVPixelFormatType_32BGRA)] as [String : Any]
        session
            .rx
            .videoCaptureOutput(settings: videoSettings)
            .observeOn(MainScheduler.instance)
            .subscribe { [unowned self] (event) in
                switch event {
                    case .next(let captureOutput):
                        print("got a frame")
                    case .error(let error):
                        print("error: %@", "\(error)")
                    case .completed:
                        break // never happens
                }
            }
            .disposed(by: disposeBag)
        session
            .rx
            .startRunning()
    }
}

因为您已经在 viewDidLoad 中本地定义了 DisposeBag,一旦 viewDidLoad 完成,所有添加到包中的订阅都会被处理掉。

将您的 DisposeBag 声明为要修复的 ViewController 的实例变量:

...
// capture session
private let session = AVCaptureSession()
private var videoDevice: AVCaptureDevice!

private let disposeBag = DisposeBag()

override func viewDidLoad() {
    super.viewDidLoad()
    ...

使用 .debug() 是捕获此类事件的好方法,因为它会打印所有事件,包括处置,例如:

session
    .rx
    .videoCaptureOutput(settings: videoSettings)
    .observeOn(MainScheduler.instance)
    .debug("Video Capture Output Observable:")
    .subscribe { [unowned self] (event) in
        switch event {
            case .next(let captureOutput):
                print("got a frame")
            case .error(let error):
                print("error: %@", "\(error)")
            case .completed:
                break // never happens
        }
    }
    .disposed(by: disposeBag)