Earlier I asked a question regarding generateCGImagesAsynchronously
. Thankfully it got answered and works great.
The issue is that it only works as a Cocoa app on xcode. I am now trying to move this logic to an executable Swift package but AVFoundation
code, such as generateCGImagesAsynchronously
, won't work. That is, no error is raised but those functions seem to be mocked. I presume this might have to do with my package being sandboxed? I was able to remove the sandbox from the Cocoa app I previously wrote the code for, but I can't figure out how to do that for this executable.
I am new to Swift and trying to understand it and it's kind of frustrating to think that what I want my code to do is dependent on the IDE I am using.
If anyone can point me in the direction of where to read in the docs, or some other sources, on how to make programs without using xcode, that would be great. Thanks!
Here is my code:
import Darwin
import Foundation
import AppKit
import AVFoundation
import Cocoa
@discardableResult func writeCGImage(
_ image: CGImage,
to destinationURL: URL
) -> Bool {
guard let destination = CGImageDestinationCreateWithURL(
destinationURL as CFURL,
kUTTypePNG,
1,
nil
) else { return false }
CGImageDestinationAddImage(destination, image, nil)
return CGImageDestinationFinalize(destination)
}
func imageGenCompletionHandler(
requestedTime: CMTime,
image: CGImage?,
actualTime: CMTime,
result: AVAssetImageGenerator.Result,
error: Error?
) {
guard let image = image else { return }
let path = saveToPath.appendingPathComponent(
"img(actualTime).png"
)
writeCGImage(image, to: path)
}
let arguments: [String] = Array(CommandLine.arguments.dropFirst())
// For now, we assume the second arg, which is the
// path that the user wants us to save to, always exists.
let saveToPath = URL(fileURLWithPath: arguments[1], isDirectory: true)
let vidURL = URL(fileURLWithPath: arguments[0])
let vidAsset = AVAsset(url: vidURL)
let vidDuration = vidAsset.duration
let imageGen = AVAssetImageGenerator(asset: vidAsset)
var frameForTimes = [NSValue]()
let sampleCounts = 20
let totalTimeLength = Int(truncatingIfNeeded: vidDuration.value as Int64)
let steps = totalTimeLength / sampleCounts
for sampleCount in 0 ..< sampleCounts {
let cmTime = CMTimeMake(
value: Int64(sampleCount * steps),
timescale: Int32(vidDuration.timescale)
)
frameForTimes.append(NSValue(time: cmTime))
}
imageGen.generateCGImagesAsynchronously(
forTimes: frameForTimes,
completionHandler: imageGenCompletionHandler
)
question from:
https://stackoverflow.com/questions/65878304/how-to-remove-sandbox-without-xcode 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…