我有一个ViewController.swift
和Broadcast Upload app Extension
的示例应用程序。在我的项目中,我创建了两个框架:
MySDK
,是一个快速的框架,用于分析和处理CMSampleBuffer
,以避免广播应用程序扩展占用太多内存。这个SDK有一个单例、一个变量func analyzeSampleBuffer(_ sampleBuffer: CMSampleBuffer)
Broadcaster
,、函数func initialize
和func initialize
,它是一个快速的框架,用于调用MySDK
调用来分析和处理CMSampleBuffer
(是的,听起来像是与MySDK的重复,但我不能这样做,我需要这两个框架)。此SDK具有单例功能,并具有以下功能:func processSampleBuffer(_ sampleBuffer: CMSampleBuffer)
,func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?)
在这个项目中,我添加了一个名为Broadcast Upload App Extension
的BroadcastExtension
。在他的主文件SampleHandler.swift
中,在processSampleBuffer
函数中,我使用我的Broadcaster SDK
提供从应用程序扩展到Broadcaster SDK
的响应性,以及从应用程序扩展名:Broadcaster.shared.processSampleBuffer(sampleBuffer)
接收到的MySDK
到流CMSampleBuffer
的响应能力。最后,MySDK
成功地分析和处理了CMSampleBuffer
,但是我的广播上传应用程序扩展占用了太多的内存,并且在屏幕共享后的X分钟后崩溃(应用程序扩展最大50 max )。如何在应用程序扩展时使用更少的内存?
这是我的档案:
MySDK.swift:
import Foundation
import ReplayKit
@objcMembers public class MySDK {
public static let shared = MySDK()
public var isReady = false
public func initialize() {
// Init SDK
}
public func analyzeSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
// Analyze
}
}
Broadcaster.swift:
import Foundation
import ReplayKit
import MySDK
@objcMembers public class Broadcaster: NSObject, Codable {
public static let shared = Broadcaster()
public func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
MySDK.shared.isReady = true
}
public func processSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
if MySDK.shared.isReady {
MySDK.shared.analyzeSampleBuffer(sampleBuffer)
}
}
}
SampleHandler.swift:
import ReplayKit
import Broadcaster
class SampleHandler: RPBroadcastSampleHandler {
override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
Broadcaster.shared.broadcastStarted(withSetupInfo: setupInfo)
}
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case RPSampleBufferType.video:
// Handle video sample buffer
Broadcaster.shared.processSampleBuffer(sampleBuffer)
break
case RPSampleBufferType.audioApp:
break
case RPSampleBufferType.audioMic:
break
@unknown default:
fatalError("Unknown type of sample buffer")
}
}
}
我希望在应用程序中使用相同的共享实例,但在应用程序扩展中使用。我试图在应用程序和应用程序扩展之间放置组应用程序,并使用与组id对应的Userdefaults
和suiteName
来发送共享实例,但是当我在应用程序扩展中接收到时,地址内存就不一样了,从而创建了对象的另一个实例(我希望在应用程序和应用程序扩展之间有一个真正的独立实例)。我不知道如何在应用程序扩展上节省内存,以及如何在两个框架、应用程序扩展和应用程序之间进行通信,以便在项目的每个部分使用相同的单例。
下面是我的项目的层次结构:
发布于 2020-05-21 08:14:29
但是我的广播上传应用程序扩展占用了太多的内存,在屏幕共享后的X分钟就崩溃了(50 max用于应用程序扩展)。如何在应用程序扩展时使用更少的内存?
避免广播上传扩展中的繁重计算和50 to内存限制的一种方法是在AVAssetWriter
中使用SampleHandler,当它完成时您只需关闭它。之后,您可以使用共享文件夹从AVAssetWriter复制(视频/音频)。
NSURL* url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"your group name"];
NSString* sharedVideoPath = [NSString stringWithFormat:@"%@/video.mp4", url.path];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError* error;
if([fileManager moveItemAtPath:PATH_TO_FILE_FROM_AVASSETWRITER toPath:sharedVideoPath error:&error])
{
NSLog(@"Successfully moved to shared folder!");
}
在此之后,您只需使用NSUserDefaults
告诉主应用程序sharedVideoPath
和主应用程序将能够访问它。
发布于 2021-08-23 20:18:28
如果您只需要将屏幕共享视频保存到“文件”中,这是很容易的。您应该在之间进行通信,该框架使用AVAssetWriter将缓冲区保存到共享容器路径( App )。当广播开始并在Sample上发送缓冲区时,只需在广播停止时将缓冲区传递到AVAssetWriter中,然后使用finishWriting AVAssetWriter完成写入。如果您想了解BroadCastExtension中的视频状态或进程,可以使用日志管理器将日志写入共享容器。例如:
func append(_ sample: CMSampleBuffer, with bufferType: RPSampleBufferType) -> Bool {
guard self.state == .recording else{return false}
guard assetWriter != nil else{return false}
guard sample.isReady else {
LogManager.shared.e(self,"Buffer Data Is not Ready")
return true
}
LogManager.shared.i(self,"Assets Writer Status : \(assetWriter.status.description)")
switch assetWriter.status {
case .failed:
LogManager.shared.e(self,"Error occured, status = \(assetWriter.status), \(assetWriter.error!.localizedDescription) \(String(describing: assetWriter.error))")
return false
default:
break
}
switch bufferType{
case .video:
self.lastVideoTime = sample.time
if let lastSampleBuffer = self.lastSampleBuffer {
videoInput.appendIfPossible(lastSampleBuffer.with(updated: sample.time))
}
case .audioMic:
if self.audioEnabled{
micInput.appendIfPossible(lastVideoTime != nil ? sample.with(updated: lastVideoTime) : sample)
}
case .audioApp:
if self.audioEnabled{
audioInput.appendIfPossible(lastVideoTime != nil ? sample.with(updated: lastVideoTime) : sample)
}
@unknown default:
LogManager.shared.e(self,"Unkown buffer type")
}
return true
}
https://stackoverflow.com/questions/60290757
复制相似问题