AVMutableComposition - 仅播放第一曲目(Swift)

时间:2016-05-16 13:31:37

标签: ios swift avplayer avasset avmutablecomposition

我有一个[AVAsset]数组,我试图将所有这些资产组合成一个资产,以便我可以无缝播放视频(我尝试使用AVQueuePlayer,但这不会播放资产无缝地)。

以下是我到目前为止的情况,但是当我尝试播放最终合成时,它只播放第一首曲目,即使它显示它包含所有曲目且总持续时间等于所有曲目。

我是否错过了一个步骤,即使看起来所有曲目都在合成中?如果AVPlayerItem有多个轨道,我可能需要以不同的方式处理AVPlayer吗?

let playerLayer: AVPlayerLayer = AVPlayerLayer()
lazy var videoPlayer: AVPlayer = AVPlayer()

var videoClips = [AVAsset]()

let videoComposition = AVMutableComposition()
var playerItem: AVPlayerItem!
var lastTime: CMTime = kCMTimeZero

for clipIndex in videoClips {

    let videoCompositionTrack = videoComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))

    do {
        try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, clipIndex.duration),
                                                  ofTrack: clipIndex.tracksWithMediaType(AVMediaTypeVideo)[0] ,
                                                  atTime: lastTime)
        lastTime = CMTimeAdd(lastTime, clipIndex.duration)
    } catch {
        print("Failed to insert track")
    }
}
print("VideoComposition Tracks: \(videoComposition.tracks.count)") // Shows multiple tracks

playerItem = AVPlayerItem(asset: videoComposition)
print("PlayerItem Duration: \(playerItem.duration.seconds)") // Shows the duration of all tracks together
print("PlayerItem Tracks: \(playerItem.tracks.count)") // Shows same number of tracks as the VideoComposition Track count

videoPlayer = AVPlayer(playerItem: playerItem)
playerLayer.player = videoPlayer
videoPlayer.volume = 0.0
videoPlayer.play()  // Only plays the first track

1 个答案:

答案 0 :(得分:5)

我能够找到答案最重要的问题。为了将所有剪辑一起播放,它们需要在同一轨道中。为此,请将以下行移到for循环之外(之前):

let playerLayer: AVPlayerLayer = AVPlayerLayer()
lazy var videoPlayer: AVPlayer = AVPlayer()

var videoClips = [AVAsset]()

let videoComposition = AVMutableComposition()
var playerItem: AVPlayerItem!
var lastTime: CMTime = kCMTimeZero

let videoCompositionTrack = videoComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))

for clipIndex in videoClips {

    do {
        try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, clipIndex.duration),
                                                  ofTrack: clipIndex.tracksWithMediaType(AVMediaTypeVideo)[0] ,
                                                  atTime: lastTime)
        lastTime = CMTimeAdd(lastTime, clipIndex.duration)
    } catch {
        print("Failed to insert track")
    }
}
print("VideoComposition Tracks: \(videoComposition.tracks.count)") // Shows multiple tracks

playerItem = AVPlayerItem(asset: videoComposition)
print("PlayerItem Duration: \(playerItem.duration.seconds)") // Shows the duration of all tracks together
print("PlayerItem Tracks: \(playerItem.tracks.count)") // Shows same number of tracks as the VideoComposition Track count

videoPlayer = AVPlayer(playerItem: playerItem)
playerLayer.player = videoPlayer
videoPlayer.volume = 0.0
videoPlayer.play()  // Does play all clips sequentially

以下是完整的更正代码:

using (DefaultSoapClient soapClient = new DefaultSoapClient())
                    {
                        InitializeWebService(soapClient,sAUser,sAPass,vCompany,vBranchID);

                        Shipment shipmentToBeFound = new Shipment
                        {
                            Type = new StringSearch { Value = shipmentType },
                            ShipmentNbr = new StringSearch { Value = shipmentNbr },
                        };
                        Shipment shipment = (Shipment)soapClient.Get(shipmentToBeFound);

                        int iLineNbr =  Int32.Parse(sLineNbr);
                        ShipmentDetail shipmentLine = shipment.Details.Single(
                            orderLineToBeUpdated =>                                
                            orderLineToBeUpdated.LineNbr.Value == iLineNbr);
                            shipmentLine.LocationID = new StringValue { Value = vLocation.Trim() };
                            shipmentLine.ShippedQty = new DecimalValue { Value = decimal.Parse(sOrderedQty) };

                            shipment = (Shipment)soapClient.Put(shipment);

                        soapClient.Logout();

                    }

编辑:我之前提到,我仍然想知道如何在一个资产中播放多个曲目。这不是它的工作方式,我现在明白了。一个很好的资源:

https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html