Swift - Workaround替代M3u8播放mp4片段或将片段合并成mp4。

问题描述 投票:0回答:1

我用的是 AVAssetExportSession 来下载会话URL,但是不能下载直播的问题,所以为了解决这个问题,将直播分成10秒的mp4段,使用m3u8下载来创建URL。然后,我使用 AVAssetExportSession 合并这些mp4片段。

我可以将这些剪辑一个一个合并成一个mp4文件,这是我想要的,但随着文件越来越大,需要更长的时间,因为我处理成千上万的片段,这变得不切实际。

我想过使用 AVplayerLooper 但我不能像单个视频一样,通过mp4片段擦洗、倒带或转发。

有没有办法将mp4片段组合在一起,作为一个视频播放,如m3u8不合并? 或者有一个快速的方法来合并视频?

注意事项:请问有什么方法可以将mp4片段合并成一个视频播放?: 服务器使用FFmpeg,但我不允许在应用程序中使用FFmpeg或pods。

以下是合并视频的功能

var mp4Array: [AVAsset] = []
var avAssetExportSession: AVAssetExportSession?

var firstAsset: AVAsset?
var secondAsset: AVAsset?

func mergeVideos() {

    firstAsset = mp4Array.first
    secondAsset = mp4Array[1]

    guard let firstAsset = firstAsset, let secondAsset = secondAsset else { return }
    let mixComposition = AVMutableComposition()

    guard let firstTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}

    do {

        try firstTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration),
                                       of: firstAsset.tracks(withMediaType: .video)[0],
                                       at: CMTime.zero)

    } catch {
        print("Couldn't load track 1")
        return
    }

    guard let secondTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}

    do {
        try secondTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: secondAsset.duration),
                                        of: secondAsset.tracks(withMediaType: .video)[0],
                                        at: firstAsset.duration)
    } catch {
        print("couldn't load track 2")
        return
    }

    let mainInstruction = AVMutableVideoCompositionInstruction()
    mainInstruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: CMTimeAdd(firstAsset.duration, secondAsset.duration))

    let firstAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack)
    firstAssetInstruction.setOpacity(0.0, at: firstAsset.duration)

    let secondAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: secondTrack)

    mainInstruction.layerInstructions = [firstAssetInstruction, secondAssetInstruction]
    let mainComposition = AVMutableVideoComposition()
    mainComposition.instructions = [mainInstruction]
    mainComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
    mainComposition.renderSize = firstTrack.naturalSize

    guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
    let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo\(videoInt).mp4")

    guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {return}

    exporter.outputURL = url
    exporter.outputFileType = AVFileType.mp4
    exporter.shouldOptimizeForNetworkUse = true
    exporter.videoComposition = mainComposition

    exporter.exportAsynchronously {

        if exporter.status == .completed {
            let avasset = AVAsset(url:url)
            self.mergeUrl = avasset
            if self.mp4Array.count > 1{
                print("This add the merged video to the front of the mp4array")
                self.mp4Array.remove(at: 1)
                self.mp4Array.removeFirst()
                self.videoInt = self.videoInt + 1
                self.mp4Array.append(self.mergeUrl!)
                self.mp4Array.bringToFront(item: self.mp4Array.last!)
            }

            if (self.mp4Array.count > 1){
                if self.mergeUrl != nil {
                    self.mergeVideos()
                }
            } else {
                var numberofvideosdeleted = 0
                while (numberofvideosdeleted < self.videoInt - 1){
                    do {
                        print("deleting")
                        let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo\(numberofvideosdeleted).mp4")
                        try FileManager.default.removeItem(at: url)
                        numberofvideosdeleted = numberofvideosdeleted + 1
                    } catch {
                        print("Error removing videos")
                    }
                }

                self.deleteCurrentSegementsInFolder()
            }
        }
    }
}
ios swift ffmpeg avplayer m3u8
1个回答
0
投票

我最后用FFmpeg Mobile来连缀视频,效果非常好。花了大约1分钟的时间来拼接一个3GB的电影文件。

下面链接到cocoapod。https:/github.comtanersenermobile-ffmpeg。

© www.soinside.com 2019 - 2024. All rights reserved.