【问题标题】:Weird behaviour of AVMutableComposition freezing while using AVMutableVideoComposition使用 AVMutableVideoComposition 时 AVMutableComposition 冻结的奇怪行为
【发布时间】:2015-07-14 09:23:18
【问题描述】:

我正在尝试使用 AVMutableComposition 合并多个视频。我面临的问题是,每当我尝试添加任何AVMutableVideoComposition 以应用任何指令时,我的播放都会在AVPlayer 中以精确的6 秒持续时间冻结。

另一个有趣的事情是,如果我在使用相同的videoComposition 导出后在 iPad 的照片应用程序中播放它,它可以正常播放。那么为什么它会在 6 秒时冻结在 AVPlayer 中?

代码:

AVMutableComposition *mutableComposition = [AVMutableComposition composition];

    AVMutableCompositionTrack *videoCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];

    AVMutableCompositionTrack *audioCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                                       preferredTrackID:kCMPersistentTrackID_Invalid];

    for (AVURLAsset *asset in assets)
    {
            AVAssetTrack *assetTrack;
            assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
            AVAssetTrack *audioAssetTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;


            NSError *error;
            [videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, assetTrack.timeRange.duration )
                                                   ofTrack:assetTrack
                                                    atTime:time
                                                     error:&error];

            if (error) {
                NSLog(@"asset url :: %@",assetTrack.asset);
                NSLog(@"Error1 - %@", error.debugDescription);
            }

            [audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAssetTrack.timeRange.duration)
                                               ofTrack:audioAssetTrack
                                                atTime:time
                                                 error:&error];

            if (error) {
                NSLog(@"Error2 - %@", error.debugDescription);
            }

            time = CMTimeAdd(time, assetTrack.timeRange.duration);

            if (CGSizeEqualToSize(size, CGSizeZero)) {
                size = assetTrack.naturalSize;;
            }
        }

        AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        AVMutableVideoCompositionLayerInstruction *videoTrackLayerInstruction =  [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoCompositionTrack];

        mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, time);
        mainInstruction.layerInstructions = [NSArray arrayWithObjects:videoTrackLayerInstruction, nil];
        AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
        mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
        mainCompositionInst.frameDuration = CMTimeMake(1, 30);
        mainCompositionInst.renderSize = size;

        pi = [AVPlayerItem playerItemWithAsset:mutableComposition];
        pi.videoComposition = mainCompositionInst;

另外,我知道问题主要出在videoComposition,因为如果我删除videoComposition,那么它在AVPlayer 上运行良好。

更新 1:我刚刚发现,当它在 6 秒后冻结时,如果我向后或向前拖动滑块(即使用 seekToTime),它会再次开始正常播放而不会进一步冻结.

即使视频冻结,音频也能正常播放。

更新 2:如果我继续使用 AVAssetExportSession 和相同的 AVMutableComposition 导出它,并从导出的视频中加载资产,它工作正常。所以就在我直接玩AVMutableComposition的时候,问题就来了。

【问题讨论】:

  • 我遇到了同样的问题,运气好吗?
  • 再次;这仍然会发生。有人可以在这里做出反应吗?
  • @Julian 目前无法解决这个问题。最终解决了导出它,这涉及等待。提供赏金后也没有注意问题。继续投票并希望有人最终注意到它。
  • @Julian 请检查我的答案。
  • 我刚刚解决了这个问题,就像 30 分钟前一样,谢谢。我实际上有一个不同的问题。我为资产轨道而不是作曲轨道创建了说明......愚蠢的一个,但我仍然花了大约 3 周的时间来找到正确的组合

标签: ios objective-c video avfoundation avmutablecomposition


【解决方案1】:

最后,我找到了解决此问题的解决方案。

您应该在 playerItem 的状态更改为 .ReadyToPlay 后播放。

请看下面。

func startVideoPlayer() {
    let playerItem = AVPlayerItem(asset: self.composition!)
    playerItem.videoComposition = self.videoComposition!

    let player = AVPlayer(playerItem: playerItem)
    player.actionAtItemEnd = .None

    videoPlayerLayer = AVPlayerLayer(player: player)
    videoPlayerLayer!.frame = self.bounds

    /* add playerItem's observer */
    player.addObserver(self, forKeyPath: "player.currentItem.status", options: .New, context: nil)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerItemDidReachEnd:", name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem);

    self.layer.addSublayer(videoPlayerLayer!)
}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath != nil && keyPath! == "player.currentItem.status" {
        if let newValue = change?[NSKeyValueChangeNewKey] {
            if AVPlayerStatus(rawValue: newValue as! Int) == .ReadyToPlay {
                playVideo() /* play after status is changed to .ReadyToPlay */
            }
        }
    } else {
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
    }
}    

func playerItemDidReachEnd(notification: NSNotification) {
    let playerItem = notification.object as! AVPlayerItem
    playerItem.seekToTime(kCMTimeZero)

    playVideo()
} 

func playVideo() {
    videoPlayerLayer?.player!.play()
}       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-06
    • 2017-05-03
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    相关资源
    最近更新 更多