2

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.

Xavi Font
  • 296
  • 4
  • 19
  • "I am familiar with the relatively new async and await functionalities". Where is the `Continuation`? This is not `async await` ready. I think you are mixing closures with concurrency which, they are both asynchronous. – lorem ipsum Aug 04 '22 at 20:40

1 Answers1

3

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

de.
  • 7,068
  • 3
  • 40
  • 69
  • Hello, after the bounty I have less than 50 reputation on my other account, so I comment here with this one... I appreciate the effort, I am wondering if you could show me how to call async function that in SwiftUI (this is not an extra ask as it is part of the bounty description :) sorry for the trouble) – Xavi Font Aug 04 '22 at 05:33
  • Hi, I haven't done much swiftui but I assume it will be similar, at function start and in the completion block you set up your @state or similar accordingly. I suggest opening a new question for the specific issue! – de. Aug 06 '22 at 09:07
  • No no! It worked perfectly fine! Thankssss – Xavi Font Aug 09 '22 at 07:06