0

我正在尝试从静止图像制作电影,为此我使用带有自定义指令的自定义合成器。实际上我得到电影并且长度符合预期,但在一帧(5秒)后我得到黑屏(对于另一帧)

我所做的是在我的演示项目中:

https://github.com/satishVekariya/MovideMakerDemo

class StoryComposer {
    var slide:[ImageResource] = []
    
    init() {
    }
    
    private var needRebuildComposition = true
    private var needRebuildVideoComposition = true
    
    private(set) var composition: AVMutableComposition?
    private(set) var videoComposition: AVMutableVideoComposition?
    
    private(set) var addedTrackIds:[CMPersistentTrackID] = []
}
    

extension StoryComposer {
    func composeForAVPlayerItem() -> (AVPlayerItem, AVMutableComposition, AVMutableVideoComposition) {
        let composition = compose()
        let playerItem = AVPlayerItem(asset: composition)
        let video = composeVideoComposition()
        playerItem.videoComposition = video
        return (playerItem, composition, video!)
    }
}

extension StoryComposer {
    
 
    
    @discardableResult func compose() -> AVMutableComposition {
        if let oldComposition = self.composition, !needRebuildComposition {
            return oldComposition
        }
                
        let composition = AVMutableComposition(urlAssetInitializationOptions: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
        
        var startTime = CMTime(seconds: 0, preferredTimescale: 1)
        for (_, item) in slide.enumerated() {
            
            let track = slide.first!.trackInfo(for: .video, at: 0).track
            let emptyVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
            if let id = emptyVideoTrack?.trackID {
                addedTrackIds.append(id)
            }
            do {
                emptyVideoTrack?.removeTimeRange(CMTimeRange(start: startTime, duration: item.duration))
                try emptyVideoTrack?.insertTimeRange(CMTimeRangeMake(start: startTime, duration: CMTime(seconds: 1, preferredTimescale: 30)), of: track, at: startTime)
                emptyVideoTrack?.scaleTimeRange(CMTimeRange(start: startTime, duration: CMTime(seconds: 1, preferredTimescale: 30)), toDuration: item.duration)
            } catch {
                print("\(Self.self) : \(#function) error - \(error)")
            }
            startTime = CMTimeAdd(startTime, item.duration)
        }
        
        self.composition = composition
        return composition
    }
}

extension StoryComposer {
    public func composeVideoComposition() -> AVMutableVideoComposition? {
        if let videoComposition = self.videoComposition, !needRebuildVideoComposition {
            return videoComposition
        }
        compose()
        var videoCompositionInstruction = [VideoCompositionInstruction]()
        var startTime = CMTime(seconds: 0, preferredTimescale: 1)
        for (index, item) in slide.enumerated() {
            let trackId:CMPersistentTrackID = Int32(index) + 1
            let layerInstr = VideoCompositionLayerInstruction(trackID: trackId)
            layerInstr.resource = item
            
            let instr = VideoCompositionInstruction(theSourceTrackIDs: [layerInstr.trackID as NSValue], forTimeRange: CMTimeRangeMake(start: startTime, duration: item.duration))
            instr.layerInstructions = [layerInstr]
            videoCompositionInstruction.append(instr)
            startTime = CMTimeAdd(startTime, item.duration)
        }
        
        
        let videoComposition = AVMutableVideoComposition()
        videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
        videoComposition.customVideoCompositorClass = VideoCompositor.self
        videoComposition.instructions = videoCompositionInstruction
        videoComposition.renderSize = CGSize(width: 480, height: 480)
        self.videoComposition = videoComposition
        
        return videoComposition
    }
    
    
}

4

1 回答 1

2

这行代码的问题:

try emptyVideoTrack?.insertTimeRange(CMTimeRangeMake(start: startTime, duration: CMTime(seconds: 1, preferredTimescale: 30)), of: track, at: startTime)

在您的情况下timeRange应该从零开始,因此更改为以下代码:

try emptyVideoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: CMTime(seconds: 1, preferredTimescale: 30)), of: track, at: startTime) 

insertTimeRange在函数中检查文档

@param timeRange - 指定要插入的轨道的 timeRange。

“要插入的轨道的时间范围”是指要插入轨道的时间范围。

于 2020-07-06T17:47:09.477 回答