STerrier
STerrier

Reputation: 4015

FFmpeg - How to concatenate video from images without losing quality

I am concatenating images into a video using mobileffmpeg cocoapod using the command below but the video quality drops a bit when it has finished concatenating.

-f concat -i \(outputTxt) -b:v 8M -pattern_type sequence -r 25 \(output)

I can see the image array isn't the issue as the quality is good so how can I avoid losing quality when concatenating? I thought maybe using libx264 would solve the issue but it isn't supported by mobileffmpeg

Below are the functions I use in Swift to concatenate if it helps understand the process. Thanks for your help!

func concatonateScreenshotsToVideo( completed: @escaping (URL) -> ()){
    if compilingVideo {
        self.delegate?.screenRecordingConcatonating()

            var imgs = self.storedTempScreenshotImgArray()
            imgs.sort()
            
            self.createFFmpegTextFile(tempScreenshotImgArray: imgs) {
                let filename = "screenshot_ffmpegData.txt"
                let outputTxt = URL(fileURLWithPath: self.mainPath + "/Temp/").appendingPathComponent(filename)
                let output = URL(fileURLWithPath: self.mainPath + "/Temp/").appendingPathComponent("screenshot.mp4")
                
                let ffmpeg =  "-f concat -i \(outputTxt) -b:v 8M -pattern_type sequence -r \(self.fps) \(output)"
                
                MobileFFmpeg.execute(ffmpeg)
                completed(output)
            }
    } else {
        terminateFFmpeg()
        return
    }
}

func createFFmpegTextFile(tempScreenshotImgArray: [String], completed: () -> Void){
    let filename = "screenshot_ffmpegData.txt"
    let textFile = URL(fileURLWithPath: mainPath).appendingPathComponent("Temp/\(filename)")
    
    for img in tempScreenshotImgArray {
        autoreleasepool {
            do {
                let fileHandle = try FileHandle(forWritingTo: textFile)
                fileHandle.seekToEndOfFile()
                
                let filepath = "file \(img)\n duration 0.04\n"
                fileHandle.write(filepath.data(using: .utf8)!)
                
            } catch {
                do {
                    let filePath = "file \(img)\n duration 0.04\n"
                    try filePath.write(to: textFile, atomically: false, encoding: .utf8)
                } catch {
                    DebugPrint.DBprint("FFmpeg manager error writing text file: \(error.localizedDescription)")
                }
            }
        }
    }

func storedTempScreenshotImgArray() -> [String] {
    var screenshotImgArray: [String] = []
    
    guard let dataFilePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("/Temp") else {return screenshotImgArray}
    
    do {
        let fileUrls = try fileManager.contentsOfDirectory(at: dataFilePath, includingPropertiesForKeys: nil)
        for jpgFile in fileUrls {
            if jpgFile.pathExtension == "jpg" && !screenshotImgArray.contains(jpgFile.lastPathComponent) {
                screenshotImgArray.append(jpgFile.lastPathComponent)
            }
        }
    } catch {
        DebugPrint.DBprint("screenshot - Error while enumerating folder segment")
    }
    
    return screenshotImgArray
    
}

Upvotes: 0

Views: 406

Answers (1)

Amin Rezaew
Amin Rezaew

Reputation: 338

use :

pod 'mobile-ffmpeg-full-gpl'

that support's x264 and x265

in here you can read about mobile ffmpeg versions

for using in swift you should add ProjectName-Bridging-Header.h to your project and then import the library in that: #import <mobileffmpeg/MobileFFmpeg.h>

Upvotes: 1

Related Questions