Use FFMPEG in XCode(for MacOS)

1. Download FFMPEG binary
Visit https://ffmpeg.org -> Download -> Apple logo -> Download "Static builds for OS X Intel 64-bit". This will contain single ffmpeg binary.


2. Add "ffmpeg" from above as bundle resource


3.  Use Bundle to execute ffmpeg command

func filterVideo(inputFilePath: String, outputFilePath: String,
filterPath: String, callback: @escaping (Bool) -> Void) -> (Process, DispatchWorkItem)? {
guard let launchPath = Bundle.main.path(forResource: "ffmpeg", ofType: "") else {
return nil
}
let process = Process()
let task = DispatchWorkItem {
process.launchPath = launchPath
process.arguments = [
"-y",
"-i", inputFilePath,
"-filter_script:v", filterPath,
outputFilePath
]
process.standardInput = FileHandle.nullDevice
process.launch()
process.terminationHandler = { process in
callback(process.terminationStatus == 0)
}
}
DispatchQueue.global(qos: .userInitiated).async(execute: task)
return (process, task)
}

You can also intercept console output from the process or interrupt the process when problem occurred.

typealias ProcessMeta = (Process, DispatchWorkItem)
typealias ProgressCallback = (String) -> Void
typealias ProcessResult = ([String], [String], Int32)
private func createBundleProcess(bundleName: String, bundleType: String? = nil,
arguments: [String]?, progressCallback: ProgressCallback? = nil,
callback: @escaping (ProcessResult) -> Void) -> ProcessMeta? {
guard let launchPath = Bundle.main.path(forResource: bundleName, ofType: bundleType) else {
return nil
}
let process = Process()
var output : [String] = []
var error : [String] = []
let outpipe = Pipe()
process.standardOutput = outpipe
let errpipe = Pipe()
process.standardError = errpipe
let task = DispatchWorkItem {
process.launchPath = launchPath
process.arguments = arguments
process.standardInput = FileHandle.nullDevice
let errorHandler: (Data) -> Void = { data in
if let str = String(data: data, encoding: .utf8) {
print(str)
if str.contains("Error while decoding stream") {
process.interrupt()
}
}
}
var outdata = Data()
outpipe.fileHandleForReading.readabilityHandler = { handle in
let data = handle.availableData
outdata.append(data)
if let msg = String(data: data, encoding: .utf8) {
progressCallback?(msg)
}
errorHandler(data)
}
var errdata = Data()
errpipe.fileHandleForReading.readabilityHandler = { handle in
let data = handle.availableData
errdata.append(data)
if let msg = String(data: data, encoding: .utf8) {
progressCallback?(msg)
}
errorHandler(data)
}
process.terminationHandler = { process in
if var string = String(data: outdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
output = string.components(separatedBy: "\n")
}
if var string = String(data: errdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
error = string.components(separatedBy: "\n")
}
callback((output, error, process.terminationStatus))
}
process.launch()
process.waitUntilExit()
}
return (process, task)
}


References
- http://stackoverflow.com/a/37422688/2279149

댓글

이 블로그의 인기 게시물

Unity에서 모델의 폴리곤의 반대편이 랜더링 되지 않는 문제 해결 방법

Docker 컨테이너 네트워크 설정시 ifconfig로 docker0를 찾을 수 없는 문제에 대해