precise timing with AVMutableComposition

泄露秘密 提交于 2019-12-05 06:13:47
Insomniac Software

Your CMTimeMakeWithSeconds(t, 1) is in whole second 'slices' because your timescale is set to 1. No matter what fraction t is, the atTime: will always end up as 0. This is why it works when you increase it to 1 second (t=i*1).

You need to set the timescale to 4 to get your desired 0.25 second slices. Since the CMTime is now in .25 second slices, you won't need the i * 0.25 calculcation. Just use the i directly; atTime:CMTimeMake(i, 4)

If you might need to get more precise in the future, you should account for it now so you won't have to adjust your code later. Apple recommends using a timescale of 600 as it is a multiple of the common video framerates (24, 25, and 30 FPS) but it works fine for audio-only too. So for your situation, you would use 24 slices to get your .25 second value; Float64 t = i * 24; atTime:CMTimeMake(t, 600)

As for your issue of all 4 sounds playing almost all at once, be aware of this unanswered SO question where it only happens on the first play. Even with the changes above, you might still run into this issue.

Unless each track is exactly 0.25 seconds long this is your problem:

Float64 t = i * 0.25;
NSError *error;
BOOL success = [track insertTimeRange:timeRange ofTrack:assetTrack atTime:CMTimeMakeWithSeconds(t, 1) error:&error];

You need to be keeping track of the cumulative time range added so far, and inserting the next track at that time:

CMTime currentTime = kCMTimeZero;

for (NSInteger i = 0; i < 4; i++) {

   /* Code to create track for insertion */

    CMTimeRange trackTimeRange = [assetTrack timeRange];

    BOOL success = [track insertTimeRange:trackTimeRange
                                  ofTrack:assetTrack 
                                    atTime:currentTime
                                      error:&error];

    /* Error checking code */

    //Update time range for insertion
    currentTime = CMTimeAdd(currentTime,trackTimeRange.duration);
}

i changed a bit your code, sorry i had no time to test it.

   AVMutableComposition *composition = [AVMutableComposition composition];
    NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey : @YES};

    CMTime totalDuration = kCMTimeZero;

    for (NSInteger i = 0; i < 4; i++)
    {
        AVMutableCompositionTrack* track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];


        NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Record_%i", i] ofType:@"caf"]];
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:options];
        AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
        CMTimeRange timeRange = [assetTrack timeRange];
        NSError *error;

        BOOL success = [track insertTimeRange:timeRange ofTrack:assetTrack atTime:CMTIME_COMPARE_INLINE(totalDuration, >, kCMTimeZero)? CMTimeAdd(totalDuration, CMTimeMake(1, 4)): totalDuration error:&error];

        if (!success)
        {
            NSLog(@"unsuccesful creation of composition");
        }
        if (error)
        {
            NSLog(@"composition creation error: %@", error);
        }
        totalDuration = CMTimeAdd(CMTimeAdd(totalDuration,CMTimeMake(1, 4)), asset.duration);
    }

    AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:composition];
    self.avPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];

P.S. use kCMTimeZero instead of CMTimeMakeWithSeconds(0, 1).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!