重复两次,每次使用不同的参数

时间:2019-10-29 00:07:06

标签: swift ffmpeg ffprobe

我对编码和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,还是有更好的方法呢?

1 个答案:

答案 0 :(得分:0)

变量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
}