FFMPEG Kit iOS Async Call Not Behaving Asynchronously

860 Views Asked by At

When I call the executeAsync method of FFmpegKit I expect asynchronous behaviour, but instead the code is ran but never waits for the FFmpegKit.executeAsync to run, therefore, the program output comes from print("FFmpeg process exited with state \(FFmpegKitConfig.sessionState(toString: session.getState()) ?? "Unknown") and rc \(returnCode).\(session.getFailStackTrace() ?? "Unknown")") (seen in the code below) which by the way, is instantly outputted... to make sure I checked the output file path and no file had been saved there, meaning the FFMPEG command did not actually execute.

guard let outputPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return }
                    let output = outputPath.appendingPathComponent("file1.mp4")
                    FFmpegKit.executeAsync("-i http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4 -c:v \(output.path)") { session in
                        guard let session = session else {
                            print("!! Invalid session")
                            return
                        }
                        guard let returnCode = session.getReturnCode() else {
                            print("!! Invalid return code")
                            return
                        }
                        print("FFmpeg process exited with state \(FFmpegKitConfig.sessionState(toString: session.getState()) ?? "Unknown") and rc \(returnCode).\(session.getFailStackTrace() ?? "Unknown")")
                    } withLogCallback: { logs in
                        guard logs != nil else { return }
                        // CALLED WHEN SESSION PRINTS LOGS
                    } withStatisticsCallback: { stats in
                        guard stats != nil else { return }
                        // CALLED WHEN SESSION GENERATES STATISTICS
                    }

If I try to await for the FFmpegKit.executeAsync by the way, I get a No 'async' operations occur within 'await' expression warning, which should be happening because that method is not asynchronous.

In case you wanted to replicate this, the code posted does not depend on anything other than the dependency which can be downloaded through the GitHub repo download link

If you wanted extra info on how to get install the dependency click here

Question Why is my asynchronous FFMPEG method running and exiting right away, without executing the FFMPEG command I passed?

I am familiar with the relatively new async and await functionalities and therefore I am treating this that way, I am encapsulating the code above in an asynchronous function which I am awaiting when called.

1

There are 1 best solutions below

3
de. On

I replicated your code. It works just fine if you remove the options "-c:v" that come form the original example you mentioned. I don't know what they do but you probably want to add some other arguments there anyway.

Also remember to go back to the main thread in the completion block if you want to update your UI.

This is my complete code:

import UIKit
import ffmpegkit

class ViewController: UIViewController {
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.asyncCommand()
    }
    
    func asyncCommand() {
        self.view.backgroundColor = .orange
        guard let outputPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return }
        let output = outputPath.appendingPathComponent("file1.mp4")
        try? FileManager.default.removeItem(at: output)
        FFmpegKit.executeAsync("-i http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4  \(output.path)") { session in
            guard let session = session else {
                print("!! Invalid session")
                return
            }
            guard let returnCode = session.getReturnCode() else {
                print("!! Invalid return code")
                return
            }
            print("FFmpeg process exited with state \(FFmpegKitConfig.sessionState(toString: session.getState()) ?? "Unknown") and rc \(returnCode).\(session.getFailStackTrace() ?? "Unknown")")

            DispatchQueue.main.async {
                if ReturnCode.isSuccess(returnCode) {
                    self.view.backgroundColor = .green
                } else {
                    self.view.backgroundColor = .red
                }
            }
        } withLogCallback: { logs in
            guard logs != nil else { return }
            // CALLED WHEN SESSION PRINTS LOGS
        } withStatisticsCallback: { stats in
            guard stats != nil else { return }
            // CALLED WHEN SESSION GENERATES STATISTICS
        }
    }
}