Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift merge .ts or mpeg files

I have an array of local files, I downloaded them from a .m3u8 playlist, since i have to save for later local playing. All the files are in .ts format, and I want to merge them all in a single video file. I already tried to merge the files using AVMutableComposition, I tried to convert all local files to a AVAsset but the property .tracks always return 0, so i presume the AVAsset was incorrect, then I tried to rename all the files to MPEG but the problem still the same.

Does anyone have any idea on how to, read correctly those files, here is my code so far :

 func mergeAllVideos(filesPath: URL) {
        let allVideos = extractAllFile(atPath: filesPath.absoluteString)
        var arrayVideos = [AVURLAsset]()
        var atTimeM: CMTime = CMTimeMake(0, 0)
        var lastAsset: AVAsset!
        var layerInstructionsArray = [AVVideoCompositionLayerInstruction]()
        var completeTrackDuration: CMTime = CMTimeMake(0, 1)
        var videoSize: CGSize = CGSize(width: 0.0, height: 0.0)
        var totalTime : CMTime = CMTimeMake(0, 0)

        for asset in allVideos.enumerated() {
            if let url = URL(string: asset.element) {

                let newAsset = AVURLAsset(url: url)
                arrayVideos.append(newAsset)
            }
        }

        let mixComposition = AVMutableComposition()
        for videoAsset in arrayVideos {
            let player = AVPlayer(url: videoAsset.url)

            let videoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
            do {
                if videoAsset == arrayVideos.first{
                    atTimeM = kCMTimeZero
                } else{
                    atTimeM = totalTime
                }
                print(videoAsset.tracks)
                try videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0], at: atTimeM)
                videoSize = videoTrack.naturalSize
            } catch let error as NSError {
                print("error: \(error)")
            }

            totalTime = CMTimeAdd(totalTime, videoAsset.duration)

            completeTrackDuration = CMTimeAdd(completeTrackDuration, videoAsset.duration)
            let videoInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
            if let asset = arrayVideos.last, videoAsset != asset {
                videoInstruction.setOpacity(0.0, at: completeTrackDuration)
            }
            layerInstructionsArray.append(videoInstruction)
            lastAsset = videoAsset
        }

        let mainInstruction = AVMutableVideoCompositionInstruction()
        mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, completeTrackDuration)
        mainInstruction.layerInstructions = layerInstructionsArray

        let mainComposition = AVMutableVideoComposition()
        mainComposition.instructions = [mainInstruction]
        mainComposition.frameDuration = CMTimeMake(1, 30)
        mainComposition.renderSize = CGSize(width: videoSize.width, height: videoSize.height)

        let documentDirectory = NSSearchPathForDirectoriesInDomains(.developerApplicationDirectory, .userDomainMask, true)[0]
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .long
        dateFormatter.timeStyle = .short
        let date = dateFormatter.string(from: NSDate() as Date)
        let savePath = (documentDirectory as NSString).appendingPathComponent("mergeVideo-\(date).mov")
        let url = NSURL(fileURLWithPath: savePath)

        let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
        exporter!.outputURL = url as URL
        exporter!.outputFileType = AVFileTypeQuickTimeMovie
        exporter!.shouldOptimizeForNetworkUse = true
        exporter!.videoComposition = mainComposition
        exporter!.exportAsynchronously { 
            print("exported")
        }
    }
like image 502
Vinícius Albino Avatar asked Sep 06 '25 03:09

Vinícius Albino


1 Answers

You can't work with .tsfiles, also renaming of .tv extension to .mp4 will not be enough

You need to translate .tv file to mp4. You can use this lib https://github.com/Keemotion/TS2MP4 for this

And then you will be able to mix videos

like image 179
Taras Chernyshenko Avatar answered Sep 07 '25 21:09

Taras Chernyshenko