2

I have been browsing the web, even this website... bu cannot find a good option to implement ffmpeg functionality in an iOS application made in swift.

Options looked at and reasons why they are not solutions:

SwiftFFmpeg - I am not sure it can run on iOS, plus I don't see an option to run my desired Ffmpeg command.

MobileFFmpeg - Not maintained anymore, and a new project by the same founders created a "better altenrative" called ffmpeg-kit.

ffmpeg-kit - looks amazing, but their API only allows for interaction in the Objective-C language.

Any solutions anyone can give me?

Xavi Font
  • 296
  • 4
  • 19
  • 2
    I’ve used used mobile-ffmpeg (now ffmpeg-kit) through Swift, just because it’s written in objc doesn’t mean it’s not availability to swift – MadProgrammer Jun 18 '22 at 21:48
  • @MadProgrammer I just started using swift, I normally just take a pckage github link and paste on xcode, it imports it for me... https://github.com/tanersener/ffmpeg-kit/tree/main/apple is full of instructions on how to use it in Objective-C... I have no clue of how to import the package for use in my project... worst of all, Googling "ffmpeg-kit swift ios" gives me zero relevant results. Any advice? – Xavi Font Jun 18 '22 at 22:02
  • 1
    Including ffmpeg into your project is ... a lot of head aches. ffmpeg-kit basically exposes the command line functionality of ffmpeg to you application, it's not meant for "playing" media. There are a few projects around which will do that, but they become even more complex to interact with, so the question is, what do you want to achieve? – MadProgrammer Jun 18 '22 at 22:17
  • @MadProgrammer there is nothing more that I want than exactly just that. I want to interact with the command line functionality of Ffmpeg in swift... I want to take a video from a user and change the codec. – Xavi Font Jun 18 '22 at 22:23
  • @MadProgrammer hey, I have a related question I believe you can help me with... https://stackoverflow.com/questions/72681878/ffmpeg-kit-not-detecting-my-vidoe-file-ios-development-swift-but-the-actual-a – Xavi Font Jun 20 '22 at 03:15

1 Answers1

7

First...

Make sure you understand what "packages" are available. You can build it yourself, but to be honest, unless you have a very specific reason, I'd just use the pre-build packages. See "8. Packages" of the ffmpeg-kit README.MD to see what's on offer

Second

Go to the Releases and find the version you're interested (I used FFmpegKit Native v4.5.1), scroll down and expand the "Assets" list for the release you're interested in.

For this experiment I used ffmpeg-kit-full-4.5.1-macos-xcframework.zip. If you're doing this in iOS, the workflow is basically the same, you just need to take into account that your file access is sandboxed (and yes, I've done this, and yes, it takes a long time to transcode video, compared to a desktop)

Third

Create a new Xcode project. Again, for this experiment, I created a "MacOS App" using "Storyboards" as the UI (you could try using SwiftUI, but that's another layer of complexity this example didn't need right now)

  • Unzip the *xcframework.zip file you download from the last step.
  • In Xcode, select the "project" node, select the MacOS target ( there's only one target).
  • Select "General", drag the *.xcframework folders from Finder to the "Frameworks, Libraries and Embedded Content" section of your project

enter image description here

Forth

For this experiment, I opened the ViewController class (which was automatically created by Xcode) and simply added...

func syncCommand() {
    guard let session = FFmpegKit.execute("-i file1.mp4 -c:v file2.mp4") else {
        print("!! Failed to create session")
        return
    }
    let returnCode = session.getReturnCode()
    if ReturnCode.isSuccess(returnCode) {
        
    } else if ReturnCode.isCancel(returnCode) {
        
    } else {
        print("Command failed with state \(FFmpegKitConfig.sessionState(toString: session.getState()) ?? "Unknown") and rc \(returnCode?.description ?? "Unknown").\(session.getFailStackTrace() ?? "Unknown")")
    }
}

func asyncCommand() {
    FFmpegKit.executeAsync("-i file1.mp4 -c:v file2.mp4") { 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 let logs = logs else { return }
        // CALLED WHEN SESSION PRINTS LOGS
    } withStatisticsCallback: { stats in
        guard let stats = stats else { return }
        // CALLED WHEN SESSION GENERATES STATISTICS
    }

}

The code above is basically the "2. Execute synchronous FFmpeg commands." and "4. Execute asynchronous FFmpeg commands by providing session specific execute/log/session callbacks." examples from the ffmpeg-kit/apple documentation

!! Important !! - don't forget to add import ffmpegkit to the start of the file!

At this point, this should now compile (you'll get a couple of warnings about logs and stats not been used, you can ignore those).

After thoughts...

You should realise by now that the code I've provided won't actually run, for two reasons.

  1. I've not actually called either func from anywhere (I tested it by placing it in the viewDidLoad func of the ViewController class)
  2. The input file, used in the execute command, doesn't exist. You will need to provide an actual reference to an actual file, preferably with an absolute path. This, how ever, may require you to change the "App Sandbox" settings under the targets "Signing and Capabilities"
  3. Xcodes auto code suggestions aren't bad and I mostly filled out the above using it, and the Obj-c code as a starting point.

Also, beware, SO is not a "tutorial" site, Xcode is a complex beast and you may need to spend some time exploring other resources to overcome issues you encounter

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Works perfectly! iOS, MacOS, what not. Also, I could not thank you enough for the elavorate and detailed answer, I can see you put a fair amount of time on it. – Xavi Font Jun 18 '22 at 23:36
  • 1
    Hey @MadProgrammer, not sure if I am allowed to do this but if I am not just let me know and I will remove this comment. I was thinking not many people have your skills, mind taking a look at this? https://stackoverflow.com/questions/73073953/ffmpeg-kit-ios-async-call-not-behaving-asynchronously (I commented with this account because it has enough points to do so, I lost so many points already lol) – Xavi Font Jul 23 '22 at 01:48
  • In your code example, I assume it should be guard let session = FFmpegKit.execute("-i file1.mp4 -c:v file2.mp4") // <– "file2" ? – de. Aug 02 '22 at 22:20
  • @de Hay, if that works for you – MadProgrammer Aug 02 '22 at 22:49
  • Actually it doesn't =) I had to provide a full path to the input file in the bundle and output in documents dir. Also -c:v caused errors. Just trying to get the basics done here. – de. Aug 02 '22 at 23:02
  • 1
    @de - Yes "*2. The input file, used in the execute command, doesn't exist. You will need to provide an actual reference to an actual file, preferably with an absolute path. This, how ever, may require you to change the "App Sandbox" settings under the targets "Signing and Capabilities""* – MadProgrammer Aug 02 '22 at 23:04
  • 1
    @de. Remember, this answer is taking the Objc examples from the original github samples and converting them to Swift ;) – MadProgrammer Aug 02 '22 at 23:05
  • wonderful explanation!! appreciate – Rashesh Bosamiya Feb 06 '23 at 07:10
  • When I attempted to add a blur effect to a specific area of video, I encountered an error: "No such filter: Boxblur." It appears that this filter is under license, so I am wondering if there is any way to bypass this error. – Rashesh Bosamiya Mar 03 '23 at 05:49