我对编码和 Swift 还很陌生。请原谅我无疑笨拙的代码。
我正在尝试使用主资源包中的 ffprobe 运行进程。实际上,我需要运行它两次,每次使用不同的参数,一次是为了获取我输入的音频文件的持续时间,一次是为了获取完整的输出,以便我可以解析它以获取我可以的数据不能像我可以在单个参数中隔离文件持续时间的方式一样。 (我必须执行两次,因为完整输出实际上并未按照我需要的方式列出以秒为单位的持续时间。)
为了避免大量重复代码,我想在一个函数中执行此操作。这就是我所拥有的:
func ffprobeOperations() {
var probeArguments = [String]()
// get full ffprobe output to parse
let probeArguments1 = [
"-hide_banner",
"\(inputFilePath)"]
// get just file duration in seconds
let probeArguments2 = [
"-hide_banner",
"-v",
"0",
"-show_entries",
"format=duration",
"-of",
"compact=p=0:nk=1",
"\(inputFilePath)"]
var probePass: Int = 0
if probePass == 1 {
probeArguments = probeArguments2
} else if probePass == 0 {
probeArguments = probeArguments1
}
guard let launchPath = Bundle.main.path(forResource: "ffprobe", ofType: "") else { return }
do {
let probeTask: Process = Process()
probeTask.launchPath = launchPath
probeTask.arguments = probeArguments
probeTask.standardInput = FileHandle.nullDevice
let pipe = Pipe()
probeTask.standardError = pipe
probeTask.standardOutput = pipe
let outHandle = pipe.fileHandleForReading
outHandle.waitForDataInBackgroundAndNotify()
var obs1 : NSObjectProtocol!
obs1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable,
object: outHandle, queue: nil) { notification -> Void in
let data = outHandle.availableData
if data.count > 0 {
if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
self.ffmpegLogOutput.string += ("\(str)")
let range = NSRange(location:self.ffmpegLogOutput.string.count,length:0)
self.ffmpegLogOutput.scrollRangeToVisible(range)
}
outHandle.waitForDataInBackgroundAndNotify()
} else {
print("EOF on stderr from process")
NotificationCenter.default.removeObserver(obs1!)
}
}
var obs2 : NSObjectProtocol!
obs2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification,
object: probeTask, queue: nil) { notification -> Void in
print("terminated")
NotificationCenter.default.removeObserver(obs2!)
}
probeTask.launch()
probeTask.waitUntilExit()
probePass += 1
}
}
但是无论我将 probePass += 1
放在函数中的哪个位置,XCode 仍然会警告我条件 probePass == 1
永远不会成立,因此带有第二组参数的传递将永远不会被执行。
我应该在哪里放置 probePass += 1
,或者有更好的方法来完成此操作吗?
最佳答案
变量probePass的范围只是函数ffProbeOptions,因为它是在那里创建的。这意味着一旦 ffProbeOptions 完成运行,该变量将被取消初始化。尝试在函数外部定义probePass,这样它就有更大的作用域。这样,每次函数完成时变量都不会被销毁,并且它将跟踪其值(例如 0 或 1)。
像这样:
var probePass = 0
func ffprobeOperations() {
var probeArguments = [String]()
// get full ffprobe output to parse
let probeArguments1 = [
"-hide_banner",
"\(inputFilePath)"]
// get just file duration in seconds
let probeArguments2 = [
"-hide_banner",
"-v",
"0",
"-show_entries",
"format=duration",
"-of",
"compact=p=0:nk=1",
"\(inputFilePath)"]
if probePass == 1 {
probeArguments = probeArguments2
} else if probePass == 0 {
probeArguments = probeArguments1
}
guard let launchPath = Bundle.main.path(forResource: "ffprobe", ofType: "") else { return }
do {
let probeTask: Process = Process()
probeTask.launchPath = launchPath
probeTask.arguments = probeArguments
probeTask.standardInput = FileHandle.nullDevice
let pipe = Pipe()
probeTask.standardError = pipe
probeTask.standardOutput = pipe
let outHandle = pipe.fileHandleForReading
outHandle.waitForDataInBackgroundAndNotify()
var obs1 : NSObjectProtocol!
obs1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable,
object: outHandle, queue: nil) { notification -> Void in
let data = outHandle.availableData
if data.count > 0 {
if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
self.ffmpegLogOutput.string += ("\(str)")
let range = NSRange(location:self.ffmpegLogOutput.string.count,length:0)
self.ffmpegLogOutput.scrollRangeToVisible(range)
}
outHandle.waitForDataInBackgroundAndNotify()
} else {
print("EOF on stderr from process")
NotificationCenter.default.removeObserver(obs1!)
}
}
var obs2 : NSObjectProtocol!
obs2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification,
object: probeTask, queue: nil) { notification -> Void in
print("terminated")
NotificationCenter.default.removeObserver(obs2!)
}
probeTask.launch()
probeTask.waitUntilExit()
probePass += 1
}
}
也许实现目标的更优雅的方法是定义一个probeArguments 列表:
let probeArgumentList: [[String]] = [
[
"-hide_banner",
"\(inputFilePath)"
],
[
"-hide_banner",
"-v",
"0",
"-show_entries",
"format=duration",
"-of",
"compact=p=0:nk=1",
"\(inputFilePath)"
]
]
然后循环列表
for probeArguments in probeArgumentList {
## Perform operation
}
关于swift - 每次使用不同的参数重复过程两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58599902/